/* ════════════════════════════════════════════════════════════════
   uni — DESIGN TOKENS (the single source of truth)
   ────────────────────────────────────────────────────────────────
   ONE system, two liveries. Every page links THIS file; nothing
   redefines a colour, a radius, an easing, or the type scale locally.
     · structural tokens (type · space · radius · motion · focus) are
       SHARED — they make the platform and its schools feel like one make.
     · colour is a LIVERY:  uni flies pearl + one deep red;
       Ginko, its school of languages, flies the ginkgo at dusk (gold).
   Each school keeps its own livery; the structure underneath is common.
   ════════════════════════════════════════════════════════════════ */

:root{
  /* ── type ── */
  --font:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
  /* THE TYPE SCALE lives with the Ginko livery below (minted 2026-08-20). The nine tokens that
     stood here (--t-hero/display/h2/h1/say/lede/body/sm/xs) were deleted the day they were
     measured at ZERO references across the whole tree: a scale nobody reaches for is not a scale,
     it is a vacuum, and 44 ad-hoc clamp() sizes had filled it. One scale, or none. */

  /* ── space / measure ── */
  --maxw:1200px;

  /* ── radius scale (shared → coherent corners everywhere) ── */
  --r-sm:9px; --r-md:14px; --r-lg:22px; --r-pill:999px;

  /* ── motion (shared easing + a default duration) ── */
  --ease:cubic-bezier(.22,.61,.36,1); --dur:.18s;

  /* ════ LIVERY · uni — pearl concourse + ONE vine red (OURS: the valley's wine country) ════
     Vertical integration 2026-07-21: the flag red is re-derived as OURS — vine red #872338, the
     Sacramento valley's own deep red, replacing the borrowed "Harvard-crimson" story. The flag law
     stands: used at <5%, NEVER as body text — the seal, one accent rule/underline, the active nav
     state, the primary action. Everything else neutral. */
  --pearl:#F2F4F5; --pearl-hi:#F8FAFA; --pearl-lo:#E6EAEC; /* THE COOL FOUNDATION (2026-07-21): the shell inherits Luyml's cool-foundation law; the cream-brown-black AI cliche is BANNED on the shell (COLOR_JITSU). Warmth belongs to the WORLDS — cool concourse, warm windows. */
  --ink:#16181A; --ink-2:#454B50; --ink-3:#5C666D; /* cool inks; ink-3 5.3:1 on field */
  --line:rgba(22,24,26,.12); --line-2:rgba(22,24,26,.07);
  --w-music:#7C5CD6; --w-math:#2E9BD6; --w-med:#4C9A4C; --w-dusk:#8EA4B8; --awn-stroke:#C9CFD3;
  --red:#872338; --red-dk:#691B2B; --red-tint:rgba(135,35,56,.07); /* VINE RED — ours: the valley's wine country, no campus attached (vertical integration, 2026-07-21) */
  /* MICROCRAFT (researched 2026-07-21): shadows are tinted with the FIELD's hue, never black —
     black desaturates a warm field and reads dirty. All uni shadows compose from --shadow-hsl. */
  --shadow-hsl:205deg 10% 32%; /* shadows carry the cool field's hue */
  /* THE NIGHT REGISTER (specced by the 2026-07-21 color research; the DOOR wears it — daily rooms stay pearl) */
  --night:#171310; --night-hi:#1E1813; --night-lo:#241E17;
  --night-text:#E9DFCB; --night-muted:#B3A78F; --night-line:rgba(233,223,203,.14); --night-line-2:rgba(233,223,203,.08);
  --shadow-rest:0 1px 1px hsl(var(--shadow-hsl) / .05), 0 2px 2px hsl(var(--shadow-hsl) / .04);
  --shadow-float:0 1px 1px hsl(var(--shadow-hsl) / .03), 0 4px 8px -4px hsl(var(--shadow-hsl) / .06), 0 16px 24px -8px hsl(var(--shadow-hsl) / .08);

  /* ════ LIVERY · Ginko — "a sunny Sacramento, told in the crew's own line" (redesign 2026-07-01) ════
     Ends the clash with the vibrant robot cast: the UI speaks the crew's own language —
     a warm sun-bleached street, a bold confident ink LINE, sky-blue + sunset-gold pulled from the
     cast, a characterful display face. Defined globally so the uni masthead's Ginko card previews it. */
  /* THE GROUND CAME OFF THE AMBER (2026-09-03). He has rejected it four times in one day —
     "too much yellow", "entrance is still yellowish", "ginko is either bland or yellow, not
     something you want to see daily, think of instagram, youtube, tiktok, browsers, linkedin,
     email... everything needs to be standardized and match eachother".

     Measured against real grounds at the same lightness, in OKLCH chroma:
        Ginko  #FBF3E2  L 0.966  C 0.0240  R−B +25   ← what this was
        Babbel #F6F4EF  L 0.967  C 0.0070  R−B  +7
        LinkedIn        L 0.961  C 0.0029  R−B  +3
        Apple           L 0.971  C 0.0027  R−B  −2
     Three to nine times the chroma of any shipping ground, at the same lightness. That is the
     whole of "yellow": not the hue, the amount.

     NOT NEUTRAL, THOUGH, and Babbel is the evidence — a genuinely warm ground that still measures
     +7. His own ruling says so: "in summer we still have warm colors... it is never pure white."
     So the target is a warm ground at the measured ceiling rather than a cool one: same hue as
     before, a third of the chroma. Ginko still reads warm; it stops shouting.
     Kin: POINTER_JITSU — the number found the ceiling, the eye picked the hue. */
  /* THE GROUND IS DARK AND DENSE (his word through VALE, Axon 18:14; WHAT_GINKO_IS 52-53: "the
     screen is FULL, it is full of PICTURES OF PEOPLE, something is already happening"; ours was a
     cream page with a white card, "none of the four"). The four we are measured against
     (Crunchyroll, Jackbox) put the art on a dark dense ground and the type over it; a cream page
     lights the paper and dims the picture, which is the whole finding of the 18:00 grade: every
     cream surface breaks the FULL law, the bare band at 26 to 30% ink against the doors' 76%.
     The values are the livery's own dark register (livery-ginko.css, computed in OKLCH by kit/mk.py
     and gated in both modes), pointed at the legacy names every room reads, so the rooms move with
     one sheet rather than thirty-three edits. The ratios are the register's, measured there:
     on-ground 12.8:1, on-ground-2 9.3:1, the surface a step lighter than the ground, never a
     white card on a dark page. */
  /* THE NEUTRALS READ THE KIT'S SLOTS, WITH THE DARK REGISTER AS THE FALLBACK (2026-09-17, queue row 22;
     his word 15:20, two faces). Until this line these were hex with no mode, so the light register
     landed in 42a04abf7 reached the three adopted rooms and left the other twenty-seven dark under a
     light attribute (the play dot a dark disc on a light ground, design/tungsten/1-round-light.png).
     Every room that loads the shell loads the livery, and reads whichever face the person has; the
     fallback in each var() is the dark value as it stood, for the five shipped pages that carry no kit
     (index, entrance, store, terms, 404), which keep today's look until they adopt it. */
  --gko-paper:var(--v-surface, #262626); --gko-bg:var(--v-ground, #1B1B1B); --gko-bg2:var(--v-ground, #1B1B1B);
  --gko-ink:var(--v-on-ground, #DEDEDE); --gko-ink2:var(--v-on-ground-2, #BEBEBE);   /* the register's pairs (was #221A10 / #4E402E on cream;
     ink2 had been darkened 2026-08-27 to clear 7:1 on the amber ground, and the dark register's
     9.3:1 clears it on this one). */
  /* AND THE INK THAT SITS ON A FILL IS THE FILL'S OWN (2026-09-16, with the dark ground): the kit
     paints --gko-ink on the act, the gold and the crew's saturated discs, and on this ground that
     ink is light, so a label on amber went light-on-light. One name for that pair, the register's
     on-fill; the kit's filled rules read it and nothing else moves. */
  --gko-ink-on-fill:var(--v-on-fill, #161616); /* 8.2:1 on the act, 8.6:1 on the gold; the kit's ink on a fill in both faces */
  --gko-line-bold:var(--v-line, #BEBEBE);      /* the outline's colour while the outline lasts (RETIRING with --gko-bw, 2026-09-17); the kit's line */
  --gko-line:var(--v-line-quiet, rgba(222,222,222,.16));   /* the one hairline, the kit's, in both faces */
  --gko-sky:#1F7CB0; --gko-sky2:#18688F;       /* open / go — the Sacramento sky, COMMITTED
     2026-08-27. The old #2E9BD6 carried white at 3.10:1, so the front door's primary button, the
     single most important control on the property, failed AA. A polite blue was also the thing
     making the page read cream-on-cream rather than inviting: the fix for both is the same, take
     the blue down until it means something. White on #1F7CB0 is 4.60:1. */
  --gko-gold:#E65179; --gko-gold2:#E65179;     /* the house act (row 11, 2026-10-20: #E65179, hue 344, ink #161616 5.01:1, dark shape 4.77:1, light shape 3.34:1; was #E3A256 / #D97C17 / #8A5309 while the 29 round cards wait on the studio). */
  --gko-gold-text:#9E2448; --gko-sky-text:#1B6D9B; /* TEXT-grade accent siblings (>=4.5:1 on paper+cream, COLOR_JITSU daily-use law: bright accents never carry small text) */
  --gko-red:var(--v-stop, #D6715E);            /* the crossing-guard red, stop / recording, the fault on a field: the kit's stop in both faces (#D6715E dark, #C4482F light; was #E1533A here, a second red) */
  --gko-sun:#F2EEE6; --gko-peach:#F0C6D2;      /* atmosphere (row 11, 2026-10-20: Gump's dial off hue 34 #FFE0A6 to neutral #F2EEE6 under rule 15's <20 chroma; stage tint off #FBCF92 to hue 344 #F0C6D2) */
  --gko-sand:#E8DCC3;                          /* worn chip ground */
  /* ══ THE TOTAL RESKIN: FLAT DESIGN 2.0 AT THE CORE, BAUHAUS HEAVILY MIXED IN (his word, 2026-09-17
     12:55: "not an excuse to produce 2016 design, we still make it look like the top million dollar
     platforms. But I see some neo-brutalism, and nobody does neo-brutalism stuff in platforms, not
     a single soul"; the brief: STRATEGY/luyml/uni/RESKIN_BRIEF.md). The comic-pop offset that
     stood here, a hard 6px throw in the line colour doubling a drawn outline, IS the neo-brutalism
     he saw. Every token the brief names, and where it lives, so a later commit reads and never
     rediscovers:
       ground, surface, field (the two elevations), ink   livery-ginko.css (--v-ground, --v-surface,
                                                          --v-field, --v-on-ground); depth is lightness
                                                          plus the soft shadow below, never a line
       the one accent                                     the ACT, --gko-act / --v-fill, lit by the room
                                                          under [data-light]; go is the act now
                                                          (livery); the blue on three pages leaves
                                                          at the pages' commit
       radius                                             --r-sm / --r-md / --r-lg / --r-pill, three
                                                          and a pill, unchanged
       the shadow set                                     the four layers below, the livery renders
       the space scale                                    --sp-1..6 here, --v-s-* in the standard
       the type scale                                     the six roles (--t-*) below; weight and
                                                          size carry the hierarchy, never a box
     The drawn outline (--gko-bw, --gko-bw-bold) is retired at the controls' commit, where every
     consumer of it is rewritten in one stretch; a border that does a shadow's job is the fault. */
  --gko-shadow-sm:var(--v-lift-1);             /* a pressable thing at rest */
  --gko-shadow:var(--v-lift-2);                /* a card, a window, a sheet */
  --gko-shadow-lg:var(--v-lift-3);             /* the one thing over everything */
  --gko-drop:var(--v-lift-1);                  /* round objects resting on the world */
  /* ── THE STROKE LADDER IS CLOSED (2026-09-17). It was GD01 §8's fraction-of-the-frame rule
     (futowa D/5 to itowa D/80) for the drawn outline, and test/ladder.mjs measured the comic-pop
     outline against it on 2026-08-27 and found the panels off every rung. His word on 09-17 settles
     the question the ladder left open: the outline itself is the neo-brutalism, so no panel gets a
     heavier line and no object keeps its ring. Flat 2.0 draws no outline; a field or a divider
     takes the hairline (--v-line-quiet at --v-line-w) and nothing else takes a line. The four rungs
     nobody consumed (futo, chū, hoso, ito: zero references, measured) are gone; the two below are
     zero, so every outline in the pages is off at once, and the names go the day the pages' rules do. ── */
  --gko-bw-bold:0;     /* the drawn line is gone (the controls' commit, 2026-09-17); 29 page rules still say the name and go as each surface is redressed */
  --gko-bw:0;          /* the same, 49 page rules */
  --gko-room-w:640px; --gko-street-w:760px;    /* a room · the street hub */

  /* ── THE ROOM LIGHTS (GD01 §6, revived 2026-08-20). The walk went flat cream-and-gold when the
     R-0 physics ruling orphaned the old per-room palettes; the Commander: "i am not okay with it
     being all yellow. we need range." Range does NOT mean decoration: a room's light is WHOSE
     ROOM IT IS, or WHERE it stands in the world. Ink, paper, nose red and marquee gold keep their
     jobs unchanged on every one of them; only the hour changes.
     A room sets data-light and the world ground re-tints — one ground declaration, one variable. ── */
  --gko-l-stage:var(--gko-peach);        /* the lamp over the stage: the round, the doors */
  --gko-l-alley:#BFC8E8;                 /* an alley at night: echo */
  --gko-l-garden:#BFD8B8;                /* Osgood's garden: the window, a real call */
  --gko-l-sky:#B8D8EC;                   /* Bolt's sky, daylight: the road, the crossing */
  --gko-l-grape:#CFC2E8;                 /* Gump's grape: the scene, the drift */
  --gko-l-teal:#B2DED8;                  /* Meter's teal: the pocket */
  --gko-l-ember:#F0C0A8;                 /* the last of the sun: the pitch, the club */
  /* the ACT colour of each light: the same hour, at the strength a pressed thing needs.
     Ink on every one of these measures 7.1:1 or better (checked 2026-08-20), so the act is
     always readable whichever room it stands in. */
  /* ══ THE SEVEN ACTIONS EMIT (2026-09-09, his ruling) ═══════════════════════════════════════
     Six of these were paper colours and one was not, and nobody had noticed they were in two
     different registers for months. STAGE IS UNCHANGED below: it was already C* 66 and already
     reading as light. The other six were pastels, which is the colour of a coloured SHEET, on a
     medium that cannot carry the one thing that makes a sheet read as a sheet, its grain.
     Munari, Design as Art, "12,000 Different Colours", p31, read as screens on disk at
     STRATEGY/GUIDES/JITSU/MUNARI_JITSU: "Every colour changes according to the material in which
     it is fixed... A SMOOTH SURFACE REFLECTS THE LIGHT AND THE COLOUR IS MORE INTENSE, WHILE ON A
     ROUGH SURFACE THE COLOUR IS MATT AND MORE SUBDUED." A screen is the smooth case. These were
     specified in the rough one.
     HIS WORDS: "still colored paper colors. that doesn't work on phones... even colored paper has
     grain on it. but how can you put grainy paper on a non-grainy screen, just weird."
     Two things this is NOT. It is not maximum chroma: Munari's sentence is a COMPARATIVE, more
     intense than a rough surface, and the first draft read it as a superlative and produced
     gamut-edge neon. And it is not one lightness band: gold does not live where blue lives, and
     forcing every hue to L* 55 turned ember into a warning and stage into mustard. Each hue takes
     the lightness where it reads as itself at strength.
     THE BOUND IS EACH OTHER, NOT THE GAMUT. At full chroma alley and sky collapse into the same
     blue, and seven lights that cannot be told apart are not seven lights. Nearest pair is now
     ember and stage at dE 28, which are meant to be neighbours. */
  --gko-a-stage:var(--gko-gold);  --gko-a-alley:#88AFFF;  --gko-a-garden:#83C575;
  --gko-a-sky:#48BFF5;            --gko-a-grape:#BF9DF6;  --gko-a-teal:#1DCBBC;   /* grape was #7550D8: the
     ink on it measured 3.4:1 (Collagen, 2026-09-17), under the AA the note above claims for all seven; same hue and
     chroma, L .55 to .62, ink 4.6:1. Every other act measured today: alley 5.5, garden 6.1, sky 7.4, teal 5.6,
     ember 6.5, stage 8.6. */
  --gko-a-ember:#F5956A;
  /* ONE LIGHTNESS FOR THE SEVEN (VALE's ruling 2026-09-17 18:30, queue row 56): the six were at L .62 to .66 under a
     stage at .76, six lamps darker than the seventh; a lamp is luminous. Re-solved at .76 with chroma inside the band,
     ink on each 8.1:1 or better and each 7.7:1 or better on the ground, measured before landing; the same seven in
     livery-ginko.css's dark lamps. */
  /* THE CEILING, 2026-09-17 (VALE, his eye on the contact sheet: "that toxic green that makes no
     sense"). Four of the seven acts stood outside the house's own band - COLOR_JITSU puts an
     interface accent at OKLCH chroma 0.10 to 0.15, and alley measured .193, garden .198, grape .190,
     ember .175, while the room lights in livery-ginko.css sat correctly at .08 to .12. The cause is
     in the note above: the seven were tuned to be maximally tellable APART, which walks to the
     gamut edge, and the two worst landed on borrowed system colours - #0390FF is the iOS blue and
     #2FAC2A is the call-answer green, which is why the screen read as somebody else's app. Each is
     now pulled to chroma .14 at its own hue and lightness, so nothing moves but the intensity:
     alley #0390FF -> #4792E1, garden #2FAC2A -> #58A553, grape #9167EA -> #8D72D1, ember #F7753A ->
     #E88155. Ink on the fill measured after: alley 5.6, garden 6.0, grape 4.7, ember 6.6, each at
     or above what it was. Nearest pair of the seven afterwards is sky-alley at dE 0.085 in OKLab,
     so they are still seven lights. test/chroma.mjs is the instrument and it fails over .15. */
  --gko-act:var(--gko-a-stage);   /* a room's light sets this; .go reads it */
}
/* THE LIGHT FACE'S ACTS (2026-09-17, queue row 27): the same seven hues at the lightest value that stands 3:1 on the light
   ground as a shape and still carries the dark ink at AA (measured, the reasons in livery-ginko.css beside the same seven,
   which the kit blocks read); alley, grape and teal barely move, the warm and light ones come down by value. */
[data-mode="light"]{
  --gko-a-stage:#E65179; --gko-a-alley:#E65179; --gko-a-garden:#E65179; --gko-a-sky:#E65179;
  --gko-a-grape:#E65179; --gko-a-teal:#E65179; --gko-a-ember:#E65179;   /* BY DAY THE ACT IS ONE HOUSE COLOUR, the stage's rose-red #E65179 (row 11, 2026-10-20; VALE's ruling 19:50: on white seven pigments read as six brands, and the references spend their colour on the act alone); the room shows in its sign, its figure and its pictures; the seven pigments the signs are cut from, and the study, are in livery-ginko.css */
}
:root{
  --gko-light:var(--gko-l-stage);   /* a room overrides this; the world does the rest */
  --gko-dusk:color-mix(in srgb, var(--gko-light) 52%, var(--gko-bg));
  --gko-dusk-deep:color-mix(in srgb, var(--gko-light) 44%, var(--gko-bg2));

  /* ── THE TYPE SCALE (GD01 · minted 2026-08-20). Six named roles, because 44 ad-hoc clamp()
     sizes were counted across 21 rooms: the same intent reinvented with different numbers is a
     TIC (TIC_JITSU), and the vacuum where a scale should be is what fine print filled.
     A room chooses a ROLE. A room that needs a size not on this list is telling you the scale
     is wrong; fix the scale, never the room. ── */
  --t-voice:clamp(26px,6.2vw,44px);   /* the room's one sentence. THE FLOOR OPENED A STEP, 28 to 26
     (VALE 13:36, RESKIN_CONTROLS rule 7): a cue past three lines at 390 was stepping down to the say
     rung and stopped being the room's voice; measured on tonight's 69-character cue in every wrap
     mode, 28px is four lines in the gutters and 26px is three. */
  --t-say:clamp(22px,4vw,34px);       /* words being spoken: a cue, a line, a quote */
  --t-lead:clamp(17px,2.6vw,20px);    /* the sentence under the voice */
  --t-read:16px;                      /* body */
  --t-label:12.5px;                   /* the kicker and other small-caps labels */
  --t-datum:clamp(44px,12vw,86px);    /* a number that IS the screen: the clock, the odometer */
  --gko-disp:"Bricolage Grotesque",var(--font);
  --gko-body:"Hanken Grotesk",var(--font);

  /* focus ring colour — overridden per livery below */
  --focus:var(--red);

  /* ════ TIER 2 · SEMANTIC SLOTS (added 2026-07-07, per BIG_GINKO_SYSTEM) ════
     Components consume ONLY these slots (--s-…) + structure tokens (t, r, ease).
     A livery is a [data-skin] block assigning slots from its primitives;
     a room re-tints via --room-* (falls back to the livery's slots).
     Default assignment = the uni livery. */
  --s-surface:var(--pearl-hi);          /* cards / paper things sit on */
  --s-field:var(--pearl);               /* the page ground */
  --s-field-2:var(--pearl-lo);
  --s-ink:var(--ink);
  --s-ink-muted:var(--ink-2);
  --s-line:var(--ink);                  /* the drawn outline colour */
  --s-line-soft:var(--line);
  --s-accent:var(--red);
  --s-accent-2:var(--red-dk);
  --s-on-accent:#fff;
  --s-pop:var(--shadow-float);          /* the raised thing: the soft set above, never an offset (the reskin, 2026-09-17) */
  --s-pop-sm:var(--shadow-rest);
  --s-disp:var(--font);
  --s-body:var(--font);
}

/* a Ginko page declares its livery once — the slots re-dress, the grammar stays */
[data-skin="ginko"]{
  --focus:var(--gko-gold2);
  --s-surface:var(--gko-paper);
  --s-field:var(--gko-bg2);
  --s-field-2:var(--gko-bg);
  --s-ink:var(--gko-ink);
  --s-ink-muted:var(--gko-ink2);
  --s-line:var(--gko-line-bold);
  --s-line-soft:var(--gko-line);
  --s-accent:var(--gko-sky);
  --s-accent-2:var(--gko-sky2);
  --s-on-accent:var(--gko-paper);
  --s-pop:var(--v-lift-2);
  --s-pop-sm:var(--v-lift-1);
  --s-disp:var(--gko-disp);
  --s-body:var(--gko-body);
}

/* ════ ROOM PALETTES — each room wears a crew member's colours (v3 mockups, approved) ════
   A room sets data-room on its container; components pick up --room-* with livery fallback. */
[data-skin="ginko"]{ --room-accent:var(--s-accent); --room-field:var(--s-field); --room-field-2:var(--s-field-2); }
[data-room="today"], [data-room="exhale"]{ --room-accent:#E8912D; --room-field:#FFF6E0; --room-field-2:#FFEDC4; --s-on-accent:#2A2013; }  /* sunrise gold — light accent carries INK text */
[data-room="rep"]   { --room-accent:#2E9BD6; --room-field:#E9F5FD; --room-field-2:#D5EBFA; }  /* Bolt's sky */
[data-room="voices"]{ --room-accent:#7C5CD6; --room-field:#F1ECFC; --room-field-2:#E4DBF8; }  /* Gump's grape */
[data-room="clip"]  { --room-accent:#F0703A; --room-field:#FFEFE5; --room-field-2:#FFDFCC; }  /* sunset coral */
[data-room="oneplay"]{--room-accent:#3D5AC8; --room-field:#E9EDFA; --room-field-2:#D7DEF5; }  /* night indigo */
[data-room="scene"] { --room-accent:#9B59C8; --room-field:#F5ECFA; --room-field-2:#EBDCF6; }  /* Ring's purple */
[data-room="pocket"]{ --room-accent:#1FA9A0; --room-field:#E4F6F4; --room-field-2:#CFEFEB; }  /* Meter's teal */
[data-room="mirror"]{ --room-accent:#4C9A4C; --room-field:#EBF6E6; --room-field-2:#DCEFD2; }  /* Osgood's garden */

/* ── shared a11y: a visible keyboard focus ring on every interactive thing ── */
/* THE RING FOLLOWS THE SHAPE (2026-09-17, Tungsten 3, plate 3-rec-focus-echo): border-radius:4px
   stood here and squared the ring on the record disc's circle; an outline follows the element's
   own radius, so the line goes and the disc's ring is a circle. WCAG 2.4.13: a 2 CSS px perimeter. */
a:focus-visible, button:focus-visible, [tabindex]:focus-visible{
  outline:2px solid var(--focus); outline-offset:3px;
}

/* ── shared: honour reduced-motion everywhere, once ── */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{ animation:none !important; transition:none !important; }
  /* entrance patterns start at opacity:0 and rely on their animation to appear; with
     animations off they must land visible (found 2026-08-19: voices/road rendered blank) */
  .enter{ opacity:1 !important; transform:none !important; }
}

/* AND THE SAME STOP, REACHABLE BY SOMEBODY WHO NEVER TOLD THEIR MACHINE (2026-09-03).
   WCAG 2.2.2 Level A: anything that moves automatically for more than five seconds needs a
   mechanism to stop it. Four never-ending animations on /ginko/round meet all three conditions,
   and the media query above covers only people who have already set a system preference. The
   gap is the person who has not — and they are the ones who need it while uncomfortable.

   THIS IS THE SAME RULE, NOT A SECOND IMPLEMENTATION, and that matters more than the
   duplication it costs. The `.enter` line is here because entrance patterns start at opacity:0
   and rely on their animation to appear: without it, turning motion off renders BLANK PAGES,
   which is the bug voices and road shipped in August. A separate implementation would have
   re-earned it, in the exact place where the person who most needs the control is the one who
   gets a blank screen. If you change one block, change both — they are one rule wearing two
   triggers, and shell.js's `still` control is what sets the attribute. */
:root[data-still] *, :root[data-still] *::before, :root[data-still] *::after{
  animation:none !important; transition:none !important; }
:root[data-still] .enter{ opacity:1 !important; transform:none !important; }

/* THE HIDDEN ATTRIBUTE MEANS HIDDEN (2026-08-26). `hidden` is a semantic promise in the markup,
   but the UA's `display:none` is the weakest possible rule, so ANY component that sets a display
   (every flex row, every grid) silently defeats it. Five pages had each patched this for their own
   element — pocket twice, keynote, tapes, words (whose comment says exactly why) — and the one
   place nobody thought to patch shipped a blank ticket stub sitting under a recovery form. One
   rule, once. !important is right here: a display that overrides `hidden` is a defect, never an
   intention. */
[hidden] { display: none !important; }

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   THE SCALE — one root, named steps, nothing between them.       Added 2026-09-03. ADDITIVE:
   nothing above is removed and no page changes until it opts in, because a token file is read by
   every shipped page and thirty pages cannot be re-measured in one commit.

   WHY, MEASURED. Ginko's shipped pages carry 28 distinct pixel font-sizes, 120 distinct padding
   values, 31 radii, and no spacing token of any kind. 61% of the font-sizes are raw px rather than
   derived from anything, so they are 28 independent decisions that can only drift; Beatbump, doing
   the same job, expresses 83% of its 46 sizes off one --base-font-size and resizes the whole
   product from a single value.

   AND A CORRECTION TO MY OWN ARGUMENT, made before it got written into a token. I had said the 28
   sizes form a half-pixel ladder in which "no two steps are distinguishable". That is a claim about
   perception and I cannot support it — Butterick says the opposite for print body text:
     "Try sizes down to 10 point, including intermediate sizes like 10.5 and 11.5 point—half-point
      differences are meaningful at this scale."   (Practical Typography, "Point size", read
      2026-09-03, on disk at STRATEGY/GUIDES/SOURCES/typography/butterick_point-size.txt)
   The real fault is not that 13px and 13.5px look alike. It is that NOTHING ASSIGNS A SIZE TO A
   ROLE, so the same role takes a different value on each page and the site cannot match itself.
   A ramp is not a perception aid; it is a rule about what a thing is.

   THE ROOT is 17px because that is where the web's readable band sits:
     "In print, the optimal point size for body text is 10–12 point. On the web, the optimal size
      is 15–25 pixels."                                (Butterick, "Point size", read)
   Everything below is rem off that root, so changing this ONE line resizes the product. */
:root{
  /* DERIVED BY calc, NOT BY rem, AND THAT IS THE WHOLE POINT (corrected 2026-09-03). The first
     version wrote the steps in rem and then set html{font-size:var(--root)} to make them mean 17px.
     That works and it is not additive: 33 shipped pages already use rem or em, so one line would
     have moved every one of them 6% without anybody asking for it, while I was promising the token
     file changed nothing. calc off --root gives the same single point of control with no blast
     radius — change this number and the scale moves; nothing that does not use the scale notices. */
  --root: 17px;

  /* Seven steps, ratio 1.25 (the major third). Named for role, not for size. */
  --step-fine:  calc(var(--root) * 0.82);   /* ~14px · stamps, legal, tabular labels — never running text */
  --step-body:  var(--root);      /* 17px  · everything a person reads */
  --step-lead:  calc(var(--root) * 1.25);   /* ~21px · standfirst, the line under a headline */
  --step-head:  calc(var(--root) * 1.563);  /* ~27px · section heads */
  --step-title: calc(var(--root) * 1.953);  /* ~33px */
  --step-loud:  calc(var(--root) * 2.441);  /* ~42px */
  --step-voice: calc(var(--root) * 3.052);

  /* ONE FLUID STEP, ADDED DELIBERATELY (2026-09-03). G22 refused entrance.html's headline for
     using clamp(32px,7.4vw,60px) — my own gate refusing my own work, which is what it is for. A
     page that must fit ONE SCREEN at 360 and at 1440 genuinely needs a display size that moves;
     a fixed step is too big for the phone or too small for the desktop. So the scale gains the
     step rather than the page gaining an exemption. It travels between --step-title and
     --step-voice and lands on neither by accident: those are its own ends. */
  --step-display: clamp(calc(var(--root) * 1.953), 7.4vw, calc(var(--root) * 3.052));  /* ~52px · one per screen, at most */

  /* ONE STEP ABOVE THE RAMP, FOR A HEADLINE THAT OWNS A COLUMN (2026-09-03). The entrance's left
     column at 1440 held ~300px of nothing under the button, and the diagnosis was not that the
     block sat in the wrong place: --step-display tops out at 52px, and its 7.4vw is measured
     against the WHOLE VIEWPORT while the headline lives in a 630px column. The headline was too
     small for its room, so the room read empty. Scale contrast is the thing that buys presence;
     the alternative is buying it with colour, which is the fault he named on this very page.
     Continues the ramp's own 1.25 ratio (…33 · 42 · 52 · 65) — ONE step, not two:
     81px was measured against the rendered column and broke 'Get genuinely good' across two lines,
     which is a worse headline than a smaller one rather than inventing a size:
     the scale grows by its own arithmetic or it is not a scale. */
  --step-hero:  calc(var(--root) * 3.815);  /* ~65px · a headline that has a column to itself */

  /* Line spacing: "For most text, the optimal line spacing is between 120% and 145% of the point
     size." (Butterick, "Line spacing", read.) Tight for display, open for reading. */
  --leading-read: 1.42;
  --leading-tight: 1.1;

  /* Measure: "Aim for an average line length of 45–90 characters, including spaces."
     (Butterick, "Line length", read.) 66ch sits mid-band; --measure-tight for a caption column. */
  --measure: 66ch;
  --measure-tight: 48ch;

  /* Spacing. One base, six steps, and the six replace 120 hand-written paddings. */
  --sp-1: calc(var(--root) * 0.25);   /* 4  */
  --sp-2: calc(var(--root) * 0.5);    /* 8.5 */
  --sp-3: var(--root);      /* 17 */
  --sp-4: calc(var(--root) * 1.5);    /* 25.5 */
  --sp-5: calc(var(--root) * 2.5);    /* 42.5 */
  --sp-6: calc(var(--root) * 4);      /* 68 */

  /* Radius: three, from 31. */
  --rad-sm: 6px;
  --rad-md: 14px;
  --rad-lg: 22px;

  /* THE TOUCH TARGET, AND WHICH BAR THIS IS — read the level before you change the number.
     WCAG 2.2 SC 2.5.8 Target Size (Minimum), Level AA, new in 2.2:
       "The size of the target for pointer inputs is at least 24 by 24 CSS pixels"
     WCAG 2.2 SC 2.5.5 Target Size (Enhanced), Level AAA:
       "The size of the target for pointer inputs is at least 44 by 44 CSS pixels"
     (w3.org/TR/WCAG22, pulled and on disk at STRATEGY/GUIDES/SOURCES/w3c/wcag22.txt.)

     Ginko holds the AAA figure, deliberately: the audience is adult learners on phones, often
     one-handed on a bus, and the product is nightly. 24 is the floor a page must clear to conform;
     44 is the size a thumb actually hits. This was nearly written in as "the floor everyone agrees
     on" — it is not, it is the enhanced level, and the next person to touch it should be choosing
     rather than inheriting. */
  --tap: 44px;
  --tap-conform: 24px;

  /* ══ AAA FOR THE THUMB, AA FOR THE EYE, AND THAT IS A DECISION (2026-09-09) ════════════════
     The paragraph above holds the ENHANCED figure for tap targets on purpose. The seven room
     actions do NOT hold the enhanced figure for text on their fill: they run 5.5:1 to 8.6:1, two
     over 7 and five between 4.5 and 7, with alley the floor at 5.5.
     THAT LOOKS LIKE A CONTRADICTION AND IT IS A CHOICE. An emitting fill at strength sits exactly
     where neither black nor white reaches 7:1; alley cannot be fixed by flipping its ink, because
     white on that blue is 3.3:1, which is worse. The alternative was seven duller fills that clear
     7:1 and read as pigment rather than light. He was shown both, with these numbers, and took the
     light: "emission at AA".
     So do not "fix" this to match the line above. A person reading AAA-for-the-thumb should find
     AA-for-the-eye in the same breath, with the reason, rather than discover it as an oversight. */

  /* ══ THE FIELD CARRIES NO COLOUR (2026-09-03) ══════════════════════════════════════════════
     MEASURED, from the rendered pages of the three products he named — not from their
     stylesheets, because LinkedIn's stylesheet declares warm creams its page never uses as a
     ground and I nearly reported that as a finding:

       youtube.com    #ffffff  C 0.000   ·  #0f0f0f  C 0.000
       instagram.com  #F0F2F5  C 0.005   ·  #1f1f22  C 0.006
       linkedin.com   #ffffff  C 0.000   ·  #f3f2f0  C 0.003
       ginko          #FBF3E2  C 0.024   ← five times the ceiling of all six

     Nothing they ship carries colour in the ground, light or dark, warm or cool. Ours did, and
     that is the fault behind "too much yellow" said three times — not the hue, and not the
     amount. Colour was in the one place none of them ever puts it.

     THE RULE, and it is a rule rather than a value so it holds a range: COLOUR LIVES IN THE
     MARK, THE ACTION AND THE CONTENT. THE FIELD CARRIES NONE. A photograph may be any colour a
     photograph is; a rice field in July and a flooded bypass in January are both CONTENT, and
     the frame that holds them does not move with the season. Warm is not banned anywhere it
     belongs — only in the empty field.

     Chroma ceiling for anything below: 0.006. */
  /* THE FIELD READS THE KIT'S FACE (2026-09-17, queue row 28): the entrance, the one page a stranger buys on, kept
     these as hex with no mode and was a white page between two dark ones on a phone that opened dark. Each reads the
     livery's slot now, with the 09-03 light values as the fallback for a page that carries no kit; the chroma rule
     above still holds in both faces (the kit's neutrals are chroma 0). */
  --field:      var(--v-ground, #FAFAF9);
  --field-band: var(--v-surface, #F2F2F0);
  --field-edge: var(--v-line-quiet, #DEDEDB);
  --field-ink:  var(--v-on-ground, #16181A);
  --field-ink2: var(--v-on-ground-2, #4A4E52);
  --act:        var(--v-fill, #15618C);        /* the ACTION: the room's act in the kit, the 09-03 blue without it */
  --on-act:     var(--v-on-fill, #FFFFFF);     /* the ink that sits on the act is the act's own */
  --act-text:   var(--v-fill-text, #12557A);   /* the act at text grade: a link, a figure */
  --figure:     var(--v-fill-text, #7A4A08);   /* the price, the one warm note, at text grade */
}
