/* generated: combined theme tokens, data-theme scoped */
/* ═══════════════════════════════════════════════════════ */
/* Benchwright — Theme Tokens                              */
/* ═══════════════════════════════════════════════════════ */
/* Single source of truth for the design tokens used by
   every page. Edit here to retheme the site.

   Loaded server-side before style.css on every page —
   see serveHtml() in website/src/main/kotlin/.../Server.kt.
   Inline <style> blocks across the static HTML pages are
   wired to consume these via var(--…); see the bottom of
   each file's <style> block for the colors it actually
   touches.

   Naming convention:
     --<color>            base hex for the brand/semantic role
     --<color>-bright     a slightly more saturated variant
     --<color>-soft       a slightly muted variant
     --<color>-dim        the canonical low-alpha tint (≈10%)
     --<color>-NN         alpha variant at 0.NN  (e.g. -08 = 8%)
     --<role>-rgb         comma-separated triplet for ad-hoc rgba()

   All hex/rgba values were extracted verbatim from the prior
   palette; nothing has been "unified" yet. To collapse drift
   (e.g. the three different teals in use historically), point
   --teal-77 / --teal-98 at the same hex as --teal here. */
:root,:root[data-theme="dark"] {
  /* ─── Brand teal ─────────────────────────────────── */
  /* Primary teal from logo.svg (rgb 0,206,200).        */
  --teal: #00cec8;
  --teal-bright: #00cec8;
  --teal-soft: #98efff;
  --teal-deep: #3090a0;
  --teal-warm: #4dd0e1;
  --teal-rgb: 0,206,200;

  /* Drift shades. Several near-teals were authored over
     time; exposed as separate vars so a retheme can collapse
     them to one value by editing this file alone. */
  --teal-77-rgb: 77,184,199;
  --teal-98-rgb: 98,212,228;
  --teal-208-rgb: 77,208,225;

  /* Brand alpha tints (canonical, used across components) */
  --teal-dim: rgba(0,206,200,0.10);
  --teal-ghost: rgba(0,206,200,0.05);
  --teal-border: rgba(0,206,200,0.28);
  --teal-08b: rgba(0,206,200,0.08);
  --teal-22: rgba(0,206,200,0.22);
  --teal-50: rgba(0,206,200,0.5);

  --teal-77-04: rgba(77,184,199,0.04);
  --teal-77-05: rgba(77,184,199,0.05);
  --teal-77-06: rgba(77,184,199,0.06);
  --teal-77-08: rgba(77,184,199,0.08);
  --teal-77-25: rgba(77,184,199,0.25);
  --teal-77-50: rgba(77,184,199,0.5);

  --teal-98-04: rgba(98,212,228,0.04);
  --teal-98-05: rgba(98,212,228,0.05);
  --teal-98-08: rgba(98,212,228,0.08);
  --teal-98-12: rgba(98,212,228,0.12);
  --teal-98-15: rgba(98,212,228,0.15);
  --teal-98-22: rgba(98,212,228,0.22);
  --teal-98-35: rgba(98,212,228,0.35);
  --teal-98-40: rgba(98,212,228,0.4);
  --teal-98-50: rgba(98,212,228,0.5);
  --teal-98-60: rgba(98,212,228,0.6);

  /* ─── Surfaces ───────────────────────────────────── */
  --bg: #060b10;
  /* Glass tints over --bg, used by the topbar / footer chrome.   */
  --bg-glass-55: rgba(6,11,16,0.55);
  --bg-glass-70: rgba(6,11,16,0.7);
  --surface: #0a1018;
  --surface-1: #0b121b;
  /* What a card is FILLED with (.na-card / .na-stat), and therefore what
     anything painting on top of a card must use to disappear against it —
     notably .na-tablewrap's scroll-edge patches. A token rather than a
     per-theme override so the two can never drift apart. Dark keeps the
     tint; light overrides to white (see theme-light.css). */
  --card-fill: var(--surface-1);
  --surface-2: #0e1620;
  --surface-3: #14202c;
  --surface-deep: #050505;
  --surface-warm: #1a1400;
  --border: #172333;
  --border-glass-60: rgba(23,35,51,0.6);
  --border-light: #1e3040;

  /* ─── Code/diff panel (GitHub-flavored grays) ─────
     Used by dashboard.html / registry.html / admin.html
     when rendering code, diffs, or terminal-style cards. */
  --code-bg: #0e1116;
  --code-bg-2: #0d1117;
  --code-bg-3: #161b22;
  --code-text: #c9d1d9;
  --code-text-2: #8b949e;
  --code-mono: #d4d4d4;
  --code-border: #2d2d2d;
  --code-mute: #8a8a8a;

  /* ─── Text ───────────────────────────────────────── */
  --text: #e0eaf2;
  --text-2: #a0b8cc;
  --text-3: #7e95ad;
  --text-on-brand: #ffffff;

  /* ─── Accent — amber (marketing spotlight) ────────────
     The one "pop" hue on marketing surfaces (see /docs/admin/palette).
     Was hard-coded #f5a36b across the landing; now tokenized so light
     mode can deepen it (a pale peach reads as washed-out on cream). */
  --amber: #f5a36b;
  --amber-bright: #f7b489;
  --amber-rgb: 245,163,107;
  --amber-dim: rgba(245,163,107,0.14);
  --amber-border: rgba(245,163,107,0.40);
  /* Pressed partner, defined in both themes so the slot always
     resolves. Nothing in dark mode fills with it today: on
     near-black the amber CTA stays a tint + outline, because a
     solid peach fill needs DARK text and would invert the
     topbar's whole text-colour logic. */
  --amber-deep: #d98a4f;

  /* ─── Semantic — green ───────────────────────────── */
  --green: #40d888;
  --green-bright: #6bd77a;
  --green-soft: #7fcf8f;
  --green-mute: #59c98b;
  --green-mossy: #6fc59b;
  --green-dim: rgba(64,216,136,0.10);
  --green-08: rgba(64,216,136,0.08);
  --green-25: rgba(64,216,136,0.25);
  --green-28: rgba(64,216,136,0.28);
  --green-leaf-10: rgba(107,215,122,0.10);
  --green-40: rgba(64,216,136,0.4);
  --green-50: rgba(64,216,136,0.5);
  --green-60: rgba(64,216,136,0.6);
  --green-45: rgba(64,216,136,0.45);
  --green-mossy-08: rgba(108,216,158,0.08);
  /* Tailwind-style green (used in registry chips) */
  --green-tw: #22c55e;
  --green-tw-16: rgba(34,197,94,0.16);
  --green-tw-30: rgba(34,197,94,0.3);
  --green-leaf-30: rgba(74,222,128,0.3);

  /* ─── Semantic — red ─────────────────────────────── */
  --red: #e06060;
  --red-soft: #e5756e;
  --red-pink: #f3a2a2;
  --red-bright: #ed5757;
  --red-bright-2: #ff8585;
  --red-warm: #ff6b6b;
  --red-glass: #ffb0b0;
  --red-dim: rgba(224,96,96,0.10);
  --red-08: rgba(224,96,96,0.08);
  --red-18: rgba(224,96,96,0.18);
  --red-28: rgba(224,96,96,0.28);
  --red-soft-10: rgba(229,117,110,0.10);
  --red-vivid-12: rgba(255,80,80,0.12);
  --red-pulse-12: rgba(220,86,86,0.15);
  --red-pulse-35: rgba(220,86,86,0.35);
  --red-edge-08: rgba(237,87,87,0.08);
  --red-edge-16: rgba(237,87,87,0.16);
  --red-edge-22: rgba(237,87,87,0.22);
  --red-edge-40: rgba(237,87,87,0.4);

  /* ─── Semantic — yellow / orange ─────────────────── */
  --yellow: #e0c848;
  --yellow-warm: #f0c455;
  --yellow-bright: #ffe079;
  --yellow-amber: #f0b429;
  --yellow-dim: rgba(224,200,72,0.10);
  --yellow-05: rgba(224,200,72,0.05);
  --yellow-30: rgba(224,200,72,0.3);
  --orange: #e0a050;
  --orange-soft: #e0b050;
  --orange-warm: #f5b041;
  --orange-bright: #f5aa3c;
  --orange-glow: #ffd270;
  --orange-skin: #e0a85a;
  --orange-06: rgba(224,160,80,0.06);
  --orange-dim: rgba(224,160,80,0.14);
  --orange-25: rgba(224,160,80,0.25);
  --orange-30: rgba(224,160,80,0.30);
  --orange-35: rgba(224,160,80,0.35);

  /* ─── Semantic — blue / purple ───────────────────── */
  --blue: #5ba8e8;
  --blue-sky: #38bdf8;
  --blue-12: rgba(91,168,232,0.12);
  --blue-30: rgba(91,168,232,0.3);
  --blue-sky-01: rgba(56,189,248,0.01);
  --blue-sky-05: rgba(56,189,248,0.05);
  --blue-pop-08: rgba(100,180,255,0.08);
  --blue-haze-45: rgba(125,211,252,0.45);
  --blue-haze-00: rgba(125,211,252,0);
  --purple: #9888e0;
  --purple-light: #b39dff;
  --purple-pink: #e2adf2;
  --purple-10: rgba(152,136,224,0.10);
  --purple-12: rgba(152,136,224,0.12);
  --purple-16: rgba(152,136,224,0.16);
  --purple-20: rgba(155,138,232,0.20);
  --purple-10b: rgba(155,138,232,0.10);
  --purple-35: rgba(152,136,224,0.35);

  /* ─── Status: degraded (used by footer status pill) ─ */
  --status-degraded: #f5aa3c;

  /* ─── Neutral overlays ───────────────────────────── */
  --black-20: rgba(0,0,0,0.2);
  --black-25: rgba(0,0,0,0.25);
  --black-35: rgba(0,0,0,0.35);
  --black-40: rgba(0,0,0,0.4);
  --black-45: rgba(0,0,0,0.45);
  --black-50: rgba(0,0,0,0.5);
  --black-60: rgba(0,0,0,0.6);
  --bg-glass-60: rgba(8,14,20,0.6);
  --bg-glass-35: rgba(16,22,30,0.35);
  --white-00: rgba(255,255,255,0);
  --white-02: rgba(255,255,255,0.02);
  --white-03: rgba(255,255,255,0.03);
  --white-04: rgba(255,255,255,0.04);
  --white-05: rgba(255,255,255,0.05);
  --white-06: rgba(255,255,255,0.06);
  --white-07: rgba(255,255,255,0.07);
  --white-10: rgba(255,255,255,0.1);

  /* ─── Typography ─────────────────────────────────── */
  --font: 'Inter', 'Inter Fallback', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --mono: 'JetBrains Mono', 'Fira Code', 'SF Mono', monospace;

  /* ─── Categorical: pipeline phases + activity buckets ─
     Read by DashboardSsr.kt (PHASE_COLOR / ACT_COLOR) for the
     run report's phase ribbon and its "where the time went"
     bar. These were hex literals in the Kotlin until the light
     theme landed — this cyan/mint ramp is tuned to glow on
     near-black and reads as clip-art on cream, so each theme
     now supplies its own family. Values here are unchanged
     from those literals.

     Segments carry a near-black label (.plabel), so every value
     must stay light enough to take dark text. Add a token to
     BOTH theme files when you add a phase or bucket. */
  --phase-boot: #4a6a7a;
  --phase-find: #7adfd4;
  --phase-fetch: #00cec8;
  --phase-analyze: #45b8d6;
  --phase-setup: #66d3a8;
  --phase-attach: #3ea3b8;
  --phase-atomize: #9bd7e8;
  --phase-materialize: #40d888;
  --phase-report: #7e95ad;

  --act-shell: #00cec8;
  --act-run: #40d888;
  --act-read: #5ba8e8;
  --act-write: #c4b5fd;
  --act-snapshot: #78dbff;
  --act-proxy: #f7a072;
  --act-materialize: #e0c848;
  --act-submit: #9ef0a3;
  --act-tool: #f487b6;

  /* The ink that rides ON a --phase-* / --act-* segment (.plabel). Deliberately
     the SAME value in both theme files: the ramps above are held light in both,
     so this label is near-black in both, and every other near-black token flips
     to paper in light mode. It is a token rather than a literal so the guard
     test can see it and so the invariant is stated somewhere. */
  --categorical-ink: rgba(4,17,14,0.85);

  /* ─── Radii ──────────────────────────────────────────
     Both themes ship the rectangular radii at 0 so the
     flat aesthetic is the global default; only
     pills and circles stay round. To restore the legacy
     rounded look in dark mode, set the rectangular slots
     back to 10/6/12/14 here and stop injecting style-flat
     in Server.kt. */
  --radius-2xs: 0;
  --radius-xs: 0;
  --radius-sm: 0;
  --radius: 0;
  --radius-lg: 0;
  --radius-xl: 0;
  --radius-circle: 50%;
  --radius-pill: 0;        /* flat aesthetic — pills are square too */
}

/* ═══════════════════════════════════════════════════════ */
/* Benchwright — Light Theme ("paper")                     */
/* ═══════════════════════════════════════════════════════ */
/* An ink-on-paper light theme. Three moves make it, in order of
   how much they matter:

     1. WARM PAPER, not white. Canvas is #FBFAF6 — a cream
        with a yellow-brown cast. Cards then sit on it as
        pure #FFF, so a card reads as lighter than the page.
        That is inverted from the old light theme (white page,
        grey cards) and is most of the character.
     2. WARM HAIRLINES. Borders are brown-black at low alpha
        (rgba(54,41,0,0.12)), never neutral grey. A cool #E3E8EE
        rule on cream looks like a rendering bug.
     3. PURE BLACK INK with a warm-grey ramp under it
        (#000 → #4E4B48 → #6F6D69). No blue in the text.

   GEOMETRY IS NOT PART OF IT. A first pass paired the palette
   with soft geometry — 10px radii, pill badges, a 1px card
   shadow — and it was rejected: the flat treatment (sharp
   rectangles, no shadows, no glows; style-flat.css) is the house
   style and wins. Only COLOUR and the ink/paper relationship are
   new here. Radii stay 0, same as theme-dark.css; do not
   reintroduce them.

   ─── BRAND ACCENT: this file swaps teal → indigo ─────────
   Light mode's accent is electric indigo #4137FF, which carries
   the look as much as the paper does. Every "accent" token below
   pins to it. ART cannot pin to a token (an SVG loaded through
   <img src> sees none of these custom properties), so each
   light-theme-only asset is recoloured to match by hand:
   img/{logo,wordmark}-light.svg and blog/hero-*-light.svg. The
   DARK theme is untouched and stays teal.

   TO REVERT TO TEAL: set --brand/--brand-deep back to
   #00756d/#003d3a in the block below, then recolour EVERY
   -light asset, not just the two chrome marks. The blog heroes
   were missed on the way in and shipped cyan art against indigo
   chrome for as long as nobody opened /blog in light mode.
   LightThemeArtHygieneTest derives both hues from these files,
   so it names whatever you leave behind: it is the list, and
   this comment is not.

   Selected by the BW_THEME env var (default "dark") or the
   bw_theme cookie; Server.kt routes /theme.css + the themed
   /logo.svg + /wordmark.svg here when light. */
:root[data-theme="light"] {
  /* ─── The one place the brand hue is written ───────────
     Everything below derives from these two. The `--teal-*`
     token NAMES are kept because ~270 selectors sitewide
     reference them; only the VALUES move to indigo, so the
     swap is a palette change and not a refactor. */
  --brand: #4137ff;         /* accent, links, primary fills */
  --brand-deep: #2b21d6;    /* pressed / hover fill */
  --brand-rgb: 65,55,255;

  /* ─── Brand accent ───────────────────────────────────
     Indigo #4137FF is ~7.5:1 on the cream canvas, so it holds
     as body-weight text, as a border, and as a CTA fill with
     white text. The dark theme defines a cyan glow under these
     same names; every slot is pinned here so a stray
     `color: var(--teal-bright)` can't leak a 1.7:1 cyan onto
     cream. */
  --teal: var(--brand);
  --teal-bright: var(--brand);
  /* --teal-soft is a TEXT slot, never a fill: every one of its ~12 call sites
     is `color:` or `outline:`, sitting on a --teal-dim / --teal-22 tint (the
     run dashboard's runswitch/filterchips/viewtoggle, .na-tag, .om-goalcell
     .kind). Dark fills it with a bright pale cyan that reads on near-black.
     This was #efebfe, a pale chip fill, which is ~1.05:1 on white — so the
     "OPERATOR" eyebrow on /manage/operators and every active toggle label in
     the run report were invisible in light mode. Pinned to the brand instead. */
  --teal-soft: var(--brand);
  --teal-deep: var(--brand-deep);
  --teal-warm: var(--brand);
  --teal-rgb: var(--brand-rgb);

  /* Drift triplets — pinned into the indigo family so the
     low-alpha washes they produce stay in-hue on cream
     instead of drifting cyan. */
  --teal-77-rgb: var(--brand-rgb);
  --teal-98-rgb: var(--brand-rgb);
  --teal-208-rgb: var(--brand-rgb);

  /* Brand alpha tints. Kept low: on cream, indigo at even 20%
     reads as a solid lavender block rather than a tint. */
  --teal-dim: rgba(65,55,255,0.10);
  --teal-ghost: rgba(65,55,255,0.05);
  --teal-border: rgba(65,55,255,0.32);
  --teal-08b: rgba(65,55,255,0.08);
  --teal-22: rgba(65,55,255,0.22);
  --teal-50: rgba(65,55,255,0.50);

  --teal-77-04: rgba(65,55,255,0.05);
  --teal-77-05: rgba(65,55,255,0.07);
  --teal-77-06: rgba(65,55,255,0.09);
  --teal-77-08: rgba(65,55,255,0.11);
  --teal-77-25: rgba(65,55,255,0.25);
  --teal-77-50: rgba(65,55,255,0.45);

  --teal-98-04: rgba(65,55,255,0.06);
  --teal-98-05: rgba(65,55,255,0.08);
  --teal-98-08: rgba(65,55,255,0.11);
  --teal-98-12: rgba(65,55,255,0.14);
  --teal-98-15: rgba(65,55,255,0.18);
  --teal-98-22: rgba(65,55,255,0.24);
  --teal-98-35: rgba(65,55,255,0.35);
  --teal-98-40: rgba(65,55,255,0.40);
  --teal-98-50: rgba(65,55,255,0.50);
  --teal-98-60: rgba(65,55,255,0.60);

  /* ─── Surfaces — cream paper, WHITE panels ─────────────
     The inversion vs. the old light theme: the page is the
     tinted surface and the cards are the clean one. Depth
     therefore runs bg(cream) → surface(white) upward for
     cards, and bg → surface-1/2 downward for inset bars
     (table headers, toolbars, wells). */
  --bg: #fbfaf6;                            /* paper */
  --bg-glass-55: rgba(251,250,246,0.88);    /* sticky topbar */
  --bg-glass-70: rgba(251,250,246,0.94);
  --surface: #ffffff;                       /* cards, table body */
  --surface-1: #f7f6ef;                     /* table header, toolbar */
  /* Cards fill WHITE here, not the cream tint. On paper --surface-1 is within
     a few points of the page colour, so every /manage panel sank into the
     background and only its hairline survived; white restores the
     card-lighter-than-page relationship the rest of this theme is built on.
     --surface-1 keeps its other jobs (table headers, hovers, inputs).
     Anything painting ON a card reads this token, so the two cannot drift:
     when this was a `background` override instead, .na-tablewrap's patches
     stayed cream and every table wore two permanent bands that read as a
     scroll cue on tables that fit. */
  --card-fill: var(--surface);
  --surface-2: #eeede6;                     /* chip / pressed */
  --surface-3: #e4e2d7;                     /* deepest inset */
  --surface-deep: #f7f6ef;
  --surface-warm: #fafaf6;                  /* row hover */
  --border: rgba(54,41,0,0.12);             /* hairline */
  --border-glass-60: rgba(54,41,0,0.10);
  --border-light: rgba(42,35,0,0.16);       /* inputs, stronger edge */

  /* ─── Code panel ─────────────────────────────────────
     Barely-there warm wells rather than grey blocks — code
     sits INSIDE white cards here, so it only needs a whisper
     of tint to separate. */
  --code-bg: #f9f9f5;
  --code-bg-2: #fcfcf9;
  --code-bg-3: #f2f1e9;
  --code-text: #353630;
  --code-text-2: #464841;
  --code-mono: #353630;
  --code-border: rgba(54,41,0,0.12);
  --code-mute: #aaa7a1;

  /* ─── Text — black ink on paper, warm grey ramp ──────── */
  --text: #000000;
  --text-2: #4e4b48;
  --text-3: #6f6d69;
  --text-on-brand: #ffffff;

  /* ─── Accent — amber (marketing spotlight) ────────────
     Built on the #FF5E23 orange, deepened for the
     text/headline slot so it clears 4.5:1 on cream while the
     -bright value stays available for fills and dots. */
  --amber: #c2440e;
  --amber-bright: #ff5e23;
  --amber-rgb: 194,68,14;
  --amber-dim: rgba(194,68,14,0.12);
  --amber-border: rgba(194,68,14,0.42);
  /* Pressed/hover partner for a SOLID amber fill. --amber-bright
     can't do that job here: it is brighter than --amber, so white
     text on it lands at ~2.7:1. This is 7:1. */
  --amber-deep: #9e3608;

  /* ─── Semantic — status colours ──────────────────────
     Pass green is #426100, a deep olive that reads as "green"
     against cream without the acid cast a bright green picks
     up on a warm ground. */
  --green: #426100;
  --green-bright: #4c7100;
  --green-soft: #e6f1cd;
  --green-mute: #5b7a2a;
  --green-mossy: #2e4300;
  --green-dim: rgba(66,97,0,0.12);
  --green-08: rgba(66,97,0,0.08);
  --green-25: rgba(66,97,0,0.22);
  --green-28: rgba(66,97,0,0.26);
  --green-leaf-10: rgba(66,97,0,0.12);
  --green-40: rgba(66,97,0,0.32);
  --green-50: rgba(66,97,0,0.42);
  --green-60: rgba(66,97,0,0.50);
  --green-45: rgba(66,97,0,0.36);
  --green-mossy-08: rgba(66,97,0,0.09);
  --green-tw: #426100;
  --green-tw-16: rgba(66,97,0,0.18);
  --green-tw-30: rgba(66,97,0,0.30);
  --green-leaf-30: rgba(66,97,0,0.30);

  /* Danger is a deep crimson #A50122. The dark theme's #FF2E2E
     scorches on cream and drops to ~3:1 as text. */
  --red: #a50122;
  --red-soft: #c11f3c;
  --red-pink: #d4607a;
  --red-bright: #a50122;
  --red-bright-2: #c11f3c;
  --red-warm: #a50122;
  --red-glass: #fbdfe5;
  --red-dim: rgba(165,1,34,0.09);
  --red-08: rgba(165,1,34,0.07);
  --red-18: rgba(165,1,34,0.14);
  --red-28: rgba(165,1,34,0.20);
  --red-soft-10: rgba(165,1,34,0.09);
  --red-vivid-12: rgba(165,1,34,0.12);
  --red-pulse-12: rgba(165,1,34,0.12);
  --red-pulse-35: rgba(165,1,34,0.30);
  --red-edge-08: rgba(165,1,34,0.08);
  --red-edge-16: rgba(165,1,34,0.14);
  --red-edge-22: rgba(165,1,34,0.20);
  --red-edge-40: rgba(165,1,34,0.38);

  /* Yellow is unusable as text on cream at full chroma, so the
     text slots take a deep ochre and the bright value stays a
     highlighter fill only. */
  --yellow: #8a6d00;
  --yellow-warm: #ff5e23;
  --yellow-bright: #ffe066;
  --yellow-amber: #8a6d00;
  --yellow-dim: rgba(138,109,0,0.13);
  --yellow-05: rgba(138,109,0,0.06);
  --yellow-30: rgba(138,109,0,0.30);
  --orange: #ff5e23;
  --orange-soft: #ff5e23;
  --orange-warm: #ff5e23;
  --orange-bright: #ff5e23;
  --orange-glow: #ff9166;
  --orange-skin: #ff5e23;
  --orange-06: rgba(255,94,35,0.08);
  --orange-dim: rgba(255,94,35,0.14);
  --orange-25: rgba(255,94,35,0.22);
  --orange-30: rgba(255,94,35,0.28);
  --orange-35: rgba(255,94,35,0.32);

  /* Blue sits deliberately off the indigo primary so the two
     stay tellable apart where they meet (links inside a
     brand-filled panel, chart series). */
  --blue: #0b53c0;
  --blue-sky: #0b53c0;
  --blue-12: rgba(11,83,192,0.12);
  --blue-30: rgba(11,83,192,0.30);
  --blue-sky-01: rgba(11,83,192,0.04);
  --blue-sky-05: rgba(11,83,192,0.08);
  --blue-pop-08: rgba(11,83,192,0.10);
  --blue-haze-45: rgba(11,83,192,0.38);
  --blue-haze-00: rgba(11,83,192,0);

  /* Purple — the badge pair is #510071 text on #F4DCFF, which
     is the shape our purple tokens want. */
  --purple: #510071;
  --purple-light: #a900f4;
  --purple-pink: #c77dff;
  --purple-10: rgba(81,0,113,0.09);
  --purple-12: rgba(81,0,113,0.12);
  --purple-16: rgba(81,0,113,0.16);
  --purple-20: rgba(81,0,113,0.20);
  --purple-10b: rgba(81,0,113,0.09);
  --purple-35: rgba(81,0,113,0.32);

  --status-degraded: #ff5e23;

  /* ─── Neutral overlays — warm, never neutral grey ─────
     Hover/press washes are brown-black so they tint the cream
     rather than desaturating it. A plain rgba(0,0,0,…) here
     greys the paper out and is the tell that a light theme was
     built on white. */
  --black-20: rgba(54,41,0,0.035);
  --black-25: rgba(54,41,0,0.05);
  --black-35: rgba(54,41,0,0.07);
  --black-40: rgba(54,41,0,0.09);
  --black-45: rgba(54,41,0,0.11);
  --black-50: rgba(54,41,0,0.13);
  --black-60: rgba(54,41,0,0.17);
  --bg-glass-60: rgba(251,250,246,0.88);
  --bg-glass-35: rgba(251,250,246,0.65);
  --white-00: rgba(54,41,0,0);
  --white-02: rgba(54,41,0,0.02);
  --white-03: rgba(54,41,0,0.03);
  --white-04: rgba(54,41,0,0.04);
  --white-05: rgba(54,41,0,0.05);
  --white-06: rgba(54,41,0,0.06);
  --white-07: rgba(54,41,0,0.07);
  --white-10: rgba(54,41,0,0.09);

  /* ─── Typography ─────────────────────────────────────
     Unchanged: a neutral grotesk paired with JetBrains Mono for
     every piece of UI chrome (headers, buttons, badges,
     numerics), which is already this site's convention via
     style-flat.css.

     "Unchanged" is the CONTRACT, not a note: type does not vary by
     theme, so these two lines must be byte-identical to their
     theme-dark.css counterparts. They drifted once — light carried an
     extra `Roboto` dark did not — which nothing caught, because the
     token-parity test compares NAMES and both files declared `--font`.
     Now asserted by ThemeTokenHygieneTest.typographyTokensMatchAcrossThemes. */
  --font: 'Inter', 'Inter Fallback', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --mono: 'JetBrains Mono', 'Fira Code', 'SF Mono', monospace;

  /* ─── Categorical: pipeline phases + activity buckets ─
     The light counterpart of the block in theme-dark.css; read
     by DashboardSsr.kt. The dark ramp is a saturated cyan/mint
     set built to glow on near-black — dropped on cream it reads
     as clip-art and fights the indigo, so this is a desaturated
     warm set drawn from this theme's own hues (indigo, lilac,
     sage, ochre, peach).

     Every value is held light (L≈75–85%) because the segments
     carry a near-black label on top of them. */
  --phase-boot: #c6c1b5;
  --phase-find: #c3bef5;
  --phase-fetch: #9d95f0;
  --phase-analyze: #a9b8f2;
  --phase-setup: #c2d69b;
  --phase-attach: #a3c7d4;
  --phase-atomize: #dcc3ef;
  --phase-materialize: #b3cf8e;
  --phase-report: #cbc5b8;

  --act-shell: #9d95f0;
  --act-run: #b3cf8e;
  --act-read: #a9b8f2;
  --act-write: #dcc3ef;
  --act-snapshot: #a3c7d4;
  --act-proxy: #f2b48f;
  --act-materialize: #e8d08a;
  --act-submit: #c2d69b;
  --act-tool: #efb0c8;

  /* The ink that rides ON a --phase-* / --act-* segment (.plabel). Deliberately
     the SAME value as theme-dark.css: the ramps above are held light in both
     themes, so this label is near-black in both, and every other near-black
     token flips to paper here. Do not "fix" it to --text. */
  --categorical-ink: rgba(4,17,14,0.85);

  /* ─── Radii — zero on rectangles (flat) ───────────────
     Same eight slots as theme-dark.css, and the same values.
     Soft geometry was tried here and rejected; see the note at
     the file head. Pills and circles stay round
     only where they already were, so status dots and avatars
     don't turn into squares. */
  --radius-2xs: 0;
  --radius-xs: 0;
  --radius-sm: 0;
  --radius: 0;
  --radius-lg: 0;
  --radius-xl: 0;
  --radius-circle: 50%;
  --radius-pill: 0;        /* flat aesthetic — pills are square too */
}

/* ═══════════════════════════════════════════════════════ */
/* Light-only component patches                            */
/* ═══════════════════════════════════════════════════════ */
/* Prefixed with body[data-theme="light"] so they out-specify
   style.css / style-flat.css regardless of cascade order — the
   dark theme is unaffected. Server.kt stamps data-theme on
   <body>. NOTHING here may set border-radius or box-shadow:
   the flat treatment is the house style (see the file head). */

/* Panels used to be re-filled white HERE, as a `background` override on
   .na-card / .na-stat. That is now the --card-fill token at the top of this
   file: same pixels, but everything painting on a card can read the fill
   instead of restating it. See that token for the reasoning. */

/* The Manage CTA fills solid instead of tinting.
   At --amber-dim on cream it was the weakest element in the
   topbar despite being the highest-intent one. Solid amber keeps
   the sitewide "admin actions are amber" slot (indigo is already
   the link colour two items to its left) and clears 5:1 with
   white text, 7:1 on the pressed state.
   Light-scoped: dark's --amber is a pale peach (#f5a36b), so the
   same fill there would need dark text and would invert the
   topbar's text-colour logic. Dark keeps the tint + outline. */
body[data-theme="light"] .topbar-nav > a.topbar-gold,
body[data-theme="light"] .topbar-gold {
  background: var(--amber);
  border-color: var(--amber);
  color: var(--text-on-brand);
}
body[data-theme="light"] .topbar-nav > a.topbar-gold:hover,
body[data-theme="light"] .topbar-gold:hover,
body[data-theme="light"] .topbar-nav > a.topbar-gold.active,
body[data-theme="light"] .topbar-gold.active {
  background: var(--amber-deep);
  border-color: var(--amber-deep);
  color: var(--text-on-brand);
}

/* The dev-env version badge is a hardcoded #ff5c5c in BOTH
   style.css and style-flat.css (a dark-theme value: on cream it
   glares and drops under 3:1). Pinned to the crimson --red here
   rather than edited in place, so the dark theme keeps its
   brighter badge. */
body[data-theme="light"] .bw-admin-version-dev {
  color: var(--red);
}

/* Tabular numerics — every figure is set in mono so columns of
   costs and scores line up on the decimal. */
body[data-theme="light"] .data-table td.mono,
body[data-theme="light"] .data-table td .mono,
body[data-theme="light"] .stat-value {
  font-variant-numeric: tabular-nums;
}

/* Table chrome: header is the warm inset bar, rows separate on
   hairlines only (no zebra), hover is a warm wash. */
body[data-theme="light"] .data-table th {
  background: var(--surface-1);
  color: var(--text-3);
}
body[data-theme="light"] .data-table tr:hover td {
  background: var(--surface-warm);
}

