@import url('fonts.css');

/* ============================================================
   ACP IIT — Design Tokens
   ------------------------------------------------------------
   Three orthogonal layers, so nothing fights:

     1. SCALE      :root            type / space / radius / motion / metrics
     2. THEME      body.dark        elevation + color-scheme for the dark side
     3. PALETTE    :root[data-palette=…]   the color values themselves

   Light/dark stays exactly where it was — `body.dark`, toggled by
   toggleTheme() in assets/js/main.js, driven by localStorage["theme"].
   Palette is a separate axis on <html data-palette="…">, driven by
   localStorage["palette"]. The two never collide: palette-scoped dark
   selectors (`:root[data-palette=x] body.dark`) target <body> and so
   out-specify the generic `body.dark` block on the same element.

   ATERNOS IS THE DEFAULT AND ITS VALUES ARE UNCHANGED — the block below
   is the same one SPEC.md §12.1 requires be preserved verbatim from
   Dashboard/css/UnifiedDashboard.css:8-190. A user who never opens the
   palette picker sees exactly the colours they saw before. The alternate
   palettes are opt-in and redefine ONLY colour tokens, never scale tokens,
   so a palette can never change layout.
   ============================================================ */

:root {
    /* ── Typography ───────────────────────────────────────────
       Official Aternos Ergonomic Typography — families unchanged. */
    --font-sans: 'Play', 'Plus Jakarta Sans', 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    --font-heading: 'Play', 'Plus Jakarta Sans', 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    --font-mono: 'Roboto Mono', 'JetBrains Mono', ui-monospace, SFMono-Regular, Consolas, monospace;
    --font-spacing: 0.00em;

    /* Type scale — 7 steps replacing the 19 ad-hoc sizes the ported
       stylesheet accumulated. Nothing below --fs-2xs is permitted: 11px is
       the floor for a screen read at arm's length on a plant floor. */
    --fs-2xs: 11px;   /* uppercase micro-labels, table header caps */
    --fs-xs: 12px;    /* dense secondary text, pills, metadata */
    --fs-sm: 13px;    /* body default (compact density) */
    --fs-md: 14px;    /* card headings, comfortable body */
    --fs-lg: 16px;    /* section headings */
    --fs-xl: 20px;    /* page title, KPI values */
    --fs-2xl: 28px;   /* chart headline values */
    --fs-display: 42px; /* the thermostat dial only */

    --lh-tight: 1.2;
    --lh-base: 1.5;

    --fw-normal: 500;
    --fw-medium: 600;
    --fw-bold: 700;
    --fw-black: 800;

    /* ── Spacing — 4px base ──────────────────────────────────── */
    --s-1: 4px;
    --s-2: 6px;
    --s-3: 10px;
    --s-4: 12px;
    --s-5: 18px;
    --s-6: 24px;

    /* ── Radius — unchanged values, now the only source ───────── */
    --r-xs: 2px;
    --r-sm: 4px;
    --r-md: 6px;
    --r-lg: 8px;
    --r-xl: 12px;
    --r-pill: 9999px;

    /* ── Motion ───────────────────────────────────────────────── */
    --dur-fast: 120ms;
    --dur-base: 180ms;
    --dur-slow: 300ms;
    --ease: cubic-bezier(0.16, 1, 0.3, 1);

    /* ── Shell metrics ────────────────────────────────────────── */
    --rail-w: 224px;
    --rail-w-collapsed: 60px;
    --header-h: 56px;
    --content-max: 1600px;

    /* ── Density (compact is the default; see §1.3) ───────────── */
    --row-h: 34px;          /* nav item, toolbar control */
    --row-h-table: 38px;    /* table row */
    --control-h: 34px;      /* input, select, button */
    --pad-card: var(--s-3) var(--s-4);
    --gap-grid: var(--s-2);

    /* Legacy compatibility aliases — kept so no existing rule breaks. */
    --sb-wide: 220px;

    /* ── Elevation — light side. Two real levels do the work; the -sm/-lg
       aliases remain so ported rules keep resolving. ────────────── */
    --shadow-xs: 0 1px 2px rgba(22, 28, 33, 0.04);
    --shadow-sm: 0 2px 4px rgba(22, 28, 33, 0.06);
    --shadow-md: 0 6px 16px -2px rgba(22, 28, 33, 0.08), 0 2px 6px -1px rgba(22, 28, 33, 0.04);
    --shadow-lg: 0 16px 36px -4px rgba(22, 28, 33, 0.12), 0 4px 12px -2px rgba(22, 28, 33, 0.06);
    --shadow-glow: 0 0 24px rgba(43, 135, 211, 0.20);
}

body.density-comfortable {
    --s-1: 4px;
    --s-2: 8px;
    --s-3: 11px;
    --s-4: 15px;
    --s-5: 21px;
    --s-6: 30px;

    --row-h: 44px;
    --row-h-table: 48px;
    --control-h: 40px;
    --pad-card: var(--s-4) var(--s-5);
    --gap-grid: var(--s-3);
}

/* Elevation — dark side. Palette-independent: shadow is a property of the
   theme, not of the hue set, so it is defined once here rather than
   repeated in all four dark palette blocks. */
body.dark {
    --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-sm: 0 2px 6px rgba(0, 0, 0, 0.5);
    --shadow-md: 0 8px 24px -2px rgba(0, 0, 0, 0.6), 0 2px 8px rgba(0, 0, 0, 0.4);
    --shadow-lg: 0 20px 48px -4px rgba(0, 0, 0, 0.75), 0 6px 16px rgba(0, 0, 0, 0.5);
}

/* ============================================================
   PALETTE — Aternos (default)
   Values copied verbatim from Dashboard/css/UnifiedDashboard.css:8-190,
   per SPEC.md §12.1. Do not "modernise" these; add a new palette instead.
   ============================================================ */

:root,
:root[data-palette="aternos"] {
    /* Aternos Official CSS Variables */
    --color-main: #2b87d3;
    --color-dark: #2d3943;
    --color-light: #f0f0f0;
    --color-danger: #f62451;
    --color-success: #1fd78d;
    --color-warn: #eb7b59;
    --color-loading: #a4a4a4;
    --color-dark-mode: #161c21;
    --color-dark-text: #47535d;
    --color-dark-mark: #40505c;
    --color-dark-hover: #47535d;

    /* Canvas & surfaces */
    --bg: #f0f0f0;
    --bg-subtle: #e4e8ec;
    --card: #ffffff;
    --card-glass: rgba(255, 255, 255, 0.95);
    --surface: #ffffff;
    --surface-2: #eef2f6;
    --surface-3: #e0e6ed;

    --text: #161c21;
    --text-2: #2d3943;
    --muted: #47535d;
    --subtle: #6c7a87;

    --border: #d7d7d7;
    --border-subtle: #e8e8e8;
    --border-strong: #c0c0c0;
    --border-focus: #2b87d3;

    /* Brand & semantic */
    --accent: #2b87d3;
    --accent-hover: #2d87d3;
    --accent-active: #0c396a;
    --accent-soft: rgba(43, 135, 211, 0.12);
    --accent-glow: rgba(43, 135, 211, 0.25);

    --cyan: #2b87d3;
    --cyan-soft: rgba(43, 135, 211, 0.12);
    --green: #1fd78d;
    --green-soft: rgba(31, 215, 141, 0.12);
    --green-glow: rgba(31, 215, 141, 0.25);
    --amber: #eb7b59;
    --amber-soft: rgba(235, 123, 89, 0.12);
    --amber-glow: rgba(235, 123, 89, 0.25);
    --red: #f62451;
    --red-soft: rgba(246, 36, 81, 0.12);
    --red-glow: rgba(246, 36, 81, 0.25);
    --blue: #2b87d3;
    --blue-soft: rgba(43, 135, 211, 0.12);
    --purple: #7c3aed;
    --purple-soft: rgba(124, 58, 237, 0.10);

    /* Semantic additions — these replace hardcoded literals that were
       scattered through components.css and the view templates. */
    --overlay: rgba(15, 23, 42, 0.55);
    --focus-ring: #2b87d3;
    --grid-line: rgba(22, 28, 33, 0.08);
    --on-accent: #ffffff;

    --fg: var(--text);
    --bg-card-sub: var(--surface);

    color-scheme: light;
}

body.dark {
    /* Aternos Dark Theme Palette (Signature Dark Canvas & Slate Cards) */
    --bg: #161c21;
    --bg-subtle: #1c242b;
    --card: #2d3943;
    --card-glass: rgba(45, 57, 67, 0.90);
    --surface: #2d3943;
    --surface-2: #374652;
    --surface-3: #40505c;

    --text: #f0f0f0;
    --text-2: #d7d7d7;
    --muted: #a4a4a4;
    --subtle: #47535d;

    --border: #374652;
    --border-subtle: #2b3943;
    --border-strong: #40505c;
    --border-focus: #2b87d3;

    --shadow-glow: 0 0 30px rgba(43, 135, 211, 0.25);

    --accent: #2b87d3;
    --accent-hover: #2d87d3;
    --accent-active: #0c396a;
    --accent-soft: rgba(43, 135, 211, 0.18);
    --accent-glow: rgba(43, 135, 211, 0.35);

    --cyan: #2b87d3;
    --cyan-soft: rgba(43, 135, 211, 0.16);
    --green: #1fd78d;
    --green-soft: rgba(31, 215, 141, 0.16);
    --green-glow: rgba(31, 215, 141, 0.35);
    --amber: #eb7b59;
    --amber-soft: rgba(235, 123, 89, 0.16);
    --amber-glow: rgba(235, 123, 89, 0.35);
    --red: #f62451;
    --red-soft: rgba(246, 36, 81, 0.16);
    --red-glow: rgba(246, 36, 81, 0.35);
    --blue: #2b87d3;
    --blue-soft: rgba(43, 135, 211, 0.16);
    --purple: #a855f7;
    --purple-soft: rgba(168, 85, 247, 0.14);

    --overlay: rgba(0, 0, 0, 0.65);
    --focus-ring: #57a8e8;
    --grid-line: rgba(240, 240, 240, 0.10);
    --on-accent: #ffffff;

    --fg: var(--text);
    --bg-card-sub: var(--surface);

    color-scheme: dark;
}

/* ============================================================
   PALETTE — Slate
   Desaturated neutral greys, one restrained blue. Every text/background
   pair here clears WCAG AA (4.5:1); --muted is the token that fails most
   often elsewhere, so it is deliberately darker than Aternos's.
   ============================================================ */

:root[data-palette="slate"] {
    --bg: #f4f5f7;
    --bg-subtle: #eaecef;
    --card: #ffffff;
    --card-glass: rgba(255, 255, 255, 0.95);
    --surface: #ffffff;
    --surface-2: #f1f3f5;
    --surface-3: #e4e7ea;

    --text: #14181d;
    --text-2: #2f3740;
    --muted: #59636e;
    --subtle: #7b858f;

    --border: #d6dade;
    --border-subtle: #e6e9ec;
    --border-strong: #b9c0c7;
    --border-focus: #1f6feb;

    --accent: #1f6feb;
    --accent-hover: #1a5fd0;
    --accent-active: #14488f;
    --accent-soft: rgba(31, 111, 235, 0.10);
    --accent-glow: rgba(31, 111, 235, 0.22);

    --cyan: #0e7490;
    --cyan-soft: rgba(14, 116, 144, 0.10);
    --green: #0f7a4d;
    --green-soft: rgba(15, 122, 77, 0.10);
    --green-glow: rgba(15, 122, 77, 0.22);
    --amber: #a45a12;
    --amber-soft: rgba(164, 90, 18, 0.10);
    --amber-glow: rgba(164, 90, 18, 0.22);
    --red: #c02942;
    --red-soft: rgba(192, 41, 66, 0.10);
    --red-glow: rgba(192, 41, 66, 0.22);
    --blue: #1f6feb;
    --blue-soft: rgba(31, 111, 235, 0.10);
    --purple: #6d3fd4;
    --purple-soft: rgba(109, 63, 212, 0.10);

    --overlay: rgba(20, 24, 29, 0.55);
    --focus-ring: #1f6feb;
    --grid-line: rgba(20, 24, 29, 0.08);
    --on-accent: #ffffff;

    --shadow-glow: 0 0 24px rgba(31, 111, 235, 0.18);

    --fg: var(--text);
    --bg-card-sub: var(--surface);

    color-scheme: light;
}

:root[data-palette="slate"] body.dark {
    --bg: #14171a;
    --bg-subtle: #1a1e22;
    --card: #1e2429;
    --card-glass: rgba(30, 36, 41, 0.92);
    --surface: #1e2429;
    --surface-2: #262d33;
    --surface-3: #303840;

    --text: #e8ebee;
    --text-2: #c3cad1;
    --muted: #98a2ab;
    --subtle: #6c767f;

    --border: #2f373e;
    --border-subtle: #262d33;
    --border-strong: #3d464e;
    --border-focus: #4d94f0;

    --accent: #4d94f0;
    --accent-hover: #6aa6f4;
    --accent-active: #2f6dbd;
    --accent-soft: rgba(77, 148, 240, 0.16);
    --accent-glow: rgba(77, 148, 240, 0.32);

    --cyan: #38b2c8;
    --cyan-soft: rgba(56, 178, 200, 0.16);
    --green: #35d08a;
    --green-soft: rgba(53, 208, 138, 0.16);
    --green-glow: rgba(53, 208, 138, 0.32);
    --amber: #f0a55c;
    --amber-soft: rgba(240, 165, 92, 0.16);
    --amber-glow: rgba(240, 165, 92, 0.32);
    --red: #ff5c78;
    --red-soft: rgba(255, 92, 120, 0.16);
    --red-glow: rgba(255, 92, 120, 0.32);
    --blue: #4d94f0;
    --blue-soft: rgba(77, 148, 240, 0.16);
    --purple: #a883f5;
    --purple-soft: rgba(168, 131, 245, 0.14);

    --overlay: rgba(0, 0, 0, 0.66);
    --focus-ring: #4d94f0;
    --grid-line: rgba(232, 235, 238, 0.10);
    --on-accent: #0d1117;

    --shadow-glow: 0 0 28px rgba(77, 148, 240, 0.28);

    --fg: var(--text);
    --bg-card-sub: var(--surface);

    color-scheme: dark;
}

/* ============================================================
   PALETTE — Control Room
   Dark-first, low-emission. Built for a dim room or a wall panel on a
   night shift: the dark side drops the canvas well below the Aternos
   dark ground and uses instrument colours (cyan / sodium amber /
   signal red) rather than web colours. The light side is a low-glare
   warm neutral rather than a bright white.
   ============================================================ */

:root[data-palette="control-room"] {
    --bg: #e8e6e1;
    --bg-subtle: #dedbd4;
    --card: #f7f6f3;
    --card-glass: rgba(247, 246, 243, 0.95);
    --surface: #f7f6f3;
    --surface-2: #eeece7;
    --surface-3: #e0ddd6;

    --text: #1c1a17;
    --text-2: #34312c;
    --muted: #5c574f;
    --subtle: #7d7770;

    --border: #cfcbc3;
    --border-subtle: #e0ddd6;
    --border-strong: #b3aea4;
    --border-focus: #0b6e99;

    --accent: #0b6e99;
    --accent-hover: #095b80;
    --accent-active: #06425c;
    --accent-soft: rgba(11, 110, 153, 0.11);
    --accent-glow: rgba(11, 110, 153, 0.24);

    --cyan: #0b6e99;
    --cyan-soft: rgba(11, 110, 153, 0.11);
    --green: #1a7f47;
    --green-soft: rgba(26, 127, 71, 0.11);
    --green-glow: rgba(26, 127, 71, 0.24);
    --amber: #a35a00;
    --amber-soft: rgba(163, 90, 0, 0.11);
    --amber-glow: rgba(163, 90, 0, 0.24);
    --red: #b02a37;
    --red-soft: rgba(176, 42, 55, 0.11);
    --red-glow: rgba(176, 42, 55, 0.24);
    --blue: #0b6e99;
    --blue-soft: rgba(11, 110, 153, 0.11);
    --purple: #6b3fa0;
    --purple-soft: rgba(107, 63, 160, 0.10);

    --overlay: rgba(28, 26, 23, 0.55);
    --focus-ring: #0b6e99;
    --grid-line: rgba(28, 26, 23, 0.09);
    --on-accent: #ffffff;

    --shadow-glow: 0 0 24px rgba(11, 110, 153, 0.18);

    --fg: var(--text);
    --bg-card-sub: var(--surface);

    color-scheme: light;
}

:root[data-palette="control-room"] body.dark {
    --bg: #0b0f12;
    --bg-subtle: #0f1418;
    --card: #151b21;
    --card-glass: rgba(21, 27, 33, 0.92);
    --surface: #151b21;
    --surface-2: #1c242b;
    --surface-3: #26303a;

    --text: #d6e0e8;
    --text-2: #adbac6;
    --muted: #7d8b98;
    --subtle: #5a6673;

    --border: #232d36;
    --border-subtle: #1a222a;
    --border-strong: #32404c;
    --border-focus: #38b6e0;

    --accent: #38b6e0;
    --accent-hover: #57c6ea;
    --accent-active: #1f8bb0;
    --accent-soft: rgba(56, 182, 224, 0.15);
    --accent-glow: rgba(56, 182, 224, 0.34);

    --cyan: #38b6e0;
    --cyan-soft: rgba(56, 182, 224, 0.15);
    --green: #3ddc84;
    --green-soft: rgba(61, 220, 132, 0.15);
    --green-glow: rgba(61, 220, 132, 0.34);
    --amber: #ffb02e;
    --amber-soft: rgba(255, 176, 46, 0.15);
    --amber-glow: rgba(255, 176, 46, 0.34);
    --red: #ff4d5e;
    --red-soft: rgba(255, 77, 94, 0.15);
    --red-glow: rgba(255, 77, 94, 0.34);
    --blue: #38b6e0;
    --blue-soft: rgba(56, 182, 224, 0.15);
    --purple: #9d7bf0;
    --purple-soft: rgba(157, 123, 240, 0.14);

    --overlay: rgba(0, 0, 0, 0.74);
    --focus-ring: #38b6e0;
    --grid-line: rgba(214, 224, 232, 0.09);
    --on-accent: #06131a;

    --shadow-glow: 0 0 30px rgba(56, 182, 224, 0.30);

    --fg: var(--text);
    --bg-card-sub: var(--surface);

    color-scheme: dark;
}

/* ============================================================
   PALETTE — High Contrast
   Accessibility / bright-sunlight palette. Body text clears WCAG AAA
   (7:1), borders are visible rather than hinted, and the soft washes are
   pulled right down so text over them stays legible. Pairs with the
   shape-plus-colour status cues in components.css so nothing depends on
   hue alone.
   ============================================================ */

:root[data-palette="high-contrast"] {
    --bg: #ffffff;
    --bg-subtle: #f2f2f2;
    --card: #ffffff;
    --card-glass: #ffffff;
    --surface: #ffffff;
    --surface-2: #f0f0f0;
    --surface-3: #e0e0e0;

    --text: #000000;
    --text-2: #1a1a1a;
    --muted: #3d3d3d;
    --subtle: #545454;

    --border: #767676;
    --border-subtle: #949494;
    --border-strong: #000000;
    --border-focus: #0043a8;

    --accent: #0043a8;
    --accent-hover: #003182;
    --accent-active: #00205c;
    --accent-soft: rgba(0, 67, 168, 0.10);
    --accent-glow: rgba(0, 67, 168, 0.28);

    --cyan: #005f73;
    --cyan-soft: rgba(0, 95, 115, 0.10);
    --green: #0a5c2e;
    --green-soft: rgba(10, 92, 46, 0.10);
    --green-glow: rgba(10, 92, 46, 0.28);
    --amber: #7a4100;
    --amber-soft: rgba(122, 65, 0, 0.10);
    --amber-glow: rgba(122, 65, 0, 0.28);
    --red: #a4001f;
    --red-soft: rgba(164, 0, 31, 0.10);
    --red-glow: rgba(164, 0, 31, 0.28);
    --blue: #0043a8;
    --blue-soft: rgba(0, 67, 168, 0.10);
    --purple: #4b0f8f;
    --purple-soft: rgba(75, 15, 143, 0.10);

    --overlay: rgba(0, 0, 0, 0.66);
    --focus-ring: #0043a8;
    --grid-line: rgba(0, 0, 0, 0.22);
    --on-accent: #ffffff;

    --shadow-xs: 0 0 0 1px rgba(0, 0, 0, 0.12);
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.22);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.26);
    --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.34);
    --shadow-glow: 0 0 0 2px rgba(0, 67, 168, 0.40);

    --fg: var(--text);
    --bg-card-sub: var(--surface);

    color-scheme: light;
}

:root[data-palette="high-contrast"] body.dark {
    --bg: #000000;
    --bg-subtle: #0a0a0a;
    --card: #0d0d0d;
    --card-glass: #0d0d0d;
    --surface: #0d0d0d;
    --surface-2: #1a1a1a;
    --surface-3: #2b2b2b;

    --text: #ffffff;
    --text-2: #f0f0f0;
    --muted: #c7c7c7;
    --subtle: #a3a3a3;

    --border: #8a8a8a;
    --border-subtle: #5c5c5c;
    --border-strong: #ffffff;
    --border-focus: #6fb3ff;

    --accent: #6fb3ff;
    --accent-hover: #8ec5ff;
    --accent-active: #4a93e6;
    --accent-soft: rgba(111, 179, 255, 0.18);
    --accent-glow: rgba(111, 179, 255, 0.40);

    --cyan: #5fd4ec;
    --cyan-soft: rgba(95, 212, 236, 0.18);
    --green: #4ee88f;
    --green-soft: rgba(78, 232, 143, 0.18);
    --green-glow: rgba(78, 232, 143, 0.40);
    --amber: #ffc14d;
    --amber-soft: rgba(255, 193, 77, 0.18);
    --amber-glow: rgba(255, 193, 77, 0.40);
    --red: #ff707f;
    --red-soft: rgba(255, 112, 127, 0.18);
    --red-glow: rgba(255, 112, 127, 0.40);
    --blue: #6fb3ff;
    --blue-soft: rgba(111, 179, 255, 0.18);
    --purple: #c39cff;
    --purple-soft: rgba(195, 156, 255, 0.16);

    --overlay: rgba(0, 0, 0, 0.80);
    --focus-ring: #6fb3ff;
    --grid-line: rgba(255, 255, 255, 0.24);
    --on-accent: #000000;

    --shadow-xs: 0 0 0 1px rgba(255, 255, 255, 0.16);
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.7);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.8);
    --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.9);
    --shadow-glow: 0 0 0 2px rgba(111, 179, 255, 0.55);

    --fg: var(--text);
    --bg-card-sub: var(--surface);

    color-scheme: dark;
}

/* ============================================================
   PALETTE — Graphite
   Extracted from the Graphite design skill's reference (a dark AI-agent/
   observability console) — .claude/skills/graphite/references/tokens.md.
   Near-black layered surfaces, hairline warm-white borders, a signature
   orange accent, flat border-based elevation. Only the scale/layout
   tokens carry over unchanged from :root above (per this file's own rule
   that a palette redefines colour, never layout); this section pins every
   colour to its documented Graphite value, or marks it [inferred] where
   the reference genuinely never showed one.

   Graphite's source is dark-only — there is no light-mode reference at
   all. Per tokens.md's own instruction ("flag gaps honestly... propose a
   value that's consistent with the rest of the system rather than
   presenting a guess as if it were extracted"), the LIGHT block below is
   entirely [inferred]: the same design principles (flat layered surfaces,
   hairline borders, the same orange/cyan/violet accent identity) inverted
   onto a light near-white ladder. The body.dark block after it is the
   authentic, sourced set of values — that's Graphite's real identity.
   ============================================================ */

:root[data-palette="graphite"] {
    /* [inferred light companion — see note above] */
    --bg: #f7f6f4;
    --bg-subtle: #efeeec;
    --card: #ffffff;
    --card-glass: rgba(255, 255, 255, 0.95);
    --surface: #f2f1ef;
    --surface-2: #e8e7e4;
    --surface-3: #dcdbd7;

    --text: #1a1a1a;
    --text-2: #333333;
    --muted: #6b6b6b;
    --subtle: #8a8a8a;

    --border: rgba(20, 20, 20, 0.10);
    --border-subtle: rgba(20, 20, 20, 0.06);
    --border-strong: rgba(20, 20, 20, 0.18);
    --border-focus: #ff7c3e;

    /* Accent kept identical to the sourced dark value below — it's
       Graphite's signature/categorical-identity hue, not something that
       should shift with theme. */
    --accent: #ff7c3e;
    --accent-hover: #e8672c;
    --accent-active: #c9531f;
    --accent-soft: rgba(255, 124, 62, 0.12);
    --accent-glow: rgba(255, 124, 62, 0.25);

    /* Semantic hues darkened from their sourced dark-mode values, which
       are too pale to hold contrast on a light surface. */
    --cyan: #2a92b8;
    --cyan-soft: rgba(42, 146, 184, 0.12);
    --green: #1f9d5c;
    --green-soft: rgba(31, 157, 92, 0.12);
    --green-glow: rgba(31, 157, 92, 0.24);
    --amber: #a8720a;
    --amber-soft: rgba(168, 114, 10, 0.12);
    --amber-glow: rgba(168, 114, 10, 0.24);
    --red: #d33434;
    --red-soft: rgba(211, 52, 52, 0.12);
    --red-glow: rgba(211, 52, 52, 0.24);
    --blue: #3b82f6;
    --blue-soft: rgba(59, 130, 246, 0.12);
    --purple: #9457e0;
    --purple-soft: rgba(148, 87, 224, 0.10);

    --overlay: rgba(20, 20, 20, 0.50);
    --focus-ring: #ff7c3e;
    --grid-line: rgba(20, 20, 20, 0.08);
    /* Accent is a light, saturated orange — dark text reads far better on
       it than white, regardless of overall theme (same reasoning the
       Control Room palette's own light-hued accent uses). */
    --on-accent: #1a1a1a;

    --shadow-glow: 0 0 24px rgba(255, 124, 62, 0.18);

    --fg: var(--text);
    --bg-card-sub: var(--surface);

    color-scheme: light;
}

:root[data-palette="graphite"] body.dark {
    /* [sourced — tokens.md § Surfaces] */
    --bg: #0d0d0d;
    --bg-subtle: #131313;
    --card: #171717;
    --card-glass: rgba(23, 23, 23, 0.90);
    --surface: #1a1a19;
    --surface-2: #202020;
    --surface-3: #262626;

    --text: #f0f0f0;
    --text-2: #e0e0e0;
    --muted: #7a7a7a;
    --subtle: #555555;

    --border: rgba(255, 248, 241, 0.09);
    --border-subtle: rgba(255, 255, 255, 0.05);
    --border-strong: rgba(255, 255, 255, 0.16);
    --border-focus: #ff7c3e;

    --accent: #ff7c3e;
    --accent-hover: #ff9660;
    --accent-active: #cc5f2c;
    --accent-soft: rgba(255, 124, 62, 0.15);
    --accent-glow: rgba(255, 124, 62, 0.35);

    --cyan: #6fc6ee;
    --cyan-soft: rgba(111, 198, 238, 0.15);
    --green: #3ddc84;
    --green-soft: rgba(61, 220, 132, 0.15);
    --green-glow: rgba(61, 220, 132, 0.35);
    --amber: #ca8a04;
    --amber-soft: rgba(202, 138, 4, 0.15);
    --amber-glow: rgba(202, 138, 4, 0.35);
    /* Not present in the source file — kept at the saturation/lightness of
       the other status hues per tokens.md's own note there; flagged as
       [inferred] rather than extracted. */
    --red: #ef4444;
    --red-soft: rgba(239, 68, 68, 0.15);
    --red-glow: rgba(239, 68, 68, 0.35);
    --blue: #3b82f6;
    --blue-soft: rgba(59, 130, 246, 0.15);
    --purple: #b98aff;
    --purple-soft: rgba(185, 138, 255, 0.14);

    --overlay: rgba(0, 0, 0, 0.70);
    --focus-ring: #ff7c3e;
    --grid-line: rgba(240, 240, 240, 0.10);
    --on-accent: #1a1a1a;

    /* Flat-by-design — tokens.md: "no shadow token in the base system,"
       hierarchy comes from the surface ladder + hairline borders instead.
       Overridden here (the same way High Contrast overrides shadows above)
       rather than inheriting body.dark's generic elevation shadows, which
       would contradict that. */
    --shadow-xs: 0 0 0 1px rgba(255, 255, 255, 0.04);
    --shadow-sm: 0 0 0 1px rgba(255, 255, 255, 0.06);
    --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.35), 0 0 0 1px rgba(255, 255, 255, 0.06);
    --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.40);
    --shadow-glow: 0 0 24px rgba(255, 124, 62, 0.30);

    --fg: var(--text);
    --bg-card-sub: var(--surface);

    color-scheme: dark;
}
