/* ============================================================
   BASE — reset, document, editorial typography primitives
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html {
  -webkit-text-size-adjust: 100%;
  /* Taps fire immediately: no waiting to see if it's a double-tap zoom. */
  touch-action: manipulation;
  scroll-behavior: smooth;
  scroll-padding-top: 96px;
}

body {
  background-color: var(--ground);
  background-image: var(--ground-wash);
  background-attachment: fixed;
  background-repeat: no-repeat;
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.6;
  letter-spacing: -.011em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  text-rendering: optimizeLegibility;
}
body.is-locked { overflow: hidden; height: 100%; }

/* ── Paper ──────────────────────────────────────────────────
   The stone texture, laid under everything as the page ground.

   TILED, not stretched: the source is smaller than a desktop
   viewport, so `cover` would upscale it into mush. Repeating it
   at native scale keeps every bit of the grain sharp.

   `paper-tile.jpg` is a mirrored 2x2 block built from the source
   photograph, so its edges match on all four sides and it repeats
   with no seam anywhere.

   Only the file that actually exists is listed. A second URL as a
   "fallback" does not work the way it reads: CSS layers every
   background-image it is given rather than picking the first that
   loads, so a missing one is simply a 404 on every page load for
   every visitor. If you regenerate the tile as a .png via
   tools/make-seamless.js, change the path here — do not add it
   alongside. If the file is absent the flat Linen ground shows
   through and nothing breaks.

   z-index -1 keeps it under the content, so it tints the ground
   and never the type sitting on it. multiply lets the texture
   contribute its shading without shifting Linen's hue.          */
body { position: relative; }
body::before {
  content: "";
  /* absolute, not fixed: a fixed multiply layer is re-blended against the
     whole page on every scroll frame, which is what made phones stutter.
     Attached to the page it is painted once and scrolls with it. */
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: url('../assets/paper-tile.jpg');
  background-repeat: repeat;
  background-size: var(--paper-tile) auto;
  background-position: center top;
  mix-blend-mode: multiply;
  opacity: var(--paper-strength);
}

img, svg, video, canvas { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }

button, input, select, textarea {
  font: inherit; color: inherit;
  background: none; border: 0; outline: none;
}
button { cursor: pointer; }
ul, ol { list-style: none; }

::selection { background: var(--accent); color: var(--on-fill-strong); }

::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: var(--ground-3); }
::-webkit-scrollbar-thumb { background: rgba(246, 243, 238, .16); }
@media (hover: hover) { ::-webkit-scrollbar-thumb:hover { background: var(--accent); } }

:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--accent-deep);
  outline-offset: 3px;
}

.skip-link {
  position: fixed;
  top: 12px; left: 12px;
  z-index: 200;
  padding: .7rem 1.1rem;
  background: var(--ink);
  color: var(--linen);
  font-size: .85rem;
  font-weight: 600;
  transform: translateY(-160%);
  transition: transform var(--dur-fast) var(--ease-out);
}
.skip-link:focus-visible { transform: translateY(0); }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ============================================================
   TYPOGRAPHY

   Two voices:
     · Vonca — everything: the portal wordmark, every heading and
       all small type, set uppercase at wide tracking for labels
     · Bangeline — the script accent, one phrase per heading and
       never at small sizes, where a script stops being legible
   ============================================================ */

/* The script accent. Scripts sit optically small and their swashes
   overhang, so it runs larger with room on both sides and a little
   extra line-height headroom where it lands in a heading. */
.ital {
  font-family: var(--font-script);
  font-style: normal;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--accent-deep);
  font-size: 1.34em;
  line-height: .9;
  padding-inline: .06em .12em;
}

/* Section statements — one per section, big and quiet */
.statement {
  font-family: var(--font-display);
  font-size: var(--fs-state);
  font-weight: 700;
  line-height: 1.0;
  letter-spacing: var(--track-tight);
  color: var(--ink);
  text-wrap: balance;
  max-width: 18ch;
}
.statement--sm { font-size: var(--fs-sm); max-width: 20ch; }

.lead {
  font-size: var(--fs-lead);
  line-height: 1.65;
  color: var(--ink-2);
  max-width: 52ch;
  text-wrap: pretty;
}

.mono {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: 400;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--ink-3);
}

.accent { color: var(--accent); }

/* ── Section header ─────────────────────────────────────────
   Number sits in the margin column, label and rule run across —
   the way a spec sheet or a printed contents page is set.      */
.sec {
  display: grid;
  grid-template-columns: var(--margin-col) auto 1fr;
  align-items: baseline;
  gap: 0 1.2rem;
  padding-bottom: 1.1rem;
  margin-bottom: clamp(2.2rem, 5vw, 3.8rem);
}
.sec__no {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: .1em;
  color: var(--ink-3);
}
.sec__label {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: 400;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--ink-2);
  white-space: nowrap;
}
/* The rule draws itself across when the header enters view. It defaults
   to drawn, so headers that aren't reveal targets (the pinned process
   section) still show a rule. */
.sec__rule {
  height: 1px;
  background: var(--rule);
  transform-origin: 0 50%;
  transition: transform 1.1s var(--ease-out);
}
.sec[data-reveal] .sec__rule { transform: scaleX(0); }
.sec[data-reveal].is-in .sec__rule { transform: scaleX(1); }

.sec__statement { margin-bottom: clamp(2.5rem, 6vw, 4.5rem); }

/* ── Oversized ghost numeral, bled off the section edge ───── */
.ghost {
  position: absolute;
  top: clamp(1rem, 4vw, 3rem);
  left: calc(var(--pad-x) * -.35);
  font-family: var(--font-edit);
  font-size: clamp(11rem, 34vw, 30rem);
  line-height: .74;
  /* A cool neutral grey, not the cream used everywhere else. The
     "never grey" rule in the README is about hairlines on Linen, where
     a neutral rule reads cold; this is a numeral behind the content on
     near-black, and the warm tint made it read as a faded word rather
     than as shading. Low enough to stay under the original 4.5% cream
     in luminance while the hue is what changed. */
  color: rgba(188, 192, 200, .035);
  pointer-events: none;
  user-select: none;
  z-index: 0;
}
.ghost--right { left: auto; right: calc(var(--pad-x) * -.35); }

/* ── Brand lockup ───────────────────────────────────────────
   Never re-typeset or recoloured; the fallback below only
   appears if the PNG fails to load.                           */
.brand-lockup { position: relative; display: inline-block; }
.brand-lockup__img { width: 100%; height: auto; }
.brand-lockup__fallback { display: none; }

.brand-lockup.is-missing .brand-lockup__img { display: none; }
.brand-lockup.is-missing .brand-lockup__fallback {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .5rem;
}
.brand-lockup__mark {
  font-family: var(--font-brand);
  font-size: 3.2rem;
  font-weight: 600;
  letter-spacing: -.06em;
  background: var(--grad-chrome);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.brand-lockup__name {
  font-family: var(--font-brand);
  font-size: 1.4rem;
  font-weight: 600;
  letter-spacing: .22em;
  color: var(--accent);
}
.brand-lockup__tag {
  font-size: .6rem;
  font-weight: 300;
  letter-spacing: .42em;
  color: var(--ink-3);
}
