/* ═══════════════════════════════════════════════════════════════════════════
   tokens.css — the single source of design values

   Extracted 2026-07-30 from the prototypes, which remain the spec. Nothing here
   is invented: every value below is traced to a prototype declaration. Where a
   name carried two values, the resolution and its evidence are noted inline.

   LAYER 1 (--p-*)  primitives — the raw scale. No component references these.
   LAYER 2 (--dep-*) semantic roles — what components actually consume.
   LAYER 3 (compat)  bare aliases the 22 widget .base.css files already reference,
                     so those spec files consume this layer UNEDITED.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ─────────────────────────────────────────────────────────────────────────────
   LAYER 1 — PRIMITIVES
   ───────────────────────────────────────────────────────────────────────────── */
:root {
  /* Neutrals — Tailwind zinc. 10 of the 12 most-used prototype hexes. */
  --p-zinc-950: #09090b;
  --p-zinc-900: #18181b;
  --p-zinc-800: #27272a;   /* most-used value in the entire design: 425 uses */
  --p-zinc-700: #3f3f46;
  --p-zinc-600: #52525b;
  --p-zinc-500: #71717a;
  --p-zinc-400: #a1a1aa;
  --p-zinc-300: #d4d4d8;
  --p-zinc-200: #e4e4e7;
  --p-zinc-100: #f4f4f5;
  --p-white:    #ffffff;

  /* Off-scale neutrals — deliberate, sit between zinc-900 and zinc-800. */
  --p-ink-870:  #1f1f23;   /* border-dim (44 uses) */
  --p-ink-885:  #1c1c1f;   /* elevated-dim (21 uses) */
  /* --p-ink-940 added 2026-08-20 by RULING C1. Sits between zinc-950 (#09090b)
     and zinc-900 (#18181b), in the same off-scale tradition as the two above.
     WHY IT HAD TO EXIST: the dark scale has no room BELOW zinc-950, so when the
     page floor and the control field both resolved there they were the same
     pixel — a toolbar chip vanished into the strip behind it. Something had to
     move UP. Moving the FIELD would have repainted --dep-bg's 65 consumers
     (every input, tooltip and dropdown trigger); moving the FLOOR repaints
     --dep-canvas's 2. */
  --p-ink-940:  #101014;   /* dark page floor — see RULING C1 */

  /* Blue — chrome/frame accent family */
  --p-blue-700: #1d4ed8;
  --p-blue-600: #2563eb;
  --p-blue-500: #3b82f6;
  --p-blue-400: #60a5fa;
  --p-blue-300: #93c5fd;
  --p-blue-dim: #1e3a5f;   /* filled dim backing */
  --p-blue-ink: #0f172a;   /* darkest blue backing */

  /* Brand blue — the widget/series accent. NOT the same role as blue-500. */
  --p-brand:    #4b7bec;

  /* Violet */
  --p-violet-700: #6d28d9;
  --p-violet-600: #7c3aed;
  --p-violet-500: #8b5cf6;
  --p-violet-400: #a78bfa;
  --p-violet-300: #c4b5fd;
  --p-violet-950: #2e1065;
  --p-indigo-950: #1e1b4b;
  --p-indigo-600: #4f46e5;
  --p-indigo-300: #a5b4fc;
  --p-fuchsia-600: #c026d3;
  --p-purple-600:  #9333ea;

  /* Emerald / green */
  --p-emerald-700: #047857;
  --p-emerald-600: #059669;
  --p-emerald-500: #10b981;
  --p-emerald-400: #34d399;
  --p-emerald-300: #6ee7b7;
  --p-green-400:   #4ade80;

  /* Amber / orange */
  --p-amber-500: #f59e0b;
  --p-amber-400: #fbbf24;
  --p-amber-300: #fcd34d;
  --p-yellow-500: #eab308;
  --p-orange-400: #fb923c;
  --p-orange-300: #fdba74;

  /* Rose / red */
  --p-rose-500: #f43f5e;
  --p-rose-400: #fb7185;
  --p-red-400:  #f87171;
  /* Added 2026-08-18 by RULING B. The DESTRUCTIVE red — what the delete buttons
     already paint (`bg-red-600`, 6 sites) and what the light half of
     --dep-negative-text now resolves to. --p-red-700 (#b91c1c) already existed
     among the tint rungs below and serves as its hover. */
  --p-red-600:  #dc2626;

  /* Categorical series scale — verbatim from funnel-chart-prototype.html:88-89 */
  --p-c1:  #4b7bec;  --p-c2:  #fa8231;  --p-c3:  #20bf6b;  --p-c4:  #8854d0;
  --p-c5:  #eb3b5a;  --p-c6:  #0fb9b1;  --p-c7:  #f7b731;  --p-c8:  #fc5c65;
  --p-c9:  #2d98da;  --p-c10: #a55eea;

  /* Alpha tints — the recurring translucent pairs (dim fill + border) */
  --p-a-blue-dim:    rgba(59,130,246,.13);
  --p-a-blue-bdr:    rgba(59,130,246,.28);
  --p-a-brand-dim:   rgba(75,123,236,.06);
  --p-a-emerald-dim: rgba(16,185,129,.12);
  --p-a-emerald-bdr: rgba(16,185,129,.28);
  --p-a-violet-dim:  rgba(124,58,237,.15);
  --p-a-violet-bdr:  rgba(124,58,237,.25);
  --p-a-rose-dim:    rgba(244,63,94,.12);
  /* Neutral chip tint — the "no semantic colour" chip (a time window, a count).
     Extracted 2026-07-31 from filter-audience.base.css, which had it inline. */
  --p-a-zinc-dim:    rgba(161,161,170,.10);
  --p-a-zinc-bdr:    rgba(161,161,170,.15);
  --p-a-amber-bdr:   rgba(245,158,11,.30);
  --p-a-scrim:       rgba(0,0,0,.60);
  --p-a-scrim-soft:  rgba(0,0,0,.50);
  --p-a-veil:        rgba(9,9,11,.92);

  /* Light-theme rungs — added 2026-08-17 for the Cohort List dark/light pilot.
     These are NOT prototype-traced like the rest of Layer 1: the prototypes are
     dark-only, so they have no light end of the scale to trace to. Each is the
     stock Tailwind value at that rung, and each is already on screen in
     production — CohortListPage.tsx authored them as `dark:` pairs long before
     this pilot. Traced to production, not to a prototype; when the prototypes
     grow a light variant, these are what to check against. */
  --p-zinc-50:     #fafafa;   /* CohortListPage bg-zinc-50 (panel, light) */

  /* WARM LIGHT SCALE — RULING MANILA, 2026-08-20. The light theme's neutral
     ramp, replacing zinc for SURFACES only (text and borders keep their own
     rules; the zinc rungs above are still what dark uses).
     Numbered by distance below white, mirroring zinc's convention: warm-25 sits
     where zinc-50 does, warm-200 where zinc-200 does.
     Hue 42°, chroma 5-13 — chosen against the zinc ramp's own hue 240°, and
     deliberately NOT a tint of it: this is a second neutral family for light,
     which is the cost the ruling accepts. See design/BUILD_LOG.md 2026-08-20. */
  --p-warm-15:     #fffefc;   /* elevated overlays — lifts above panel */
  --p-warm-25:     #fffdf9;   /* Pearl — panel, cards, rail */
  --p-warm-75:     #faf6ee;   /* Manila — the page canvas */
  --p-warm-100:    #f7f4ec;   /* recessed fill + hover */
  --p-warm-200:    #eae6de;   /* borders */
  --p-violet-100:  #ede9fe;   /* CohortListPage bg-violet-100 */
  --p-amber-700:   #b45309;   /* CohortListPage text-amber-700 */
  --p-rose-600:    #e11d48;

  /* Tint-badge rungs — RULING 2026-08-17, see the --dep-tint-* family below.
     Four rungs per hue, because that is the shape of the pattern: a -100 fill
     with -700 text in light, inverting to a -950 fill with -300 text in dark.
     Stock Tailwind values. Traced to production, not to a prototype. */
  --p-sky-100:     #e0f2fe;  --p-sky-300:     #7dd3fc;
  --p-sky-700:     #0369a1;  --p-sky-950:     #082f49;
  --p-blue-100:    #dbeafe;  --p-blue-950:    #172554;
  --p-emerald-100: #d1fae5;  --p-emerald-950: #022c22;
  --p-amber-100:   #fef3c7;  --p-amber-950:   #451a03;
  --p-red-100:     #fee2e2;  --p-red-300:     #fca5a5;
  --p-red-700:     #b91c1c;  --p-red-950:     #450a0a;
  --p-indigo-100:  #e0e7ff;  --p-indigo-700:  #4338ca;
  --p-purple-100:  #f3e8ff;  --p-purple-300:  #d8b4fe;
  --p-purple-700:  #7e22ce;  --p-purple-950:  #3b0764;
}

/* ─────────────────────────────────────────────────────────────────────────────
   LAYER 2 — SEMANTIC ROLES  (what components consume)
   ───────────────────────────────────────────────────────────────────────────── */
/* ── 2a. Theme-independent roles ──────────────────────────────────────────────
   Radius, type and layout carry no colour, so they take no light/dark split.
   20 of the 63 roles live here and need nothing from theming, ever. */
:root {
  /* Radius — 6/8/10 are the intended scale (103/98/41 uses).
     4px (91 uses) is real and additive. 7px/5px/3px/9px are drift → snap. */
  --dep-radius-xs:   4px;
  --dep-radius-sm:   6px;
  --dep-radius-md:   8px;
  --dep-radius-lg:   10px;
  --dep-radius-pill: 9999px;

  /* Type — prototype scale, by usage: 12 > 11 > 13 > 10 > 14 */
  --dep-font: 'Inter', system-ui, -apple-system, sans-serif;
  --dep-text-9:  9px;   --dep-text-10: 10px;  --dep-text-11: 11px;
  --dep-text-12: 12px;  --dep-text-13: 13px;  --dep-text-14: 14px;
  --dep-text-15: 15px;  --dep-text-16: 16px;  --dep-text-22: 22px;
  --dep-text-24: 24px;

  /* Layout — shell.base.css SH-11. NOTE: --topbar-h is deliberately absent;
     SH-1 rev.3 (2026-07-29) removed the top shell entirely. */
  --dep-rail-w:        64px;
  --dep-rail-w-exp:   224px;
  --dep-query-w:      292px;
  --dep-left-region-w: 356px;
}

/* ── 2b. LIGHT theme — the 43 colour-bearing roles ────────────────────────────
   RULING 2026-08-17: light mode is a PALETTE INVERSION of the same design.
   Same layout, same elevation logic, same hue meanings; only the palette flips.
   See design/dark-mode-experiment-cohort-list.md for the ruling and its limits.

   Derivation: mirror across the zinc ramp (100↔900, 200↔800, 800↔200), hues
   invariant, status/accent `-text` variants resolve DARKER because a tint
   readable on near-black is not readable on near-white.

   Two deliberate departures from a strict mirror, both following colour already
   authored in production rather than arithmetic:
     --dep-panel    strict mirror zinc-100 → zinc-50  (CohortListPage bg-zinc-50)
     --dep-surface  strict mirror zinc-200 → zinc-100 (CohortListPage bg-zinc-100)
   The light surface ladder is therefore COMPRESSED toward white
   (white / zinc-50 / zinc-100) rather than mirrored. It is still same-direction
   elevation — rising = darker — which is what avoids the flat/muddy inversion
   failure predicted in design/dark-mode-readiness-plan.md:216.

   PROVISIONAL. This block is the hypothesis the Cohort List pilot is testing. */
:root {
  /* Surfaces — compressed toward white; see the ladder note above. */
  --dep-bg:              var(--p-white);
  /* --dep-canvas — the PAGE FLOOR, split from --dep-bg 2026-08-19.
     --dep-bg does DOUBLE DUTY: 3 sites paint the app canvas (AppLayout ×2,
     ErrorBoundary), the other 60 paint CONTROL FIELDS — input backgrounds,
     dropdown triggers, tooltip fills, the SaveButton ghost state. In dark that
     is coherent: zinc-950 is the darkest value, so "the page floor" and "a
     recessed input" genuinely are the same thing. In light, white is the
     LIGHTEST value, so it plays both the floor and a raised input — and tinting
     --dep-bg would tint every input in the app along with the canvas.
     This role exists so the canvas can move without the controls following it.
     DEFAULTS TO --dep-bg IN BOTH THEMES: minting it moves nothing on screen. */
  --dep-canvas:          var(--p-warm-75);   /* RULING MANILA — was var(--dep-bg) */
  --dep-panel:           var(--p-warm-25);   /* RULING MANILA — was zinc-50 */
  --dep-surface:         var(--p-warm-100);  /* RULING MANILA — was zinc-100 */
  --dep-surface-raised:  var(--p-zinc-200);
  --dep-elevated:        var(--p-white);
  --dep-elevated-dim:    var(--p-warm-15);   /* RULING MANILA — was zinc-50 */

  /* Borders — clean mirror. In light these carry the separation that
     elevation-by-lightness carries in dark, which is why the compressed
     surface ladder still reads. */
  --dep-border:         var(--p-warm-200);  /* RULING MANILA — was zinc-200 */
  --dep-border-dim:     var(--p-zinc-100);
  --dep-border-strong:  var(--p-zinc-300);

  /* Text — the STRICT mirror, at both ends, since RULING F below.

     HISTORY, kept because it is the evidence the ruling turned on. The pilot
     (2026-08-17) shipped this block with --dep-text-muted and --dep-text-dim
     BOTH on zinc-500: dark separates them (zinc-400 / zinc-500) against a
     near-black field, but on white the mirror of muted (zinc-600) lost to the
     12-to-1 production evidence for zinc-500, and the mirror of dim IS
     zinc-500. Two roles, one light value — recorded rather than hidden, and
     called "the first real crack in the mirror".

     ── RULING F, 2026-08-18 — RE-SPLIT, NOT MERGE ────────────────────────────
     --dep-text-muted returns to its strict mirror, zinc-600. The two roles are
     distinct in light again and the ramp is monotonic in both themes:
       light  900, 800, 700, 600, 500, 400
       dark   100, 200, 300, 400, 500, 600
     WHY THIS BECAME URGENT. 459 sites consume --dep-text-muted and 273 consume
     --dep-text-dim. While the two resolved to one light value, every lane
     binding either one was guessing, and the guess was invisible until someone
     looked at light mode. Seventeen lanes are still unrun; deciding after them
     would have meant re-auditing all 732 sites.
     WHY NOT MERGE. Deleting --dep-text-dim and repointing its 273 sites at
     --dep-text-muted moves them zinc-500 -> zinc-400 IN DARK. Hard rule 3 —
     dark is what ships, and a change that improves light while shifting dark is
     a regression. Re-split costs ZERO dark movement; merge cannot.
     WHAT THIS COSTS, stated rather than buried: the 12-to-1 production evidence
     for zinc-500 is now overridden. Light muted text darkens one rung from what
     CohortListPage authored. That evidence was 12 sites on one pilot page; the
     mirror is the rule the whole light theme is derived from, and a rule that
     bends at its first contact with a page is not a rule.
     Not a merge candidate again without re-opening this ruling. */
  --dep-text:        var(--p-zinc-900);
  --dep-text-2:      var(--p-zinc-800);
  /* --dep-text-3 — RULING 2026-08-18c. See the dark block for the reasoning.
     Light is the STRICT mirror (dark zinc-300 -> light zinc-700), which is what
     keeps this ramp monotonic: 900, 800, 700, 600, 500, 400 (the 600 rung
     arrived with RULING F; this comment previously read "700, 500, 500, 400"
     and described the collapse that ruling closed). */
  --dep-text-3:      var(--p-zinc-700);
  --dep-text-muted:  var(--p-zinc-600);   /* RULING F — was zinc-500 */
  --dep-text-dim:    var(--p-zinc-500);
  --dep-text-faint:  var(--p-zinc-400);
  --dep-text-on-accent: var(--p-white);   /* invariant — fills stay coloured */

  /* Accents — hue invariant, lightness flips. R10's ladder REVERSES direction:
     in dark, brighter = more interactive (500 → 400 → 300); in light, darker =
     more interactive. The three roles stay mutually distinct, which is what R10
     protects. Untested by this pilot — Cohort List binds only accent-lift. */
  --dep-accent:         var(--p-blue-600);
  --dep-accent-strong:  var(--p-blue-700);
  --dep-accent-soft:    var(--p-blue-700);
  --dep-accent-dim:     var(--p-a-blue-dim);    /* alpha — reads on both fields */
  --dep-accent-widget:  var(--p-brand);         /* invariant — series identity */
  --dep-accent-lift:    var(--p-blue-600);      /* CohortListPage text-blue-600 */

  /* Primary action — R5 preserved: --dep-action stays one step apart from
     --dep-positive in light exactly as in dark. Both darken for contrast on
     white; the failure mode R5 guards against is landing them on one value. */
  --dep-action:        var(--p-emerald-600);
  --dep-action-hover:  var(--p-emerald-700);

  /* Status — solids invariant (they sit on coloured fills with white text),
     `-text` variants resolve darker for contrast on white. */
  --dep-positive:      var(--p-emerald-600);
  --dep-positive-text: var(--p-emerald-700);
  --dep-positive-dim:  var(--p-a-emerald-dim);
  --dep-warning:       var(--p-amber-500);
  --dep-warning-text:  var(--p-amber-700);
  --dep-negative:      var(--p-rose-500);
  /* RULING B move 1, 2026-08-18 — was --p-rose-600. This role was the ONE place
     the system crossed colour families: red-400 in dark, rose-600 in light,
     while every sibling keeps its family across the boundary. The withdrawal
     note on the dark half (2026-08-18d) named this exact fix and declined to
     infer it from a withdrawal; it is now ruled deliberately.
     Costs ZERO dark movement — the dark half is untouched. */
  --dep-negative-text: var(--p-red-600);
  --dep-negative-dim:  var(--p-a-rose-dim);
  /* RULING B move 2, 2026-08-18 — THE DESTRUCTIVE BUTTON, a role of its own.
     Not --dep-negative (rose-500), which means "this value is bad news" — a
     drop, a failing check. This is the button that DESTROYS the user's thing:
     Delete cohort, Delete space, Delete alert. The tracker listed `bg-red-600`
     on its known-non-mappable list purely because --dep-negative is rose, a
     genuinely different colour, and refusing to bind it there was correct.
     Naming it closes those sites without touching --dep-negative at all.
     Same shape as R5's --dep-action vs --dep-positive: a shared hue is not a
     shared meaning. Do not point a destructive button at --dep-negative, and do
     not point a negative indicator here. */
  --dep-destructive:       var(--p-red-600);
  --dep-destructive-hover: var(--p-red-700);
  --dep-ai:            var(--p-violet-600);
  --dep-ai-text:       var(--p-violet-700);
  --dep-ai-bg:         var(--p-violet-100);
  --dep-ai-dim:        var(--p-a-violet-dim);
  --dep-ai-border:     var(--p-violet-700);

  /* Tint borders — all alpha over the host field, so they invert for free. */
  /* --dep-warning-bdr added 2026-08-20 by the SNAP ruling below. The family had
     accent/positive/ai/neutral but no WARNING member, which is why
     chart-settings.css `.cs-do-note.is-warn` carried a raw #524718 edge. Alpha,
     so one declaration serves both themes. */
  --dep-warning-bdr:   var(--p-a-amber-bdr);
  --dep-accent-bdr:    var(--p-a-blue-bdr);
  --dep-positive-bdr:  var(--p-a-emerald-bdr);
  --dep-ai-bdr:        var(--p-a-violet-bdr);
  --dep-neutral-dim:   var(--p-a-zinc-dim);
  --dep-neutral-bdr:   var(--p-a-zinc-bdr);
  --dep-ai-gradient:      linear-gradient(90deg,#c026d3,#9333ea,#4f46e5);
  --dep-ai-gradient-hover: linear-gradient(90deg,#a21caf,#7e22ce,#4338ca);

  /* Tint badges — RULING 2026-08-17.
     The status pill the app uses everywhere: a -100 fill with -700 text in
     light, inverting to a -950 fill with -300 text in dark. The pattern already
     had exactly one name (--dep-ai-bg / --dep-ai-text, for violet) and seven
     unnamed hues behind it — ~155 unbound sites across four page lanes were
     this and nothing else. Named per-hue, mirroring the violet pair, rather
     than as one generic role: the hue IS the distinction a reader is making.

     --dep-tint-violet-* deliberately DUPLICATES the values of --dep-ai-*. Same
     reasoning as R5's --dep-action vs --dep-positive: the AI meaning is
     load-bearing and must be re-rulable without repainting every cohort avatar
     that happens to be violet today. Do not collapse them. */
  --dep-tint-blue-bg:      var(--p-blue-100);     --dep-tint-blue-text:    var(--p-blue-700);
  --dep-tint-sky-bg:       var(--p-sky-100);      --dep-tint-sky-text:     var(--p-sky-700);
  --dep-tint-emerald-bg:   var(--p-emerald-100);  --dep-tint-emerald-text: var(--p-emerald-700);
  --dep-tint-amber-bg:     var(--p-amber-100);    --dep-tint-amber-text:   var(--p-amber-700);
  --dep-tint-red-bg:       var(--p-red-100);      --dep-tint-red-text:     var(--p-red-700);
  --dep-tint-indigo-bg:    var(--p-indigo-100);   --dep-tint-indigo-text:  var(--p-indigo-700);
  --dep-tint-purple-bg:    var(--p-purple-100);   --dep-tint-purple-text:  var(--p-purple-700);
  --dep-tint-violet-bg:    var(--p-violet-100);   --dep-tint-violet-text:  var(--p-violet-700);
}

/* ── 2c. DARK theme ───────────────────────────────────────────────────────────
   The values that shipped. Every one is prototype-traced; this block is a
   verbatim move of what used to sit at :root, so dark is byte-for-byte
   unchanged by the light/dark split. The rulings below were minted against
   these values and continue to govern them. */
.dark {
  /* Surfaces */
  --dep-bg:              var(--p-zinc-950);
  /* --dep-canvas — RULING C1, 2026-08-20. WAS var(--dep-bg); now its own value.
     The split was minted as a no-op because in dark the floor and a recessed
     field looked like the same thing. They are not: once the toolbar strip
     became page floor, chips painted --dep-bg vanished into it at Δ0.
     --p-ink-940 slots the floor BETWEEN the field and the panel:
        --dep-bg      #09090b   9   control field, recessed
        --dep-canvas  #101014  16   page floor          <- this
        --dep-panel   #18181b  24   cards
        --dep-surface #27272a  39   inset
     The bottom of the dark scale is crowded — Δ7 and Δ8 between neighbours is
     workable, not generous. Recorded because a future rung added down here has
     almost no room left. */
  --dep-canvas:          var(--p-ink-940);
  --dep-panel:           var(--p-zinc-900);
  --dep-surface:         var(--p-zinc-800);
  --dep-surface-raised:  var(--p-zinc-700);
  --dep-elevated:        var(--p-zinc-800);
  --dep-elevated-dim:    var(--p-ink-885);

  /* Borders
     RESOLVED: --border = zinc-800. 5 sources agree, incl. all three page
     prototypes where it carries the annotation "zinc-800 borders".
     filter-audience.base.css:125 declares #3f3f46 under the same name — that is
     --dep-border-strong (split-audience.base.css:70 names it --border2). */
  --dep-border:         var(--p-zinc-800);
  --dep-border-dim:     var(--p-ink-870);
  --dep-border-strong:  var(--p-zinc-700);

  /* Text */
  --dep-text:        var(--p-zinc-100);
  --dep-text-2:      var(--p-zinc-200);
  /* ── --dep-text-3 — RULING 2026-08-18c ─────────────────────────────────────
     zinc-300 (#d4d4d8) had no role, and the ramp jumped --dep-text-2 (zinc-200)
     straight to --dep-text-muted (zinc-400) with nothing between. Production
     used it anyway: 23 sites, and it blocked conversion in three consecutive
     files — AppLayout (4), metrics-prototype.css (6), metrics/parts/*.tsx (4).

     WHY THIS IS A RULING AND NOT A LANE EDIT. Hard rule 1 forbids a lane
     minting a role to close a gap in front of it, and that stands. This is the
     escalation path the same rule describes: a gap that keeps recurring is
     ruled ONCE, deliberately, outside any lane, and dated here — exactly as the
     tint badges were on 2026-08-17.

     WHY NOT SNAP TO AN EXISTING ROLE. Snapping zinc-300 to --dep-text-2
     (zinc-200) or --dep-text-muted (zinc-400) repaints 23 shipped sites in
     DARK, which hard rule 3 forbids: dark is what ships, and a change that
     improves light while shifting dark is a regression. Minting is the only
     move that leaves dark byte-identical.

     SCOPE. This closes zinc-300 ONLY. The chromatic -400/-600 rungs reported
     alongside it (violet-400 x16, amber-400 x10, indigo-500 x7, blue-600 x7,
     violet-500 x6, rose-400 x6) are NOT closed here — whether those are
     semantic or decorative is a design-intent question, and answering it by
     arithmetic is how two roles get collapsed onto one value. They stay
     reported. */
  --dep-text-3:      var(--p-zinc-300);
  --dep-text-muted:  var(--p-zinc-400);
  --dep-text-dim:    var(--p-zinc-500);
  --dep-text-faint:  var(--p-zinc-600);
  --dep-text-on-accent: var(--p-white);

  /* Accents — TWO roles, per funnel-chart-prototype.html:91:
     "Widget accents use the series blue (#4B7BEC per exp widgets);
      the frame keeps #3b82f6."
     The prototypes had only one name (--blue) for both, so they resolved it with
     a later-wins `:root { --blue: #4B7BEC }` override. Two names removes the hack. */
  --dep-accent:         var(--p-blue-500);   /* frame / chrome */
  --dep-accent-strong:  var(--p-blue-700);
  --dep-accent-soft:    var(--p-blue-300);
  --dep-accent-dim:     var(--p-blue-dim);
  --dep-accent-widget:  var(--p-brand);      /* widgets + series-1 */
  /* RULING R10, 2026-08-04 (#1704) — the INTERACTIVE blue, one step brighter
     than the chrome accent. Inline text links at rest, and hover borders on a
     recessed tile. Hover on a LINK resolves lighter still, to --dep-accent-soft.

     Minted rather than collapsed onto a neighbour, on R8's reasoning: neither
     is this colour, and one of them is already this rule's own hover.
       --dep-accent      blue-500 #3b82f6 — the frame/chrome accent, a different job
       --dep-accent-soft blue-300 #93c5fd — what `.ma-advanced:hover` ALREADY is,
                         so pointing the RESTING state there collapses two states
                         into one
     --p-blue-400 holds the value but is LAYER 1, which this file reserves from
     component use in its own header.

     NOT NAMED `--dep-accent-link`, which is what the ruling was prepared as.
     The same #60a5fa is a hover BORDER on `.ma-tab` one rule away from being a
     link COLOUR on `.ma-advanced`, so a name carrying "link" would have been
     wrong the day it landed. Three rules bind it, not one. */
  --dep-accent-lift:    var(--p-blue-400);

  /* Primary action — RULING R5, 2026-08-03.
     The button that COMMITS the user's edit: Save, Apply, the header +.
     A distinct role from --dep-positive, which means "this value is good news"
     (a lift, a passing check). They were conflated because both are green, and
     the four action buttons in the set had drifted to four different treatments:
       compare/.apply-btn            #10b981, no border, 7px radius
       save/.save-primary           #059669 + #047857 border, hover DARKER
       filter-audience/.hdr-apply   #059669, hover LIGHTER (#10b981)
       run-control/.run-btn.primary #1d4ed8 (blue)
     Ruled to emerald-600: already the base in two of the four, already a
     palette token, and it keeps action distinguishable from the blue
     chrome/frame accent. Hover resolves DARKER (save's direction) — the two
     files disagreed on direction off the same base, which is what made the
     drift invisible in review.
     Do not point an action button at --dep-positive, and do not point a
     success indicator here; the shared hue is a coincidence, not a meaning. */
  --dep-action:        var(--p-emerald-600);
  --dep-action-hover:  var(--p-emerald-700);

  /* Status */
  --dep-positive:      var(--p-emerald-500);
  --dep-positive-text: var(--p-emerald-300);
  --dep-positive-dim:  var(--p-a-emerald-dim);
  --dep-warning:       var(--p-amber-500);
  --dep-warning-text:  var(--p-amber-300);
  --dep-negative:      var(--p-rose-500);
  /* RULING 2026-08-18d — WITHDRAWN 2026-08-18, same day, before it shipped.
     It changed this to `--p-rose-400` to stop the role crossing colour
     families. Withdrawn on the standing decision that RED IS RED: the negative
     family keeps red here, `dark-mode-page-tracker.md:96` stands, and the 62
     `red-*` sites are NOT snapped to rose (`red-600 -> rose-600` is a Δ34/255
     repaint of destructive controls, not a binding).

     Dark is therefore byte-for-byte what it has always shipped — the 17 bound
     sites move by nothing, and hard rule 3 is satisfied rather than knowingly
     spent.

     STILL OPEN, and left visible rather than quietly resolved: this role is the
     one place the system crosses families — `--p-red-400` here, `--p-rose-600`
     in the light block above, while every sibling keeps its family across the
     boundary (positive emerald-700/300, warning amber-700/300). "Keep red"
     points at `--p-red-600` for the light half, which would cost ZERO dark
     movement, but that is a fresh ruling on a value nobody has seen rendered
     yet — not something to infer from a withdrawal. Reported, not decided.

     CLOSED 2026-08-18 by RULING B move 1. The light half moved rose-600 ->
     red-600, exactly the fix this note pointed at and declined to infer. THIS
     DARK VALUE IS UNCHANGED — the whole point of that path was that it costs
     zero dark movement. The role no longer crosses families. */
  --dep-negative-text: var(--p-red-400);
  --dep-negative-dim:  var(--p-a-rose-dim);
  /* RULING B move 2 — see the light block for the reasoning. Theme-invariant:
     a destructive fill carries white text on both grounds, so it does not
     flip. */
  --dep-destructive:       var(--p-red-600);
  --dep-destructive-hover: var(--p-red-700);
  --dep-ai:            var(--p-violet-600);
  --dep-ai-text:       var(--p-violet-300);
  --dep-ai-bg:         var(--p-violet-950);
  --dep-ai-dim:        var(--p-a-violet-dim);
  /* RULING R8, 2026-08-04 — the SOLID edge that pairs with --dep-ai-bg.
     Came out of Step 4 lane 4, the way R6 came out of Step 3: shell's
     `#demo-banner` (shell.base.css:409) is a violet-950 pill outlined #6d28d9,
     and that colour had no semantic name. --dep-ai stops at violet-600, and
     --dep-ai-bdr is the TRANSLUCENT tint border (rgba(124,58,237,.25)) that
     pairs with a `-dim` FILL — a different job from outlining a solid one.
     The only other name for #6d28d9 was the Layer 1 primitive --p-violet-700,
     which this file reserves from component use, so production was left on
     Tailwind's `border-violet-700`. v4 resolves that to rgb(112,8,231) against
     the design's rgb(109,40,217) — close enough to have gone unnoticed for a
     generation, far enough to be a different edge on screen.
     Do NOT collapse this into --dep-ai-bdr: one is a solid stroke, the other a
     tint outline, and they take different values on purpose. */
  --dep-ai-border:     var(--p-violet-700);

  /* Tint BORDERS — the 1px outline that pairs with each `-dim` fill. Added
     2026-07-31: the `-dim` fills were already named here, but their partner
     borders were still inline literals in filter-audience.base.css, so a chip's
     fill was tokenised while its outline was not. A tint is a fill AND its
     border; naming only half of it is why the two drifted apart. */
  --dep-warning-bdr:   var(--p-a-amber-bdr);
  --dep-accent-bdr:    var(--p-a-blue-bdr);
  --dep-positive-bdr:  var(--p-a-emerald-bdr);
  --dep-ai-bdr:        var(--p-a-violet-bdr);
  --dep-neutral-dim:   var(--p-a-zinc-dim);
  --dep-neutral-bdr:   var(--p-a-zinc-bdr);
  --dep-ai-gradient:      linear-gradient(90deg,#c026d3,#9333ea,#4f46e5);
  --dep-ai-gradient-hover: linear-gradient(90deg,#a21caf,#7e22ce,#4338ca);

  /* Tint badges — RULING 2026-08-17. See the light block for the reasoning.
     Dark is the -950 fill / -300 text half of the pattern, which is what these
     sites already ship as authored `dark:` pairs — so binding them leaves dark
     byte-identical. */
  --dep-tint-blue-bg:      var(--p-blue-950);     --dep-tint-blue-text:    var(--p-blue-300);
  --dep-tint-sky-bg:       var(--p-sky-950);      --dep-tint-sky-text:     var(--p-sky-300);
  --dep-tint-emerald-bg:   var(--p-emerald-950);  --dep-tint-emerald-text: var(--p-emerald-300);
  --dep-tint-amber-bg:     var(--p-amber-950);    --dep-tint-amber-text:   var(--p-amber-300);
  --dep-tint-red-bg:       var(--p-red-950);      --dep-tint-red-text:     var(--p-red-300);
  --dep-tint-indigo-bg:    var(--p-indigo-950);   --dep-tint-indigo-text:  var(--p-indigo-300);
  --dep-tint-purple-bg:    var(--p-purple-950);   --dep-tint-purple-text:  var(--p-purple-300);
  --dep-tint-violet-bg:    var(--p-violet-950);   --dep-tint-violet-text:  var(--p-violet-300);
}

/* ═════════════════════════════════════════════════════════════════════════════
   RULINGS B, F AND A2 — ALL RULED 2026-08-18. Drafted and signed off the same
   day, out of design/color-system-audit.md. Each ruling now lives beside the
   value it governs; what follows is the index and the one part that was
   REFUSED, which is the part worth keeping in one place.

   ── RULING B — ONE RED, NOT FOUR ─────────────────────────────────────────────
   The app painted "danger" in four families: --dep-negative (rose-500),
   197 red-* utility sites, raw #ef4444/#dc2626, and shadcn --destructive
   (#d4183d). Three moves were approved; TWO WERE APPLIED AND ONE WAS REFUSED
   ON MEASUREMENT.

   MOVE 1 — APPLIED. --dep-negative-text light: rose-600 -> red-600. Zero dark
   movement. See the light Status block.
   MOVE 2 — APPLIED. Minted --dep-destructive / --dep-destructive-hover at
   red-600/700, and bound the six `bg-red-600 hover:bg-red-700` delete buttons.
   Those sites were ALREADY red-600/700, so this moved nothing on screen — it
   gave an unnamed colour a name. See the light Status block.

   MOVE 3 — REFUSED 2026-08-18, and this is why:
     Pointing shadcn's --destructive at --dep-destructive looked like closing
     the fourth red. MEASURED, it is not the same role at all.
       light  --destructive  #d4183d              vs red-600 #dc2626   Δ23
       dark   --destructive  oklch(.396 .141 25.7) = #82181a           Δ90
     shadcn's DARK --destructive is a dark tint BACKGROUND, paired with a bright
     --destructive-foreground (#fb2c36) for the text on top. --dep-destructive
     is a SOLID FILL that carries white text. They are a tint-pair and a fill —
     two different jobs that happen to both be red, which is exactly the
     conflation R5, R8 and R10 exist to prevent.
     Binding them would repaint 53 sites by 90/255 in dark. Hard rule 3.
     WHAT WOULD ACTUALLY CLOSE IT: a --dep-destructive-dim / -text tint PAIR,
     mirroring --dep-negative-dim, that shadcn's two vars could bind to
     separately. That is a new role pair, not a repoint, so it is not smuggled
     in here. The fourth red survives, deliberately, and is now the only one.

   NOT RULED, unchanged: --dep-negative itself stays rose-500. It is what ships
   on 25 bound sites and there is no evidence it is wrong.

   ── RULING F — RE-SPLIT ──────────────────────────────────────────────────────
   Light --dep-text-muted returns to its strict mirror, zinc-600. Merging the
   two roles was declined: it moves 273 sites in DARK. The ruling and its cost
   live in the LIGHT Text block above.

   ── RULING A2 — #1e1e24 BINDS --dep-elevated-dim ─────────────────────────────
   Sibling of the 2026-08-04 #1c1c1e ruling, closed the same day by binding
   measured-as .fc-menu. #1e1e24 could not close the same way: it is a DECLARED
   SPEC VALUE (time-granularity.base.css:53 .gran-chip, plus the y-axis-config
   prototype), and its nearest token by value — --p-ink-870 (#1f1f23), Δ(1,1,1) —
   is --dep-border-dim, a BORDER role. Putting a border value on a surface is
   how two roles collapse onto one meaning, so the cheap bind was the wrong one.

   RULED: accept Δ(2,2,5) and bind the nearest SURFACE role,
   --dep-elevated-dim (#1c1c1f). Chosen over minting a second dim-surface role
   because two dim surfaces two units apart is a distinction no reader can make
   and every future author would have to guess at. The delta is below the
   conformance harness's own tolerance, and .gran-chip is not measured by
   design-conformance.time-granularity.spec.ts (only .gran-option* are), so no
   waiver moved. Spec and production both bind the role.
   ═════════════════════════════════════════════════════════════════════════════ */

/* ═════════════════════════════════════════════════════════════════════════════
   RULING SNAP — 2026-08-20. THE FOURTH TINT VOCABULARY IS RETIRED.

   Three off-palette darks were painting "a deep tinted backing" — an active
   button state and two note boxes — in a vocabulary that predates and duplicates
   the --dep-tint-* family minted by RULING 2026-08-17. No role held any of them,
   so hard rule 1 had kept them reported-but-unbound, and they were FROZEN DARK:
   near-black rectangles in light mode, on every page that renders them.

     chart-toolbar.css  .cw-btn.on        #0c1c2e -> --dep-tint-blue-bg   Δ(11, 9,38)
     chart-settings.css .cs-do-note.is-info  #0c1526 -> --dep-tint-blue-bg   Δ(11,16,46)
     chart-settings.css .cs-do-note.is-warn  #1c1300 -> --dep-tint-amber-bg  Δ(41, 7, 3)
     chart-settings.css warn border       #524718 -> --dep-warning-bdr  (alpha, free)

   THIS COSTS DARK MOVEMENT, and that is the whole reason it is a ruling rather
   than a lane edit. Up to 46/255 on one channel. Hard rule 3 says dark is what
   ships, so spending it has to be argued, not assumed:

     · The surfaces are SMALL — one button's open state and two note boxes. This
       is not a field repaint.
     · The alternative is maintaining a SECOND blue-and-amber tint vocabulary
       indefinitely, for three sites, against a named family built for exactly
       this pattern.
     · That second vocabulary was ALREADY LEAKING. `.cs-do-note.is-info` had its
       border bound to --dep-accent-dim while its fill stayed raw — one rule half
       in the system and half out. A vocabulary that cannot hold a single rule
       together is not one worth keeping.
     · Left alone they do not merely look wrong in light; they are unfixable
       there, because a frozen literal has no light half to correct.

   Preserving the exact darks by minting three per-site roles was considered and
   REFUSED: it costs zero movement but entrenches the duplicate vocabulary and
   spends three role names on three sites.

   The `-100 fill / -700 text` light half and `-950 fill / -300 text` dark half
   come free — that is the shape RULING 2026-08-17 already established.
   ═════════════════════════════════════════════════════════════════════════════ */


/* PHASE 3 OWES A SPLIT HERE. metrics-prototype.css's --mp-chrome serves FOUR
   surfaces — query panel, the settings layer, the title header and the toolbar
   — and the surface families no longer agree on what they are:

     query panel     primary-background  --dep-canvas
     settings layer  primary-background  --dep-canvas
     toolbar strip   primary-background  --dep-canvas
     title header    shell               --dep-panel     <- the odd one

   Until that split lands, all four resolve to --mp-chrome's default,
   var(--dep-panel), which is what shipped before the canvas experiment and is
   internally consistent: panel-coloured chrome on a Manila canvas.

   The [data-canvas="manila"] rules that used to force them to the canvas were
   removed with the experiment — they keyed off a scope that no longer exists,
   so they were dead code, not a pending change. */

/* ─────────────────────────────────────────────────────────────────────────────
   LAYER 3 — COMPAT ALIASES
   The bare names the 22 widget .base.css spec files already reference via
   `var(--border, #27272a)`. Defining them here lets every spec file consume this
   token layer with ZERO edits — the prototype stays the untouched spec.
   Deletable once widget files migrate to --dep-*.

   ⚠ MUST NOT be at :root. theme.css already declares --border, --muted and
   --accent with DIFFERENT meanings (--muted is a background in shadcn, a text
   colour in the prototypes). Defining these globally would repaint every shadcn
   primitive. Scoped to [data-dep] so bare names resolve only inside markup
   derived from the widget prototypes; hosts opt in per subtree.
   ───────────────────────────────────────────────────────────────────────────── */
[data-dep] {
  --bg:          var(--dep-bg);
  --panel:       var(--dep-panel);
  --surface:     var(--dep-surface);
  --surface2:    var(--dep-surface-raised);
  --elevated:    var(--dep-elevated);
  --border:      var(--dep-border);
  --border2:     var(--dep-border-strong);
  --border-dim:  var(--dep-border-dim);
  --text:        var(--dep-text);
  --text-2:      var(--dep-text-2);
  --muted:       var(--dep-text-muted);
  --text-muted:  var(--dep-text-muted);
  --dim:         var(--dep-text-dim);
  --text-dim:    var(--dep-text-dim);
  --faint:       var(--dep-text-faint);
  --text-faint:  var(--dep-text-faint);
  --blue:        var(--dep-accent);
  --blue-500:    var(--p-blue-500);
  --blue-deep:   var(--dep-accent-strong);
  --blue-strong: var(--dep-accent-strong);
  --blue-txt:    var(--dep-accent-soft);
  --blue-soft:   var(--dep-accent-soft);
  --blue-dim:    var(--dep-accent-dim);
  --blue-lift:   var(--dep-accent-lift);   /* R10, 2026-08-04 — see Layer 2 */
  --emerald:     var(--dep-positive);
  --green:       var(--dep-positive);
  --positive:    var(--dep-positive);
  /* R5, 2026-08-03 — the COMMIT-my-edit button. Deliberately NOT an alias of
     --emerald/--positive even though it currently resolves to a near shade:
     re-ruling the action colour must not repaint success indicators. */
  --action:       var(--dep-action);
  --action-hover: var(--dep-action-hover);
  --brand:       var(--dep-positive);   /* events-selector.base.css: --brand:#10b981 */
  --amber:       var(--dep-warning);
  --rose:        var(--dep-negative);
  --red:         var(--dep-negative-text);
  --violet-bg:   var(--dep-ai-bg);
  --violet-fg:   var(--dep-ai-text);
  /* R8, 2026-08-04 — the bare name shell.base.css consumes for the solid
     violet edge. See --dep-ai-border. */
  --violet-bdr:  var(--dep-ai-border);
  --font:        var(--dep-font);
  --fnt:         var(--dep-font);
  --radius-sm:   var(--dep-radius-sm);
  --radius-md:   var(--dep-radius-md);
  --radius-lg:   var(--dep-radius-lg);
  --r-sm:        var(--dep-radius-sm);
  --rsm:         var(--dep-radius-sm);
  --rmd:         var(--dep-radius-md);
  --rlg:         var(--dep-radius-lg);
  --c1:  var(--p-c1);  --c2:  var(--p-c2);  --c3:  var(--p-c3);  --c4: var(--p-c4);
  --c5:  var(--p-c5);  --c6:  var(--p-c6);  --c7:  var(--p-c7);  --c8: var(--p-c8);
  --c9:  var(--p-c9);  --c10: var(--p-c10);
}
