/* ============================================================
   site.css
   Shared layout/type primitives and cross-section mechanics.
   No raw values here — everything traces to tokens.css.
   ============================================================ */

/* ------------------------------------------------------------
   Mobile gate — no mobile version yet (owner decision, Aug 2026).
   Blocks the whole page below 900px (system_2.md's one real
   breakpoint) with an honest "not built yet" message, rather than
   letting an unfinished/half-mobile layout through. Hidden entirely
   at 900px+; nothing below it can be seen or reached under 900px, so
   z-index just needs to clear the header (--z-header), not fight it.
   ------------------------------------------------------------ */
#mobile-gate{ display:none; }
@media (max-width:899.98px){
  #mobile-gate{
    display:flex; flex-direction:column; justify-content:center;
    position:fixed; inset:0; z-index:var(--z-gate);
    background:var(--bg); color:var(--text);
    padding-inline:var(--pad-inline); text-align:left;
  }
  #mobile-gate .eyebrow{ margin-bottom:var(--sp-5); }
  #mobile-gate h1{
    font-family:var(--font-display); font-weight:400;
    font-size:clamp(32px,9vw,56px); line-height:1.05; margin:0;
  }
  #mobile-gate p:not(.eyebrow){
    margin-top:var(--sp-5); max-width:36ch;
    font-size:var(--fs-t2); color:var(--text-muted);
  }
}

/* ------------------------------------------------------------
   Progress bar — reads the one eased scroll value from engine.js
   ------------------------------------------------------------ */
.prog{
  position:fixed; top:0; left:0; width:100%; height:3px;
  z-index:var(--z-header);
  background:var(--text);
  transform:scaleX(0); transform-origin:left;
  will-change:transform;
}

/* ------------------------------------------------------------
   Header — fixed, difference-blend, wordmark + contact + theme toggle
   ------------------------------------------------------------ */
.hdr{
  position:fixed; top:0; left:0; width:100%; z-index:var(--z-header);
  display:flex; align-items:center; justify-content:space-between;
  padding-block:var(--sp-5); padding-inline:var(--pad-inline);
  mix-blend-mode:difference; color:var(--w-00);
  pointer-events:none;
}
@media (min-width:900px){ .hdr{ padding-block:var(--sp-6); } }
.hdr a, .hdr button{ pointer-events:all; }
.hdr.is-normal{ mix-blend-mode:normal; color:var(--text); }

/* Anton, not Inter — the wordmark is a logotype, not a nav item, and
   deserves the same display voice as every heading on the page. Fixed
   at 24px flat: Anton's own documented floor, not a clamp that could
   ever dip under it. */
.hdr__mark{
  font-family:var(--font-display); font-weight:400; font-size:24px;
  /* --ls-display (-.014em, tight) is for reading-sized display copy —
     wrong direction for two words in caps. --ls-caps (.09em) is the
     token every other uppercase element on the page already uses. */
  letter-spacing:var(--ls-caps); text-transform:uppercase;
  background:none; border:0; color:inherit; cursor:pointer; line-height:1;
}

.hdr__r{ display:flex; align-items:center; gap:var(--sp-6); }

/* Section links sit beside Contact in the same right-hand cluster.
   Hidden below 900px, same breakpoint every scroll mechanic already
   forks on — six extra links has no room in the mobile header. */
.hdr__nav{ display:none; align-items:center; gap:var(--sp-5); }
@media (min-width:900px){ .hdr__nav{ display:flex; } }
/* Owner request: nav names read a bit big — calc(var(--fs-t3) * 0.9),
   a little smaller, not a full token step down. .hdr__contact matches
   (not explicitly asked, but it sits in the same row at the same size
   as the nav links — shrinking only one would leave them visibly
   mismatched next to each other). */
.hdr__navlink{
  font-family:var(--font-text); font-weight:500; font-size:calc(var(--fs-t3) * 0.9);
  letter-spacing:var(--ls-caps); text-transform:uppercase;
  color:inherit; text-decoration:none;
}

.hdr__contact{
  font-family:var(--font-text); font-weight:500; font-size:calc(var(--fs-t3) * 0.9);
  letter-spacing:var(--ls-caps); text-transform:uppercase;
  color:inherit;
}

/* ------------------------------------------------------------
   Mask reveal — text uncovers, never fades. See collision-protocol:
   translateY(125%) not 105% — overflow:hidden clips the padding box,
   so a mask with padding is taller than the line inside it.
   ------------------------------------------------------------ */
.mask{ display:block; overflow:hidden; }
.js .mask > *{
  display:block; transform:translateY(125%); will-change:transform;
}
.js .is-in .mask > *{
  transform:translateY(0);
  transition:transform var(--dur-4) var(--ease-reveal);
}
.js .is-in .mask:nth-of-type(2) > *{ transition-delay:90ms; }
.js .is-in .mask:nth-of-type(3) > *{ transition-delay:170ms; }
.js .is-in .mask:nth-of-type(4) > *{ transition-delay:280ms; }
.js .is-in .mask:nth-of-type(5) > *{ transition-delay:370ms; }

/* ------------------------------------------------------------
   Fades — blocks and images only. Never on a heading.
   ------------------------------------------------------------ */
.js .fade{ opacity:0; transition:opacity var(--dur-2) var(--ease-move); }
.js .is-in .fade{ opacity:1; }

/* ------------------------------------------------------------
   Dim until lit — stat/skill blocks, not a reveal. Everything is
   present the whole time; the page brightens whichever is nearest
   the middle of the screen.
   ------------------------------------------------------------ */
.js .dim{ opacity:.2; transition:opacity var(--dur-2) var(--ease-move); }
.js .dim.is-lit{ opacity:1; }

/* ------------------------------------------------------------
   Section inversion — scoped token remap, never on :root.
   ------------------------------------------------------------ */
.flip{
  transition:background-color var(--dur-1) var(--ease-move),
             color var(--dur-1) var(--ease-move);
  will-change:background-color,color;
}

/* ------------------------------------------------------------
   Underline links — origin flips so it grows in, retracts out.
   ------------------------------------------------------------ */
.link{ position:relative; width:fit-content; cursor:pointer; }
.link::before{
  content:''; position:absolute; left:0; bottom:-.15em; width:100%;
  height:max(1px,.05em); background:currentColor;
  transform:scaleX(0); transform-origin:right;
  transition:transform var(--dur-5) var(--ease-move);
}
.link:hover::before{ transform:scaleX(1); transform-origin:left; }

/* ------------------------------------------------------------
   Section scaffolding — system_2.md §3: "Section padding is --sp-9
   minimum. The close uses --sp-10." Flat, not responsive: --sp-10 is
   reserved for Contact/Bookend precisely so escalating everything
   else to it doesn't erase that distinction.
   ------------------------------------------------------------ */
.section{ padding-block:var(--sp-9); position:relative; }
.section--tight{ padding-block:var(--sp-7); }
.section--vast{ padding-block:var(--sp-12); }

.eyebrow{
  font-family:var(--font-text); font-weight:500; font-size:var(--fs-t4);
  letter-spacing:var(--ls-caps); text-transform:uppercase;
  color:var(--text-muted); margin-bottom:var(--sp-4);
}

.sub{
  font-size:var(--fs-t1); color:var(--text-muted); max-width:var(--measure);
  margin-top:var(--sp-4);
}
.sub--narrow{ max-width:44ch; }

/* Shared "eyebrow → display → sub" header, per copy-deck-index_1.md:
   every section uses it except Hero, the two quotes, and the bookend. */
.head{ margin-bottom:var(--sp-11); }
.head__display{
  font-family:var(--font-display); font-weight:400;
  font-size:var(--fs-d3); line-height:var(--lh-display); margin:0;
}

/* ------------------------------------------------------------
   Reduced motion — off, not down.
   ------------------------------------------------------------ */
@media (prefers-reduced-motion:reduce){
  .js .mask > *{ transform:none !important; }
  .js .fade{ opacity:1 !important; }
  .js .dim{ opacity:1 !important; }
  *{ transition:none !important; animation:none !important; }
  html{ scroll-behavior:auto; }
}

/* No-JS resting state stays visible per collision-protocol §5 */
.mask > *{ transform:none; }
.fade, .dim{ opacity:1; }

/* ------------------------------------------------------------
   Progress rail — shared by any pinned/scrubbed mobile section
   (Work track, Method fold) that names which card you're on.
   ------------------------------------------------------------ */
.rail{
  position:absolute; left:var(--pad-inline); right:var(--pad-inline); bottom:var(--sp-7);
  z-index:2; display:flex; align-items:center; gap:var(--sp-4);
}
.rail__n{
  font-size:var(--fs-t4); letter-spacing:var(--ls-caps); color:var(--text-muted);
  font-variant-numeric:tabular-nums; white-space:nowrap;
}
.rail__bar{ flex:1; height:1px; background:var(--border); position:relative; }
.rail__fill{ position:absolute; inset:0 auto 0 0; width:0; background:var(--text); }

/* Honest placeholder — a number awaiting real data, per copy-deck-index-v4.md's
   own convention: "[ brackets ]" rather than an invented figure. Used on Work
   card triads and detail-page meta/body copy. */
.todo{ color:var(--text-muted); border-bottom:1px dotted var(--text-muted); }

/* ------------------------------------------------------------
   Scroll reveal — body content wipes down from behind a mask.
   system_2.md §5: clip 1150ms, transform 1500ms — deliberately
   different lengths, so the line is still settling when the wipe
   has already finished, rather than everything landing at once.
   Stagger 130ms, capped at 5 (a 6th+ child reuses the 5th's delay).
   Used by About, Contact, and the five detail pages.
   ------------------------------------------------------------ */
.rv{ overflow:hidden; }
.js .rv{ clip-path:inset(0 0 100% 0); transition:clip-path 1150ms var(--ease-reveal); }
.js .is-in.rv{ clip-path:inset(0 0 0% 0); }
.rv__in{ display:block; }
.js .rv__in{ transform:translateY(34px); transition:transform 1500ms var(--ease-reveal); }
.js .is-in .rv__in{ transform:translateY(0); }

.rv:nth-of-type(2), .rv:nth-of-type(2) .rv__in{ transition-delay:130ms; }
.rv:nth-of-type(3), .rv:nth-of-type(3) .rv__in{ transition-delay:260ms; }
.rv:nth-of-type(4), .rv:nth-of-type(4) .rv__in{ transition-delay:390ms; }
.rv:nth-of-type(5), .rv:nth-of-type(5) .rv__in{ transition-delay:520ms; }
.rv:nth-of-type(n+6), .rv:nth-of-type(n+6) .rv__in{ transition-delay:520ms; }

@media (prefers-reduced-motion:reduce){
  .js .rv{ clip-path:none; }
  .js .rv__in{ transform:none; }
}
