/* web/pwa/ob-tokens.css — the one served design-token sheet (Wave 17, 17.3).
   Linked as the FIRST stylesheet on every PWA page (before each page's own <style> block, and
   before help.css via @import) so a page's own inline <style> — later in document order, equal
   or higher specificity — still wins for any token it deliberately overrides. That is the whole
   mechanism this file relies on: nothing here is `!important`, nothing raises specificity beyond
   plain `:root` / `:root:not(...)` / `:root[data-theme="dark"]`, on purpose.

   Base ramp + semantic slots below are copied VERBATIM from index.html's three :root blocks
   (post-Wave-16-polish + 17.1's focus-ring/control-edge fixes — the most complete and most
   correct source at the time of extraction, research/41 17.3 step 2). Per-page inline blocks
   were then reduced to ONLY the declarations that differ from what is here (E-17-6: a
   page-specific value that merely looks redundant stays inline, with a reason comment — nothing
   was "tidied").

   Do NOT edit this file to "fix" a page's look — that page's own inline delta is where a
   genuine per-page difference belongs. Edit this file only to change a token that is meant to
   change EVERYWHERE at once (tests/test_ob_tokens_17_3.py's baseline-equivalence suite will
   catch it if it doesn't). */
:root {
  /* base ramps (OberBuilt) */
  --paper:#FFFFFF;
  --steel-50:#F2F6FA; --steel-100:#E4ECF3; --steel-200:#C7D4E0; --steel-300:#94A8BC;
  --steel-400:#6B8197; --steel-500:#4A6076; --steel-600:#344758; --steel-700:#233140;
  --steel-800:#15232F;
  --blue-100:#DCEBFA; --blue-200:#B3D2F2; --blue-400:#4A9BE6; --blue-500:#1B7AD6;
  --blue-600:#0E5FB3; --blue-700:#0B4A8F;
  --cyan-300:#62E2EF; --cyan-500:#00B8D4; --cyan-600:#008FA5; --cyan-700:#006A7C;
  --red-100:#FBE0DD; --red-500:#E1352B; --red-600:#C32820;
  --yellow-100:#FCF3C5; --yellow-500:#F2C300;
  --green-100:#D4ECDF; --green-500:#1F8E5B; --green-600:#16704A;

  /* semantic slots — the single insertion point */
  --accent:var(--blue-600);
  --accent-weak:var(--blue-100);
  --accent-ink:var(--blue-700);
  --bg:var(--steel-50);
  --surface:var(--paper);
  --surface-2:var(--steel-100);
  --ink:#0B1620;
  --ink-soft:var(--steel-600);
  --ink-faint:var(--steel-400);
  --border:var(--steel-200);
  --border-strong:var(--steel-300);
  --focus:var(--cyan-600);   /* light: ≥3:1 focus-ring contrast (WCAG 1.4.11); dark overrides to cyan-500 below */
  --danger:var(--red-600);
  --ok:var(--green-600);
  --warn-bg:var(--yellow-100);
  --warn-ink:#6E5200;
  --warn-border:var(--yellow-500);
  --fg-on-accent:#ffffff;          /* text/icon on a brand fill */
  --hover-surface:var(--steel-50); /* button hover surface */
  --chip-bg:var(--surface);        /* atom chip surface */

  --radius:8px;          /* cards, sheets, bubbles */
  --radius-sm:4px;       /* inputs, buttons */
  --shadow:0 1px 0 rgba(11,22,32,.04), 0 2px 8px rgba(11,22,32,.07);
  --shadow-lg:0 1px 0 rgba(11,22,32,.06), 0 12px 32px rgba(11,22,32,.14);
  --maxw:760px;

  --font-display:'Saira','Helvetica Neue',system-ui,sans-serif;
  --font:'IBM Plex Sans',system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --t-fast:120ms; --t-base:160ms; --ease:cubic-bezier(0.2,0,0,1);

  /* ==========================================================================================
     NEW (17.3, additive only — no existing semantic slot above is redefined): stage/glass/
     persona tokens the rest of Wave 17 needs. design-spec.md §1 is the source of these values;
     contrast ratios are re-verified in tests/test_ob_tokens_17_3.py against that same table.
     ========================================================================================== */

  /* ---- canvas (the orb-stage background, darker than --bg so panels read as "lifted") ---- */
  --stage-bg: #060B10;
  --stage-bg-vignette: radial-gradient(120% 90% at 50% 20%, #0E1620 0%, #060B10 60%, #030608 100%);
  --stage-grid-line: rgba(124, 154, 179, 0.05);

  /* ---- glass panels (activity / tasks / transcript) ---- */
  --glass-surface: rgba(21, 35, 47, 0.62);        /* --surface #15232F at 62% */
  --glass-surface-strong: rgba(27, 44, 58, 0.78);  /* --surface-2 #1B2C3A at 78%, focused/active panel */
  --glass-border: rgba(51, 72, 92, 0.55);          /* --border-strong #33485C at 55% */
  --glass-blur: 16px;                              /* backdrop-filter: blur() */
  --glass-shadow: 0 8px 32px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.03);

  /* ---- seven persona accents — SOURCE OF TRUTH is web/pwa/agents_stage.js's PERSONA_HUES and
     its --p-hi/--p-lo/--p-glow formula (hsl(hue 72% 62%) / hsl(hue 65% 38%) /
     hsl(hue 80% 55% / .55)), re-expressed here as static page-level tokens so CSS that has no
     mounted orb element (chips, swatches, static UI) can still read a persona color without JS.
     Never hand-pick a new hex here — derive from PERSONA_HUES only.
     ⚠️ design-spec §1 correction: the persona id is `rowan`; the display name is "Rowen". The
     token is --persona-rowan; user-visible strings must still read "Rowen". */
  --persona-aria: hsl(15 72% 62%); --persona-aria-lo: hsl(15 65% 38%); --persona-aria-glow: hsl(15 80% 55% / .55);
  --persona-grumpy: hsl(66 72% 62%); --persona-grumpy-lo: hsl(66 65% 38%); --persona-grumpy-glow: hsl(66 80% 55% / .55);
  --persona-vesper: hsl(117 72% 62%); --persona-vesper-lo: hsl(117 65% 38%); --persona-vesper-glow: hsl(117 80% 55% / .55);
  --persona-forge: hsl(168 72% 62%); --persona-forge-lo: hsl(168 65% 38%); --persona-forge-glow: hsl(168 80% 55% / .55);
  --persona-axiom: hsl(219 72% 62%); --persona-axiom-lo: hsl(219 65% 38%); --persona-axiom-glow: hsl(219 80% 55% / .55);
  --persona-flint: hsl(270 72% 62%); --persona-flint-lo: hsl(270 65% 38%); --persona-flint-glow: hsl(270 80% 55% / .55);
  --persona-rowan: hsl(321 72% 62%); --persona-rowan-lo: hsl(321 65% 38%); --persona-rowan-glow: hsl(321 80% 55% / .55);

  /* ---- semantic states — ALIASES of the existing --danger/--ok/--warn-ink slots above, not a
     redefinition of them (both names now resolve identically; --state-muted is deliberately a
     desaturated neutral, never a persona hue, so "muted" can never be confused for a persona).
     This is also the one tone vocabulary loops.html and missions.html's status pills draw from
     (55:C-4) — each board still emits its own JS-side tone keys (loops.js: run|ok|bad|warn|idle;
     missions.js: run|wait|stalled), and those stay distinct (stalled ≠ warn ≠ bad: only the
     underlying token NAMES were reconciled, never the semantics), but every one of them now
     resolves through this same named set instead of a page-local raw color. ---- */
  --state-error: var(--danger);
  --state-ok: var(--ok);
  --state-attention: var(--warn-ink);
  --state-muted: var(--ink-faint);
  --state-run: var(--accent);
}
/* DARK theme. Applied when (a) the OS is dark AND the user hasn't forced a
   choice [auto], or (b) the user explicitly picks dark. The 3-way toggle sets
   data-theme = auto | light | dark; light is the :root default above. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) {
    --accent:var(--blue-400);
    --accent-weak:#12304B;
    --accent-ink:var(--blue-200);
    --bg:#0B1620;
    --surface:#15232F;
    --surface-2:#1B2C3A;
    --ink:#F4F8FB;
    --ink-soft:#B3C4D2;
    --ink-faint:#7B8E9F;
    --border:#26384A;
    --border-strong:#33485C;
    --danger:#F0857C;
    --ok:#57C99A;
    --warn-bg:#372D08;
    --warn-ink:#F7D547;
    --warn-border:#6E5A14;
    --fg-on-accent:#07121C;
    --hover-surface:var(--surface-2);
    --chip-bg:var(--surface-2);
    --focus:var(--cyan-500);   /* dark: cyan-500 already ≥6:1 on the dark surface */
    --shadow:0 1px 0 rgba(0,0,0,.3), 0 2px 8px rgba(0,0,0,.4);
    --shadow-lg:0 1px 0 rgba(0,0,0,.4), 0 14px 36px rgba(0,0,0,.55);
  }
}
:root[data-theme="dark"] {
  --accent:var(--blue-400);
  --accent-weak:#12304B;
  --accent-ink:var(--blue-200);
  --bg:#0B1620;
  --surface:#15232F;
  --surface-2:#1B2C3A;
  --ink:#F4F8FB;
  --ink-soft:#B3C4D2;
  --ink-faint:#7B8E9F;
  --border:#26384A;
  --border-strong:#33485C;
  --danger:#F0857C;
  --ok:#57C99A;
  --warn-bg:#372D08;
  --warn-ink:#F7D547;
  --warn-border:#6E5A14;
  --fg-on-accent:#07121C;
  --hover-surface:var(--surface-2);
  --chip-bg:var(--surface-2);
  --focus:var(--cyan-500);
  --shadow:0 1px 0 rgba(0,0,0,.3), 0 2px 8px rgba(0,0,0,.4);
  --shadow-lg:0 1px 0 rgba(0,0,0,.4), 0 14px 36px rgba(0,0,0,.55);
}

/* ---- the one targeted dark-canvas exception (design-spec §1): the orb-stage canvas itself
   must stay near-black EVEN under the explicit light theme — a bright white canvas behind
   glowing particle spheres reads as broken, not "light mode respected." One selector, the same
   targeted-exception shape presence.css already uses for --focus. Nothing else on the page is
   affected — every other token still flows through the normal light/dark split above. ---- */
:root[data-theme="light"] .ob-stage-canvas {
  --stage-bg: #060B10;
  --stage-bg-vignette: radial-gradient(120% 90% at 50% 20%, #0E1620 0%, #060B10 60%, #030608 100%);
  --stage-grid-line: rgba(124, 154, 179, 0.05);
}
