/* ==========================================================================
   tokens.css — colours, the type scale, the motion table, and the rem cascade.

   Loaded FIRST by every page, hand-written or generated. It is the only file
   in the repo allowed to declare html { font-size }: the cascade below is an
   ordered set of descending max-width queries, so a second declaration
   anywhere lands after it and silently takes over at some widths. The build
   fails on a second one (BUILD-PIPELINE §10, assertion 4).

   One deliberate change from the spec: the spec hardcodes html's background
   to #08080a. Here it is var(--background), because a light-theme visitor must
   not see a dark page or any flash of one (00-shared.md AC-12), and the light
   theme did not exist when that line was written.

   Values come from design/home-page-spec.md and are not rounded. Rounding
   0.833333vw to .833vw shifts every rem-derived length on the page, and the
   scale runs to 28rem.
   ========================================================================== */

/* --- The rem-based adaptive grid ----------------------------------------- */
/* Four max-width queries in DESCENDING order, each overriding the previous.
   The vw values are the design spec's and are not rounded: each is chosen so
   one rem computes to exactly 16px at that breakpoint's upper bound, and the
   layout then scales down with the viewport until the next breakpoint takes
   over. Above 1920px rem-scale.mjs sets an inline font-size on <html> and
   removes it again when the computed value is not larger than the base. Do
   not reorder, merge, mobile-first-sort, round or unit-convert any of this.

   THE FLOOR AND THE CAP ARE ADDED, and they are the only departure from the
   spec's ladder. Measured in a browser on every page, the ladder as declared
   does this:

     viewport   639  641   768   900  1024  1025  1200  1440  1441  1920
     root (px) 28.4 10.0  12.0  14.1  16.0  11.4  13.3  16.0  12.0  16.0

   Each rung resets to 16px at its own top and scales DOWN as the viewport
   narrows, so the root dips at the bottom of every band and then snaps back
   up: 2.84x at 640/641, and the same shape at 1024/1025 and 1440/1441. The
   worst of it, 641px to about 830px, renders the whole site at 10-13px body
   text — a tablet in portrait, a large phone in landscape, a browser window
   beside an editor. That is not small, it is unreadable, and it is a real
   share of anyone opening a link from LinkedIn or a conference app.

   So: a floor of 0.875rem under each desktop rung, and a cap of 1.25rem on
   the phone rung, which otherwise reaches 28px on a 640px-wide window. With
   the floor the root never drops below 14px and body text never below 14.9px:

     viewport   639  641   768   900  1024  1025  1200  1440  1441  1920
     root (px) 20.0 14.0  14.0  14.1  16.0  14.0  14.0  16.0  14.0  16.0

   14 rather than 15 or 16 because the floor stops the layout scaling with the
   viewport, and something has to give: at 1025px a 4-column Impact row and a
   7-character hero line both still fit at 14px. Checked on every route at
   375, 390, 500, 600, 639, 641, 768, 834, 900, 1024, 1025, 1200, 1440, 1441
   and 1920 — no horizontal scrolling anywhere, and the giant name fits.

   The floor and the cap are in `rem`, not px, on purpose. In a font-size on
   the ROOT element, `rem` resolves against the inherited size — the browser
   default, which is the visitor's own preference — so the floor is 14px for
   a default of 16px and 17.5px for someone who has set 20px. Verified in a
   browser: `html { font-size: 0.8125rem }` computes to 13px. Everything else
   in this ladder is `vw` and ignores that preference entirely, which is the
   design's choice to make; the floor at least does not. */
html { font-size: 16px; background: var(--background); }
@media (max-width: 1920px) { html { font-size: max(0.875rem, 0.833333vw); } }
@media (max-width: 1440px) { html { font-size: max(0.875rem, 1.111111vw); } }
@media (max-width: 1024px) { html { font-size: max(0.875rem, 1.5625vw); } }
@media (max-width: 640px)  { html { font-size: min(1.25rem, 4.444444vw); } }

/* --- Colour: dark, primary ----------------------------------------------- */
/* THE ACCENT IS BLUE, and it was the red first. The red was chosen against a
   contrast bar rather than by eye, so the blue is held to the same one: the
   accent must clear 4.5:1 — WCAG AA for small text — against the background it
   sits on, in both themes. Measured, not estimated:

     dark  --accent    #1f87ff on #08080a   5.69:1   (the red: 5.62:1)
     dark  --accent-2  #5c98ff on #08080a   7.04:1   (the red: 7.03:1)
     light --accent    #1262c4 on #f3f1ea   5.20:1   (the red: 4.98:1)
     light --accent-2  #1f67db on #f3f1ea   4.62:1   (the red: 3.59:1, which
                                                      failed small text)

   The accent is the red's own HSL geometry with the hue turned: the red was
   s100 l56 dark and s83 l42 light, and so is the blue, at hue 212 rather than
   hue 8. Hue 212 is the one place in the blue range where both of those
   lightnesses still clear the bar — turn further toward 220 and the dark
   accent falls under 4.5, further toward 200 and the light one does, because
   blue carries about a tenth of green's luminance. So this pair is not a
   preference; it is where the arithmetic leaves room.

   --accent-2 is the lighter sibling in both themes, as it was in the red. Its
   light value clears small text where the red's did not, which costs nothing:
   grep says --accent-2 is declared here and used nowhere, so the first page to
   reach for it should not inherit a value that fails.

   Everything --accent paints is either text, or a mark no larger than 2px —
   the focus ring, the current-page underline, the eyebrow dot, the marquee
   dot, the list dash — all of which need 3:1 and have it. The one place text
   sits ON the accent is ::selection, where the text is --background, so that
   ratio is the same number again. */
:root {
  --background: #08080a;
  --foreground: #f3f1ea;
  --surface: #111114;
  --surface-2: #17171b;
  --muted: #807f78;
  --line: rgba(243, 241, 234, .1);
  --line-strong: rgba(243, 241, 234, .22);
  --accent: #1f87ff;
  --accent-2: #5c98ff;

  /* How much of --background the hero's text scrim lays over the portrait.
     See .hero__inner::before in home.css for what it is and why it exists.
     It is a theme value because the two themes are not the same problem: on
     the dark page the photograph's DARK areas help cream text and only its
     highlights hurt, so 95% is enough and the picture still reads through it.
     On the cream page it is the other way round and much worse, because this
     photograph is mostly dark — a black sweater, dark trousers, a dim room —
     and dark text over any of that fails at every opacity worth having. It
     measured 1.80:1 at 1440 before this token existed. So in light the scrim
     is opaque and the photograph shows beside the text rather than under it. */
  --hero-scrim: 95%;

  /* The vignette and placeholder gradients in the design spec are written
     against the dark background. In light they would be a black smear, so the
     colour they mix from is a token too. */
  --shade: #08080a;

  color-scheme: dark;
}

/* --- Colour: light, a token swap that keeps the blue --------------------- */
/* The accent is deepened for contrast on cream — design spec, Tokens. */
:root[data-theme="light"] {
  --background: #f3f1ea;
  --foreground: #08080a;
  --surface: #e8e5db;
  --surface-2: #dedbd0;
  --muted: #6b6a62;
  --line: rgba(8, 8, 10, .12);
  --line-strong: rgba(8, 8, 10, .24);
  --accent: #1262c4;
  --accent-2: #1f67db;
  --hero-scrim: 100%;
  --shade: #6b6a62;

  color-scheme: light;
}

/* A visitor with no stored choice gets what their system asks for, and dark
   when it expresses no preference. The inline <head> script sets data-theme
   before first paint once a choice is stored, so this query only decides the
   untouched default — including for a visitor with no JavaScript. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --background: #f3f1ea;
    --foreground: #08080a;
    --surface: #e8e5db;
    --surface-2: #dedbd0;
    --muted: #6b6a62;
    --line: rgba(8, 8, 10, .12);
    --line-strong: rgba(8, 8, 10, .24);
    --accent: #1262c4;
    --accent-2: #1f67db;
    --hero-scrim: 100%;
    --shade: #6b6a62;

    color-scheme: light;
  }
}

/* --- Type ---------------------------------------------------------------- */
:root {
  --font-display: "Anton", "Arial Narrow", "Haettenschweiler", sans-serif;
  --font-sans: "Onest", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;

  --fs-hero: 28rem;      --lh-hero: .78;
  --fs-mega: 13rem;      --lh-mega: .86;
  --fs-display: 7.5rem;  --lh-display: .9;
  --fs-h1: 5rem;         --lh-h1: .95;
  --fs-h2: 3.25rem;      --lh-h2: 1;
  --fs-h3: 1.75rem;      --lh-h3: 1.15;
  --fs-lead: 1.375rem;   --lh-lead: 1.45;
  --fs-body: 1.0625rem;  --lh-body: 1.6;
  --fs-eyebrow: .8125rem; --lh-eyebrow: 1.2;

  --track-heading: -.01em;
  --track-eyebrow: .22em;
  --track-eyebrow-tight: .18em;
  --track-stat: .14em;
}

/* --- Space --------------------------------------------------------------- */
:root {
  --gutter: 2.5rem;
  --section: 9rem;
  --nav-h: 5rem;
}
@media (max-width: 640px) {
  :root { --gutter: 16px; --nav-h: 4.5rem; }
}

/* --- Motion: the spring → timing map, baked ------------------------------ */
/* design/home-page-spec.md, Motion. The left column of that table is the
   original spring; these are the baked equivalents, and they are the only
   durations and easings any stylesheet should use. */
:root {
  --ease-expo: cubic-bezier(.16, 1, .3, 1);    /* easeOutExpo  */
  --ease-quart: cubic-bezier(.165, .84, .44, 1); /* easeOutQuart */
  --ease-wipe: cubic-bezier(.22, 1, .36, 1);
  --ease-out: cubic-bezier(.33, 1, .68, 1);

  --t-wipe: 650ms;       /* t90/f20  preloader wipe            */
  --t-menu: 450ms;       /* t210/f28 mobile menu fade          */
  --t-menu-link: 420ms;  /* t260/f30 mobile menu link trail    */
  --t-body: 520ms;       /* t180/f26 hero description, story body */
  --t-list: 560ms;       /* t170/f26 story principles, impact cells */
  --t-card: 620ms;       /* t150/f26 work cards                */
  --t-portrait: 640ms;   /* t140/f24 speaking portrait scale-in */
  --t-hover: 340ms;      /* t220/f22 hover → accent            */
  --t-veil: 380ms;       /* t220/f26 liquid grayscale reveal   */
  --t-name: 900ms;       /* hero name, letter by letter        */
  --t-roles: 760ms;      /* hero roles, line by line           */
  --t-heading: 880ms;    /* section headings, line by line     */
  --t-word: 520ms;       /* speaking statement, word by word   */

  --stagger-letter: 52ms;
  --stagger-line: 90ms;
  --stagger-word: 22ms;
  --stagger-roles: 80ms;
}

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