/* ============================================================================
   ROS — CANONICAL DESIGN TOKENS  (single source of truth) — DECISIONS LOCKED
   ----------------------------------------------------------------------------
   Drop-in path:  src/ros/shell/public/tokens.css
   Load ONCE in the shell, BEFORE every module's injected <style>.
   The design half of the single-source-of-truth standing law.

   JOE-LOCKED RULES (2026-06-14):
   • NO PILLS. EVER. Anything that isn't a button is a CHIP (radius 7px). The
     fully-round 999px "pill" is banished. (Round avatars/dots use 50%, not a
     pill.)
   • NO LIGHT. ZERO light or white pages in the OS. (Light lives only in the
     scoped-out funnel.) → there is no on-light text token.
   • VIBRANCY PROTECTED — gradients + glows are first-class tokens, never
     flattened. Consolidate accidental drift, never mute the brand.
   • ADDITIVE — every existing shell token name is preserved verbatim, so the
     1,019 live var(--) usages keep working. Phase 0 is zero-risk.

   DECISIONS — RESOLVED:
     D1 amber = #FFB454 (locked).  D2 success=#40EAA8, money kept separate
     #34D399.  D3 indigo #6366F1 promoted (6th accent).  D4 NO light, ever.
     D5 glows derived via color-mix() = never drift muted. Confirmed.

   🪦 FONT FLOOR: REMOVED 2026-09-10 on Joe's order. THERE IS NO MINIMUM FONT SIZE IN ROS.
   "12px is GIGANTIC on this system… I've literally been changing fonts for months."
   The TYPE SCALE below is a vocabulary for picking the right size, never a lower bound.
   ✅ WHAT GOVERNS INSTEAD (Joe): "use a button size that's already being used on that page…
   the same font size that's being used on that page in buttons. We need to keep it symmetrical."
   THE NEIGHBOUR IS THE AUTHORITY — the test is whether it looks like it was always there.
   ============================================================================ */

:root {

  /* ---- THE BROWSER'S OWN CONTROLS ------------------------------------------
     ⬜ Joe, standing and nuclear: "raw browser input is never acceptable. Only ROS styling is
     acceptable ever" — "I've had this since flippin' March… 150 times."
     🩸 THE LAST HIDING PLACE. A dark page does NOT make Chrome draw dark CONTROLS. It keeps its
     own light rendering for the parts IT paints and we do not: the calendar and clock glyphs in
     a date/time field and the picker panels they open, the scrollbars, the checkbox and radio
     boxes. There is no white literal to grep for any of it — it is the browser's default, not
     our CSS — which is exactly why it survived every white sweep.
     📊 MEASURED 2026-09-01: `color-scheme` appeared ONCE in all of src/ros — scoped to
     `.fbv .sfld input` in marketing-facebook.js — beside 46 native date/time inputs across 17
     files. Somebody hit this, fixed their own screen, and never generalised it. That one scoped
     rule is a WORKING SPECIMEN: proof the fix works, sitting next to 46 that never got it.
     🔒 ONE LINE, HERE, BECAUSE THIS IS WHERE THE OS IS DEFINED. Every OS and admin surface links
     tokens.css and every one of them is dark by law. The scoped-out design languages
     (advertising/funnels, client-chat, sites/templates) reference this file ZERO times and serve
     their own documents, so they are untouched — measured, not assumed.
     ⚠️ AND IT IS INHERITED AND PER-DOCUMENT, WHICH CUTS BOTH WAYS. Anything that must stay LIGHT
     declares so itself: the three email/document PREVIEW frames in contacts/public/contact-detail.js
     and the signature-editing frame in email/public/signature-image.js. ⛔ Do not remove those —
     a preview of an email that will be read on white must be rendered on white. */
  color-scheme: dark;

  /* ---- FONT ---------------------------------------------------------------- */
  --font: 'Inter','Outfit',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
  /* Q107 — the mono family EXISTED in the tree and had no token: `.dma-link` (the demo
     magic link an operator copies) reached for `var(--font-mono)`, which was defined
     nowhere, so it rendered in the inherited sans. Family taken from the established
     usage in company-create.js. Anything hardcoding 'JetBrains Mono' can migrate here. */
  --font-mono: 'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;

  /* ---- SURFACES (one elevation ladder — collapses 133 near-dupe navies) ----- */
  --bg:            #1E1B3E;   /* app background                                 */
  --surface:       #1A2547;   /* raised card / panel   (legacy --panel-top)     */
  --surface-sunk:  #0E1530;   /* recessed well         (legacy --panel-bot)     */
  /* 🎨 ROW 004 / #1549 — THE BLACK BOX WAS A HUE PROBLEM, NOT A DARKNESS PROBLEM.
     Joe: "black boxes are NOT part of ROS styling… I want them all gone… just a different
     shade to the color already present."
                        hue   sat  light   reads as
       --surface        225°  46%   19%    the panel
       --surface-sunk   226°  55%   12%    a WELL CUT INTO the panel — ⭐ HE APPROVED THIS ONE
                                           by pointing at it (blackbox.jpg, Settings→Leads):
                                           "this is a nice box and fits well with our own style"
       --surface-row    243°  39%    9%    ⬅ 18° OFF-HUE. A FOREIGN OBJECT SITTING ON the panel.
     ⇒ Same darkness family, different COLOUR family — which is why one reads as depth and the
     other reads as a black box. The fix is the panel's own hue at lower lightness, below.
     ⛔ --surface-sunk IS NOT TOUCHED and must not be "completed" later: he approved it on
     screen, and it is also every text input's background (os-base .ui-field, 318 uses) where a
     well is the CORRECT affordance for a field. */
  --surface-row:   #16203D;   /* list / table rows — 225° 47% 16%, derived from --surface   */
  --surface-deep:  #06121F;   /* deepest insets                                */
  --panel-top:     #1A2547;   /* legacy alias (preserved)                       */
  --panel-bot:     #0E1530;   /* legacy alias (preserved)                       */
  --recv:          #2b2f5e;   /* chat receive bubble                           */
  --recv-2:        #333877;   /* chat receive bubble gradient end              */

  /* ---- TEXT (4-stop ladder — 4th tier promoted) ---------------------------- */
  --text:          #F0F4FB;   /* primary                                       */
  --text-2:        #B5C0DD;   /* secondary                                     */
  --text-3:        #8AA4C5;   /* tertiary / muted                              */
  --text-4:        #5E7390;   /* faded / disabled (PROMOTED)                    */

  /* ---- BRAND ACCENTS (6 — keep them LOUD) ---------------------------------- */
  --cyan:          #00D4FF;
  --purple:        #B388FF;
  --emerald:       #40EAA8;
  --gold:          #E8B968;
  --amber:         #FFB454;   /* D1 LOCKED                                      */
  --indigo:        #6366F1;   /* D3 promoted 6th accent                         */

  /* ---- ACCENT-TEXT (opaque, readable accent-colored text) -------------------
     The missing sibling to the transparent -tint/-line/-glow mixes: an OPAQUE
     accent color tuned for legible TEXT on the dark surfaces (the base accents
     are tuned as fills/strokes, not body text). Shared vocabulary the system
     was missing — modules were each hand-rolling their own lightened accent
     text (the companies cockpit alone carried ~27 such literals). One per
     accent that earns reuse. Parity-exact to the values they consolidate.      */
  --cyan-text:     #9EE8FF;
  --purple-text:   #D2B8FF;
  --emerald-text:  #7FF0C4;
  --gold-text:     #F0CB7E;

  /* ---- ACCENT VARIANTS (derived — absorb the 4,630 rgba glow tail) ----------
     -tint = soft fill · -line = accent border · -glow = the box-shadow color.
     color-mix keeps them locked to the base accent (D5). Usage:
       background: var(--cyan-tint);  border-color: var(--cyan-line);
       box-shadow: 0 0 18px var(--cyan-glow);                                   */
  --cyan-tint:     color-mix(in srgb, var(--cyan) 14%, transparent);
  --cyan-line:     color-mix(in srgb, var(--cyan) 32%, transparent);
  --cyan-glow:     color-mix(in srgb, var(--cyan) 42%, transparent);
  --purple-tint:   color-mix(in srgb, var(--purple) 16%, transparent);
  --purple-line:   color-mix(in srgb, var(--purple) 34%, transparent);
  --purple-glow:   color-mix(in srgb, var(--purple) 45%, transparent);
  --emerald-tint:  color-mix(in srgb, var(--emerald) 14%, transparent);
  --emerald-line:  color-mix(in srgb, var(--emerald) 32%, transparent);
  --emerald-glow:  color-mix(in srgb, var(--emerald) 42%, transparent);
  --gold-tint:     color-mix(in srgb, var(--gold) 16%, transparent);
  --gold-line:     color-mix(in srgb, var(--gold) 34%, transparent);
  --gold-glow:     color-mix(in srgb, var(--gold) 42%, transparent);
  --amber-tint:    color-mix(in srgb, var(--amber) 16%, transparent);
  --amber-line:    color-mix(in srgb, var(--amber) 34%, transparent);
  --amber-glow:    color-mix(in srgb, var(--amber) 42%, transparent);
  --indigo-tint:   color-mix(in srgb, var(--indigo) 16%, transparent);
  --indigo-line:   color-mix(in srgb, var(--indigo) 34%, transparent);
  --indigo-glow:   color-mix(in srgb, var(--indigo) 45%, transparent);

  /* ---- STATUS ------------------------------------------------------------- */
  --success:       #40EAA8;   /* D2 (folds in #3DD68C)                          */
  --danger:        #FF6347;
  --warning:       #FFB454;
  --info:          #5B8DEE;
  --danger-tint:   color-mix(in srgb, var(--danger) 16%, transparent);
  --danger-line:   color-mix(in srgb, var(--danger) 34%, transparent);
  --danger-glow:   color-mix(in srgb, var(--danger) 42%, transparent);
  --success-tint:  color-mix(in srgb, var(--success) 14%, transparent);
  /* Q107 — the ONE missing member of this family: every other status colour has a
     -line (danger, info, emerald, cyan, purple, gold, amber, indigo) and success did
     not, so `.cw-rchip` in admin/carriers drew no border at all. Same 34% as its
     siblings — a gap in the set, not a wrong reference. */
  --success-line:  color-mix(in srgb, var(--success) 34%, transparent);
  --success-glow:  color-mix(in srgb, var(--success) 42%, transparent);
  --info-tint:     color-mix(in srgb, var(--info) 16%, transparent);
  --info-line:     color-mix(in srgb, var(--info) 34%, transparent);

  /* ---- DECISION-LOCKED SEMANTICS (carry meaning — kept distinct) ------------ */
  --deficit:       #FF6347;
  --winback:       #FF9F6B;
  --prospected:    #5B8DEE;
  --money:         #34D399;   /* D2 kept separate from --success                */
  --rose:          #F472B6;
  --drifting:      #FFB068;

  /* ---- LINES / BORDERS ----------------------------------------------------- */
  --line:          rgba(180,210,255,0.12);
  --line-soft:     rgba(180,210,255,0.08);
  --line-strong:   rgba(180,210,255,0.22);
  --line-hover:    rgba(180,210,255,0.32);

  /* ---- AUTOFILL ------------------------------------------------------------
     What an autofilled input must look like. Chrome paints autofilled fields
     near-WHITE and forces its own text color; os-base.css suppresses that using
     these. They are tokens rather than literals so a module whose inputs sit on a
     different surface can override --autofill-bg on its own scope instead of
     fighting the shared rule. Defaults match .ui-field, which is what the large
     majority of OS inputs (and every .a2r-input on the A2P form) already use. */
  --autofill-bg:   var(--surface-sunk);
  --autofill-text: var(--text);

  /* ---- GRADIENTS (first-class — the pop; never hand-roll these) ------------- */
  --grad-brand:    linear-gradient(135deg, var(--cyan), var(--purple));
  --grad-brand-cp: linear-gradient(150deg, var(--cyan), var(--purple));
  --grad-panel:    linear-gradient(180deg, var(--surface), var(--surface-sunk));
  --grad-rail:     linear-gradient(180deg, #191634 0%, #14122C 100%);
  --grad-header:   linear-gradient(180deg, rgba(91,169,217,0.10), rgba(30,27,62,0.7));
  --grad-money:    linear-gradient(135deg, var(--emerald), #2BD39A);
  --grad-gold:     linear-gradient(135deg, var(--gold), var(--amber));
  --grad-deficit:  linear-gradient(135deg, var(--deficit), #FF8A6B);
  /* ☢️ THE CANVAS WASH — a MODULE-ACCENTED two-radial ground. ⭐ PARAMETERISED, NEVER COLOURED:
     it paints whatever the consumer sets as `--wash-1` / `--wash-2`, so Marketing (purple), Vouch
     (emerald), settings (indigo) and admin (gold) all get the same composition in their own hue.
     ⛔ DO NOT hard-code an accent into it — that is how a shared token becomes one module's.
     🔒 WHY IT IS A TOKEN AND NOT TWO LINES IN A MODULE: Joe, today — *"we just create a styling
     bucket, and nothing ever gets used outside of your styling bucket"* — and this header's own
     law, three lines up: gradients are first-class, never hand-rolled. A wash every module will
     eventually want, written inline in ONE module, is the next thing that drifts.
     ⓪ Falls back to transparent, so a consumer that sets neither gets no wash rather than a
     black box — an unset parameter must not paint something nobody chose.
     📌 SECOND CALLER, NOT CONVERTED HERE: settings.css does this inline on `.rs-canvas::before`
     and predates the ratchet. Whoever takes that row should point it at this token. */
  --grad-canvas-wash:
    radial-gradient(1000px 340px at 16% -12%, var(--wash-1, transparent), transparent 58%),
    radial-gradient(620px 380px at 98% 104%, var(--wash-2, transparent), transparent 66%);
  /* Task-state chips (Broker Hub board). ⛔ AN ACCENT IS A SOLID LIT FILL, NEVER A WASH — these are
     the three lit fills the board uses to say where a task stands, defined here because a gradient
     is a first-class token and the design guard requires them sourced from one. Purple = being
     worked right now; cyan = in process; gold = waiting on Joe's eyes; emerald = done. */
  --grad-chip-purple:  linear-gradient(180deg, color-mix(in srgb, var(--purple) 38%, transparent), color-mix(in srgb, var(--purple) 13%, transparent));
  --grad-chip-cyan:    linear-gradient(180deg, color-mix(in srgb, var(--cyan) 40%, transparent), color-mix(in srgb, var(--cyan) 14%, transparent));
  --grad-chip-gold:    linear-gradient(180deg, color-mix(in srgb, var(--gold) 42%, transparent), color-mix(in srgb, var(--gold) 15%, transparent));
  --grad-chip-emerald: linear-gradient(180deg, color-mix(in srgb, var(--emerald) 36%, transparent), color-mix(in srgb, var(--emerald) 12%, transparent));
  /* ⭐ VOUCH — the module about PAYING PEOPLE, so its identity is MONEY/EMERALD rather than
     settings' indigo. Joe locked the design 2026-09-14: *"I love the glowing elements. I love the
     colour."* ⛔ Defined HERE, not in the module, for the reason the block above states: a gradient
     is a first-class token and the design guard requires them sourced from one. The module writing
     these inline is the same drift `--grad-chip-*` exists to prevent.
     ① THE CANVAS WASH — two radials, emerald high-left, gold low-right. ⭐ THIS is the single
     device that stops the page reading "just dark"; the shape is settings' `.rs-canvas::before`
     with Vouch's own two hues. ⛔ Never dropped, never flattened to a solid.
     ② THE LIT FILL — top-lit, for the one pressable money control on a surface (Record a payment,
     Open). ⓪ AN ACCENT IS A SOLID LIT FILL, NEVER A WASH. `--grad-money` stays the 135° BADGE
     fill; this is its pressable sibling and the two are not interchangeable. */
  --grad-vouch-canvas: radial-gradient(1000px 340px at 14% -12%, var(--emerald-tint), transparent 58%),
                       radial-gradient(620px 380px at 98% 104%, var(--gold-tint), transparent 66%);
  --grad-money-lit:    linear-gradient(180deg, color-mix(in srgb, var(--emerald) 72%, var(--text)), var(--emerald) 55%, color-mix(in srgb, var(--emerald) 82%, var(--surface-deep)));
  /* 🔒 JOE RULED THIS ON 2026-09-06, choosing the QUIET variant from three rendered candidates.
     ⭐ HIS REASON IS NOT DERIVABLE FROM THE PALETTE, WHICH IS WHY A MOCKUP DECIDED IT AND NOT A
     MEASUREMENT: A REJECTION IS A VERDICT, NOT AN ALARM. He makes many in one sitting, and a chip
     at Review's weight ten times down one page turns the board into a fire alarm until he stops
     seeing red at all. ⇒ DONE is the right sibling for a terminal state, not REVIEW. The Lead and
     I both argued the opposite from the physics — darker base, more fill, so it reads as lit — and
     we were reasoning about the COLOUR while he reasoned about the PAGE after an hour of using it.
     📌 Standing ruling: any future terminal-negative state on his board is QUIET by default.
     ⛔ DO NOT BRIGHTEN THESE. 24/8 is deliberately the lowest fill in the family (cyan 40/14,
     gold 42/15, emerald 36/12) and #FFC1B5 sits at saturation 0.29 against a family band of
     0.38–0.47 — BELOW IT, ON PURPOSE. It is pinned to gold-text's measured contrast (10.36) on
     the row it sits on, which is the one anchor in this that nobody invented.
     ⚠️ AND IF YOU RE-MEASURE, MEASURE THE RIGHT GROUND: three different backgrounds were used
     during this decision before anyone checked. `.bh-trow` sets NO background of its own — it sits
     inside `.bh-card`, whose fill is `--grad-panel` (--surface → --surface-sunk), with the chip's
     own semi-transparent gradient composited over it. A contrast figure quoted against
     `--surface-deep` or a bare `--surface-row` is answering about a surface the chip is not on.
     ⛔ A red cannot join the siblings' contrast band and stay red: luminance weights are
     R .2126 / G .7152 / B .0722, so gold/emerald/cyan reach ~13 by carrying heavy GREEN, and
     lifting a red there IS desaturation. That is physics, not an oversight — do not "fix" it. */
  --grad-chip-danger:  linear-gradient(180deg, color-mix(in srgb, var(--danger) 24%, transparent), color-mix(in srgb, var(--danger) 8%, transparent));
  --danger-text:       #FFC1B5;
  /* AINSTEIN'S SURFACE — the cyan/purple identity that tells a broker whose panel he is
     looking at. Lifted VERBATIM from the shipped Daily dock (contact-detail.js .rc-ai-dock /
     .rc-ai-tab), which Joe approved: Discovery had reproduced the dock's STRUCTURE while reaching
     for the GENERIC tokens, and came out a grey utility panel with an orb in it. Values are
     Daily's, unchanged; only their home is new.
     ⚠️ TODAY ONLY DISCOVERY READS THESE. Daily still hardcodes the same gradients inline, so
     editing one of these moves Discovery and NOT Daily. What actually holds the two together is
     rail-matches-daily.test.js — it reads Daily's declarations at test time and fails on either
     side's drift. ⇒ The token does not yet PREVENT the drift; the test CATCHES it. Pointing Daily
     at these is a one-line follow-up, boarded, riding the next touch of that file. */
  --grad-ain-dock:     radial-gradient(800px 600px at 50% 22%, color-mix(in srgb, var(--cyan) 8%, transparent), transparent 65%);
  --grad-ain-tab:      linear-gradient(180deg, color-mix(in srgb, var(--cyan) 12%, transparent), color-mix(in srgb, var(--purple) 8%, transparent));
  --grad-ain-tab-hov:  linear-gradient(180deg, color-mix(in srgb, var(--cyan) 22%, transparent), color-mix(in srgb, var(--purple) 15%, transparent));
  /* ── the custom-automation BUILDER timeline (#1832-adjacent) ───────────────────────
     🔒 Joe approved these three as a picture; they are tokens so the picture has ONE home.
     ⛔ Do not flatten any of them to a solid fill — the spine's cyan→indigo→gold run is what
     makes the schedule read as a single passage of time rather than four unrelated rows. */
  --grad-builder-trigger: linear-gradient(90deg, color-mix(in srgb, var(--indigo) 18%, transparent), transparent);
  --grad-builder-spine:   linear-gradient(180deg, var(--cyan), var(--indigo) 60%, var(--gold));
  --grad-builder-first:   linear-gradient(180deg, color-mix(in srgb, var(--cyan) 8%, transparent), var(--surface));
  --grad-ain-orb:      linear-gradient(135deg, color-mix(in srgb, var(--cyan) 35%, transparent), color-mix(in srgb, var(--purple) 22%, transparent));

  --glow-ambient:  radial-gradient(1100px 560px at 14% -8%, color-mix(in srgb, var(--cyan) 16%, transparent), transparent 56%),
                   radial-gradient(900px 520px at 96% 104%, color-mix(in srgb, var(--gold) 7%, transparent), transparent 62%);

  /* ---- ELEVATION / SHADOWS (replace 699 hand-rolled) ----------------------- */
  --shadow-1:      0 1px 2px rgba(0,0,0,0.18);     /* hairline lift            */
  --shadow-2:      0 2px 8px rgba(0,0,0,0.22);     /* card                     */
  --shadow-3:      0 8px 24px rgba(0,0,0,0.30);    /* popover / raised          */
  --shadow-4:      0 18px 50px rgba(0,0,0,0.45);   /* modal / slide-over dock   */

  /* ---- Z-INDEX SCALE (fixes the real layering collisions) ------------------- */
  --z-base:        1;
  --z-raised:      10;
  --z-sticky:      100;
  --z-dock:        800;        /* all rail slide-over docks share this band     */
  --z-overlay:     1000;       /* backdrops / scrims                            */
  --z-modal:       9000;       /* the global rt().modal()                       */
  --z-toast:       9500;       /* toasts above modals                           */
  --z-max:         2147483000; /* iframe-escape embed ONLY                       */

  /* ---- SPACING SCALE (snap the magic 6/7/9/13/18 values onto this) --------- */
  --sp-1:          4px;
  --sp-2:          8px;
  --sp-3:          12px;
  --sp-4:          16px;
  --sp-5:          20px;
  --sp-6:          24px;
  --sp-7:          32px;
  --sp-8:          40px;

  /* ---- RADIUS (assigned per component — NOT a menu; NO pill) ----------------
     Each component uses ONE value everywhere it appears. Round things
     (avatars, status dots) use border-radius:50% directly, not a token.        */
  --r-chip:        7px;     /* CHIPS — the common value found in code (5–9 → 7)  */
  --r-btn:         9px;     /* buttons / inputs                                 */
  --r-card:        12px;    /* cards                                            */
  --r-panel:       16px;    /* panels / modals                                  */
  /* (no --r-pill — pills are banished, Joe-locked)                             */

  /* ---- TYPE SCALE ---------------------------------------------------------- */
  /* 🪦 THE 12px FLOOR IS GONE — REMOVED 2026-09-10 ON JOE'S DIRECT ORDER. There is NO minimum
     font size in ROS, for prose or for anything else.
     🔒 HIS WORDS: "Somewhere along the lines, somebody roped a dope to me and added 12px font
     as the floor for ROS. This has been the biggest pain in my rear end ever since. 12px is
     GIGANTIC on this system, and I am forever changing fonts. I've literally been changing
     fonts for months." · "Huge font for no reason whatsoever looks amateurish. It looks
     immature and juvenile." · "Wherever it says a 12-pixel floor, I want that removed."
     🩸 THE SENTENCE THAT CAUSED IT WAS RIGHT HERE, on the --fs-1 line — "the minimum size on
     any actionable page". Read as a platform floor it made 12px the safe answer for every
     element a broker can click, which is nearly all of them, and it was COPIED verbatim into
     three module files as a design contract. It was then ENFORCED by a guard (design-guard
     `badFont`) whose only local remedy was to make the text BIGGER. ⇒ He spent months
     hand-undoing a guard's work, one element at a time, and it grew back on the next commit.
     ⛔ DO NOT RE-DERIVE A FLOOR FROM THIS SCALE, at any number, under any name. The fork was
     put to him explicitly — remove it entirely, or keep something stopping prose shrinking to
     10px — and he chose REMOVAL, everywhere it appears. Nothing here is a minimum. ☢️ Yes,
     that means body copy at 10px is now possible; that is HIS decision, taken knowingly.
     ⭐ WHAT THIS SCALE IS NOW: a VOCABULARY, not a rulebook. It exists so two seats pick the
     same size for the same job — never so a size can be called too small.
         READS  (prose, help text, table cells, labels he parses) → --fs-1 and up
         SCANS  (tabs, section nav, menus, rail labels)           → --fs-nav  (11px)
         RECOGNIZES (a chip: a shape+colour he identifies, never reads) → --fs-chip (9px)
     ⚠️ A CHIP IS NOT SMALL BODY TEXT. It is uppercase, so it reads at cap-height — ~1.38× a
     mixed-case tab at the same px. That is why it needs its own token and why --fs-nav
     looks correct on a tab and oversized on a chip. See --fs-chip below.
     ✅ WHAT GOVERNS INSTEAD — Joe, 2026-09-10, and it is NOT a number: "Tell him to use a
     button size that's already being used on that page. Tell him to use the same font size
     that's being used on that page in buttons. We need to keep it symmetrical."
     🔑 THE NEIGHBOUR IS THE AUTHORITY. A new element takes its size from the elements already on
     the page it lands on — never from a token judged correct in isolation, and never from a
     minimum. The test is whether it looks like it was always there. */
  --fs-1:          12px;    /* SMALL — prose he reads. ⛔ NOT a floor; nothing is. */
  --fs-2:          13px;    /* body-small (tables / lists)                      */
  --fs-3:          14px;    /* body                                             */
  --fs-4:          16px;    /* subhead                                          */
  --fs-5:          18px;    /* h3                                               */
  --fs-6:          22px;    /* h2                                               */
  --fs-7:          26px;    /* h1                                               */
  --fs-8:          32px;    /* display / hero                                   */
  --fs-fine:       11px;    /* legal / disclaimer ONLY — NEVER on actionable UI */
                            /* ⛔ NOT A GENERIC "SMALL TEXT" TOKEN, and it was being used as
                               one: 10 chips were sized from it, which literally styles a
                               status as fine print. If you want small, you want --fs-nav
                               (chrome) or --fs-chip (a chip). This one MEANS "legalese". */
  --fs-nav:        11px;    /* NAV / MENU CHROME ONLY (cockpit tabs, section nav, */
                            /* thread filters) — the sanctioned sub-12px exception:*/
                            /* dense repeated chrome reads calmer at 11/500/mixed- */
                            /* case. ⛔ There is NO lower bound on body/content —   */
                            /* the 12px floor is gone (see the TYPE SCALE header).  */
                            /* Prefer the TOKEN var(--fs-nav) so chrome stays       */
                            /* consistent, not because a literal is too small.      */
  --fs-chip:        9px;    /* ☢️ CHIPS ONLY — Joe-locked 2026-08-16.               */
                            /* "they're retarded big!! NON NEGOTIABLE. that 12px    */
                            /* floor is crap, and was majorly misinterpreted and    */
                            /* I've been fighting it ever since."                   */
                            /*                                                      */
                            /* ⭐ HE WAS NOT WRONG AND THE TOKEN WAS NOT WRONG — THE */
                            /* COMPARISON WAS. The section tabs are 11px MIXED CASE,*/
                            /* so their apparent height is the x-height (~0.52em).  */
                            /* A chip is UPPERCASE, so its apparent height is the   */
                            /* CAP-height (~0.72em). At the same px an uppercase    */
                            /* chip therefore reads ~1.38x a mixed-case tab, which  */
                            /* is why --fs-nav looks correct on a tab and oversized */
                            /* on a chip. Matching them NUMERICALLY is not matching */
                            /* them VISUALLY.                                       */
                            /*                                                      */
                            /* Optical parity with an 11px tab is 11x(0.52/0.72)    */
                            /* = ~8px. 9px is one pixel to the safe side AND is the */
                            /* size already surviving on .rc-qchip in production —  */
                            /* evidence beats arithmetic by a pixel.                */
                            /* ⛔ --fs-nav (11px) IS NOT A FALLBACK FOR THIS. It is  */
                            /* nav chrome; a chip is RECOGNISED, not read. Do not   */
                            /* "restore" it. Ships with the accepted .rc-qchip      */
                            /* combination: 9px / weight 500 / 0.06em / UPPERCASE.  */

  /* ---- THE CHIP SCALE — Joe-approved 2026-09-01, all three tiers rendered live -- */
  /* ⭐ HIS REASON WAS NOT TASTE: "there's so much going on that these buttons start  */
  /* to make your head spin. It makes everything tighter and smushed." Oversized      */
  /* chrome eats the room the CONTENT needs, so shrinking the chrome is what          */
  /* un-crowds a dense page. He looked at all three rendered live and changed none.   */
  /* ⛔ ALL CAPS THROUGHOUT — he ruled UPPERCASE KEPT. The SIZE and the WEIGHT were   */
  /* the bug, never the casing. Do not "fix" a chip by making it mixed-case.          */
  /* ⭐ PICK THE TIER BY CROWDING, NOT BY IMPORTANCE — that is the whole scale.       */
  /* ⚠️ These used to be explained as an EXEMPTION from a 10px front-facing floor.    */
  /* 🪦 There is no such floor any more — none of these needs an exemption. They are   */
  /* simply the sizes a RECOGNISED chip reads best at.                                */
  --fs-chip-1:      10px;   /* standalone — own row, nothing crowding it · --fw-med  */
  --fs-chip-2:      9.5px;  /* grouped, with room around it             · --fw-normal*/
  --fs-chip-3:      var(--fs-chip);
                            /* dense series — eight in a tight rail     · --fw-normal*/
                            /* ⭐ AN ALIAS, NOT A SECOND 9px. --fs-chip is Joe-locked */
                            /* (2026-08-16) and keeps its name AND its literal; -3 is */
                            /* only its POSITION in the scale. Two tokens each        */
                            /* spelling 9px is a duplicate that drifts the day one is */
                            /* edited — and the one that drifts would be the unlocked */
                            /* copy. One literal, one owner.                          */
  --fw-normal:     500;
  --fw-med:        600;
  --fw-semi:       700;
  --fw-bold:       800;
  --lh-tight:      1.2;
  --lh-base:       1.5;

  /* ---- MOTION -------------------------------------------------------------- */
  --ease:          cubic-bezier(.16,1,.3,1);
  --dur-fast:      .14s;
  --dur-base:      .24s;
  --dur-slow:      .4s;
}

/* ============================================================================
   BREAKPOINTS — convention (CSS vars can't be used in @media). Consolidate the
   current ~19 ad-hoc widths onto these 5. Always pair motion with
   @media (prefers-reduced-motion: reduce).
       xl 1400 · lg 1100 · md 900 · sm 680 · xs 560
   ============================================================================ */
