/* SITE V4 token layer. Motion-first, editorial.
 *
 * Kyle ruling 2026-09-03, verbatim: "redesign and refresh the entire site
 * instead of trying to enhance. i feel everytime you try to enhance, nothing
 * changes and we're just looking at something which is the same."
 *
 * That sentence is a diagnosis of a method, not a complaint about a colour. The
 * previous passes all re-pointed VALUES inside an unchanged structure: same
 * static hero, same stacked bands, same still image of a product. So v4 adds the
 * axis those passes had no token for at all, MOTION, and treats it as a design
 * primitive with the same standing as colour and type rather than as decoration
 * bolted on at the end.
 *
 * Reference bar Kyle set (three sites, one lesson each):
 *   - fluidmotion.app: motion IS the product; the first impression is a loop,
 *     not a screenshot.
 *   - the editorial reference: serif display type, one conversion path, and
 *     production polish, where the type does the persuading.
 *   - scale.com: the masterstroke, the hero is the product OPERATING.
 *
 * oddly's version of scale's trick has to be HONEST, which is the constraint
 * that makes it ours: scale animates a detection overlay, and we animate real
 * reads with their observation stamps attached, every figure one click from its
 * proof. A fabricated ticker would be the single most brand-destroying thing
 * this estate could ship, so the motion tokens below exist to move REAL numbers,
 * never to manufacture the feeling of activity.
 *
 * SCOPED under `.site-v4`, never :root, and gated by SITE_V4 (wrangler.toml
 * [vars], off). Both belts hold: production 404s the whole v4 tree, and these
 * tokens resolve only inside a v4 subtree, so this file changes zero pixels on
 * any existing surface.
 *
 * TYPE COMES FROM THE TITAN REGISTER RULING, not from taste and no longer from
 * tokens-v3.json. DR-2026-09-15-site-titan-register (docs/canon/rulings.json)
 * supersedes the ratified token source on type: the site is built to the
 * register of the billion-dollar infrastructure sites, default faces are out,
 * and the family is Newsreader for the story, Hanken Grotesk for the interface,
 * IBM Plex Mono for every figure, all self-hosted. The previous pass rendered
 * the committed canvas in Fraunces and Inter because the one ratified artifact
 * still named them; that drift is CX-2026-09-15-titan-register-uncaptured, and
 * the checkable half of the ruling is pinned in tests/unit/site/site-v4.test.ts
 * (first faces, and no third-party font host on any v4 surface).
 *
 * Figures are mono because the tape is a ledger: proportional digits change
 * width as they change value, so a number re-reading in a proportional face
 * jitters, and jitter reads as animation. The one thing the tape must never do
 * is make a real number look animated.
 *
 * The three @font-face blocks below are declared IN THIS FILE rather than in
 * oddly-tokens.css on purpose: they are loaded only by a v4 surface, so no
 * existing page pays a byte for a design that is still dark.
 */
@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/_shared/fonts/newsreader-latin-var.woff2") format("woff2");
}
@font-face {
  font-family: "Hanken Grotesk";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/_shared/fonts/hanken-grotesk-latin-var.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/_shared/fonts/ibm-plex-mono-400.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/_shared/fonts/ibm-plex-mono-600.woff2") format("woff2");
}
.site-v4 {
  /* ---- Canvas + ink: an ink-black editorial ground with paper-white type ---- */
  --v4-canvas: #0A0A0C;             /* page: near-black, warm-neutral not blue */
  --v4-surface: #131317;            /* raised panel */
  --v4-surface-sunken: #08080A;     /* the tape's own well */
  --v4-ink: #F5F4F1;                /* primary type: warm paper white */
  --v4-ink-secondary: #B4B2AC;      /* secondary */
  --v4-ink-muted: #74726C;          /* stamps, captions, provenance */
  --v4-accent: #2FD3B4;             /* action + live signal only */
  --v4-accent-hover: #57E7CC;
  --v4-premium: #D9B978;            /* money only */

  /* ---- Rules: hairlines that read as a ledger, not as card borders ---- */
  --v4-rule: rgba(245, 244, 241, 0.10);
  --v4-rule-strong: rgba(245, 244, 241, 0.24);
  --v4-focus: 0 0 0 2px var(--v4-canvas), 0 0 0 4px var(--v4-accent);

  /* ---- Type ---- */
  --v4-font-display: "Newsreader", var(--oddly-font-serif);
  --v4-font-text: "Hanken Grotesk", var(--oddly-font-sans);
  --v4-font-figures: "IBM Plex Mono", var(--oddly-text-mono);
  /* Display sizes are fluid: the hero line is the first impression at every
     width, and a clamp is how it stays one line of thought on a phone without a
     second set of breakpoint overrides. */
  --v4-display-1: clamp(2.5rem, 6.4vw, 5rem);
  --v4-display-2: clamp(1.75rem, 3.2vw, 2.5rem);
  --v4-figure: clamp(1.75rem, 3.6vw, 2.75rem);
  --v4-tracking-display: -0.022em;
  --v4-tracking-label: 0.14em;

  /* ---- MOTION, the axis this design layer exists to add ----
     Three durations and two easings, so every moving thing on the surface is
     drawn from one vocabulary. --v4-motion-enter is the one that must land
     inside the ruled 3-second first impression: it is the tape's own reveal.
     --v4-tape-tick is the cadence a live figure re-reads at, deliberately slow:
     a number that changes every second is a slot machine, and the underlying
     feeds advance daily. */
  --v4-motion-fast: 180ms;
  --v4-motion-base: 420ms;
  --v4-motion-enter: 900ms;
  --v4-tape-tick: 5200ms;
  /* Standard: decelerate into rest, for anything arriving. */
  --v4-ease-enter: cubic-bezier(0.16, 1, 0.3, 1);
  /* Mechanical: near-linear, for the tape's own travel. A ledger advances at a
     constant rate; easing it would imply an intent the data does not have. */
  --v4-ease-tape: cubic-bezier(0.4, 0, 0.6, 1);

  /* ---- Structure ---- */
  --v4-gutter: clamp(1.25rem, 4vw, 4rem);
  --v4-measure: 62ch;
  --v4-radius: 4px;                 /* editorial: a cut, not a pill */

  /* ---- THE DESCENT'S SURFACES, from the committed canvas ----
     Source: docs/design/canvas/the-world-on-the-record/Main.dc.html (#1763),
     which Kyle committed as V4's reference pixels after holding the preview
     against it. The page descends ink to paper in four surfaces, and the paper
     half then carries the record and the four ruled lines. These are section
     surfaces of the ONE page, not a register switch: the ratified daylight
     register (.v4-daylight below) keeps its own values for surfaces that are
     records, and where the two disagree (paper #F4F1EA vs ledger-light #F7F4ED)
     the canvas governs this page because the canvas is what BUILD 4 is accepted
     against, section for section. Named here so the deviation is on the record. */
  --v4-step-dusk: #1A1A2E;          /* descent step 02, and the paper's own ink */
  --v4-step-dawn: #E8E6E0;          /* descent step 03, and the card border on paper */
  --v4-paper: #F4F1EA;              /* descent step 04, and the record's ground */
  --v4-paper-raised: #FAFAF7;       /* the four ruled lines' ground */
  --v4-paper-card: #FFFFFF;         /* the three deciders' cards */
  --v4-paper-ink: #1A1A2E;
  --v4-paper-ink-secondary: #5A5A6E;
  --v4-paper-ink-muted: #8A8A98;
  --v4-paper-accent: #2C7873;       /* eyebrows and links on paper */
  --v4-paper-accent-hover: #246059;
  --v4-paper-rule: rgba(26, 26, 46, 0.14);
  --v4-bronze: #B08D57;             /* receipts and provenance on paper */
  /* The sky's second twinkle cadence (the canvas runs 5.2s and 7.1s so the
     field never beats in unison). The first reuses --v4-tape-tick. */
  --v4-twinkle-slow: 7100ms;

  /* ---- The hero scrim ----
     The sky draws one circle per subject and the corpus grows daily, so the
     field's type must stay legible over any density the ledger reaches. The
     scrim sits between the sky and the said, the canvas ink fading to clear
     toward the field's right edge, so points near the type dim while the open
     sky keeps its full field. Token-sourced so the page's style block stays
     hex-free; the rgba triplet is --v4-canvas (#0A0A0C). */
  --v4-scrim: linear-gradient(112deg, rgba(10, 10, 12, 0.88) 0%, rgba(10, 10, 12, 0.5) 46%, rgba(10, 10, 12, 0) 78%);

  /* ---- THE ORBIT RAMP ----
     docs/design/canvas/orbit-direction.md (#1894), ruled by Kyle 2026-09-17.
     This is NOT a change of hue. DR-2026-09-15-site-titan-register still rules
     the three hues and the three faces and none of them move here. What this
     adds is a name for each step of the ramp BETWEEN the ruled values, and it
     is needed because of what the orbit direction did to the page: light now
     does the work borders, radii and shadows used to do, so the surface depends
     on a set of very close dark values that drift page to page the moment they
     are written as ad hoc hex. Two surfaces that should be the same plane end
     up visibly not, and nobody can see it because they sit on different routes.

     --v4-glow and --v4-glow-white are the only genuinely new idea in this
     table. Every other row is a value already in use somewhere in the estate,
     given a name so it stops being retyped. Light that is not a token drifts
     faster than anything else in a palette.

     --v4-accent-dim is a CORRECTNESS token, not taste: #2FD3B4 on #F4F1EA fails
     WCAG AA for text, so the paper register needs its own accent. It is not a
     second accent and it is not a licence to pick a different green on ink. */
  --v4-ink-00: #0A0A0C;             /* the ground, ruled */
  --v4-ink-01: #101014;             /* a raised plane */
  --v4-ink-02: #16161C;             /* a card's own ground */
  --v4-ink-03: #1E1E24;             /* hairline rules */
  --v4-ink-04: #2A2A32;             /* a border that must be seen */
  --v4-ink-05: #4A4E55;             /* the land on the map, the only grey with no chroma */
  --v4-bone: #ECEAE4;               /* body on ink */
  --v4-bone-2: #C9C7C0;             /* a lede on ink */
  --v4-grey: #7E8C89;               /* secondary, biased toward the accent so it reads as chosen */
  --v4-grey-2: #515E5B;             /* mono labels */
  --v4-accent-2: #8FE7D6;           /* a second mark on the MAP only, never type */
  --v4-accent-dim: #1B8A74;         /* the accent on paper, where the ruled value fails contrast */
  --v4-bronze-dim: #A8956B;         /* bronze on paper */
  --v4-paper-2: #FBFAF6;            /* a card on paper */
  --v4-glow: rgba(47, 211, 180, 0.26);      /* the bloom: the only place the accent is light */
  --v4-glow-white: rgba(255, 255, 255, 0.07); /* a floor under a lit object */
  /* The land reads through a name rather than through --v4-ink-05 directly, so
     the daylight register can flip the map without flipping every hairline. */
  --v4-map-land: var(--v4-ink-05);

  /* ---- THE CAMERA ----
     The four numbers the orbit move is made of, here rather than in the page,
     so the whole travel can be retimed without touching markup.

     --v4-orbit-zoom is 4.2 and that is not taste. The land is drawn at a two
     degree grid; past roughly 4x the grid stops reading as land and starts
     reading as blur, which is the exact moment a push-in stops being a camera
     and becomes a screensaver. --v4-orbit-track is the scroll distance the
     sticky stage holds for: shorter and the four shots cut faster than they can
     be read, longer and the reader is scrolling through a held frame. */
  --v4-orbit-track: 340vh;
  --v4-orbit-zoom: 4.2;
  --v4-sheet-lift: 44px;
  --v4-sheet-radius: 44px;
}

/* THE DAYLIGHT REGISTER: the record.
 *
 * Two registers, one family. CANON.md ruling 1 (TWO-MODE IDENTITY, Kyle
 * 2026-08-19) names them: Ledger Light is the record in daylight, Deep Field is
 * the machine at work, and Signal moves only live data in both. The block above
 * is V4's ink register, the instrument. This block is the other half: the SAME
 * token names remapped to the ratified Ledger Light values from
 * docs/design/tokens-v3.json (ratified Kyle 2026-08-19, #1183), so a daylight
 * surface is a class on the same layer, never a second stylesheet.
 *
 * Only SURFACE tokens remap. Type, motion, structure and the reduced-motion
 * contract are inherited from .site-v4 unchanged, which is what "one family"
 * means mechanically: the record and the instrument cannot drift apart in
 * anything but light. Direction: docs/design/OEG-DESIGN-2026-09-v4-two-registers.md.
 */
.site-v4.v4-daylight {
  --v4-canvas: #F7F4ED;             /* ledger-light bg */
  --v4-surface: #FFFFFF;            /* ledger-light bg-raised */
  --v4-surface-sunken: #EFEAE0;     /* ledger-light bg-inset */
  --v4-ink: #14161C;
  --v4-ink-secondary: #4A4E58;
  --v4-ink-muted: #8B8E96;
  --v4-accent: #0F7A5C;             /* every link and verify affordance */
  --v4-accent-hover: #2C7873;       /* accent-teal: ledger-light defines no hover tone, so the nearest ratified one */
  --v4-premium: #A9824F;            /* bronze: receipts and roots, evidence only */
  --v4-rule: rgba(20, 22, 28, 0.12);
  --v4-rule-strong: rgba(20, 22, 28, 0.28);
  --v4-focus: 0 0 0 2px var(--v4-canvas), 0 0 0 4px var(--v4-accent);
  /* The scrim remaps with the surface it protects: the same stops in the
     daylight canvas (#F7F4ED), so a daylight field dims its own ground. */
  --v4-scrim: linear-gradient(112deg, rgba(247, 244, 237, 0.88) 0%, rgba(247, 244, 237, 0.5) 46%, rgba(247, 244, 237, 0) 78%);

  /* The orbit ramp in daylight. Only the values whose MEANING is "dark" flip;
     the ruled hues and the camera's geometry are register-independent, which is
     what keeps the instrument and the record one family. */
  --v4-ink-01: #FFFFFF;
  --v4-ink-02: #FFFFFF;
  --v4-ink-03: rgba(20, 22, 28, 0.10);
  --v4-ink-04: rgba(20, 22, 28, 0.20);
  --v4-bone: #14161C;
  --v4-bone-2: #4A4E58;
  --v4-grey: #515E5B;
  --v4-grey-2: #7E8C89;
  --v4-accent-2: var(--v4-accent-dim);
  --v4-map-land: #B9BDC2;
  --v4-glow: rgba(27, 138, 116, 0.18);
  --v4-glow-white: rgba(20, 22, 28, 0.05);
}

/* THE REDUCED-MOTION CONTRACT, and it is a contract rather than a courtesy.
 *
 * A motion-first design has exactly one accessibility obligation it cannot
 * delegate: a visitor who has asked their OS for less motion must get the same
 * INFORMATION, not a degraded page. So the durations collapse to zero here
 * rather than the animations being removed: every element ends in its final,
 * fully-legible resting state, the live figures still read and still carry their
 * observation stamps, and only the travel between states is dropped.
 *
 * Written as token overrides, not as a pile of `animation: none` rules, so it
 * keeps working for motion added later by any build that uses the vocabulary.
 * Note Playwright's reducedMotion is a CONTEXT option, so a visual-QA capture
 * that sets it with test.use() is silently ignored (tests/e2e sets it on the
 * context). */
@media (prefers-reduced-motion: reduce) {
  .site-v4 {
    --v4-motion-fast: 1ms;
    --v4-motion-base: 1ms;
    --v4-motion-enter: 1ms;
    --v4-ease-enter: linear;
    --v4-ease-tape: linear;
  }
}
