/* Four themes: Ledger (default), Console, Daylight, Nocturne.
 *
 * NOCTURNE is the 2026-08-07 design pack's dark theme, landed as an OPT-IN
 * fourth option -- the default stays `ledger` by operator ruling. It is the
 * only theme whose values are not this file's own invention: every one of them
 * is transcribed from handoff-v2/tokens.css, which the pack declares to be its
 * single source of truth. The earlier note here -- that th-nocturne was omitted
 * because the first bundle gave it no CSS block of its own -- is superseded:
 * the v2 pack ships a full token set for it.
 *
 * WHERE A VALUE LIVES is the load-bearing decision in this file. tokens.css
 * declares everything on a bare `:root`, which the console cannot copy: its
 * themes are CLASS-scoped, so a colour on :root is inherited by th-day and a
 * dark value inherited by the light theme is precisely the bug the
 * `color-scheme` guard below exists for. So the port splits the token set:
 *
 *   :root         structure only -- type scale, spacing, fixed heights and
 *                 widths, radii, z-index layers, focus, motion, and the
 *                 --grid-* NAMES. Theme-independent values, or a var()
 *                 indirection through a token every theme declares for itself.
 *                 No colour literal. Ever.
 *   .th-nocturne  every colour token, the legacy aliases the live stylesheet
 *                 reads (--r/--r2, --ok/--warn/--bad, --line2/--vline, --hair,
 *                 --filine, --flowbg, --page-gap, --kpi-*, --row-*), and the
 *                 --chart-* family that tokens.css omits outright. Without that
 *                 last one the dashboard and trends charts would silently
 *                 un-theme -- a missing custom property paints nothing and
 *                 warns nobody, the same failure mode as the `color-scheme`
 *                 story below.
 *
 * The variables below the documented set (--filine, --flowbg, --hair, --pop,
 * --track and the accent tint pair) are used by the prototype but absent from
 * the README. They are carried here rather than rediscovered later.
 *
 * EVERY theme declares `color-scheme`, and it is the most load-bearing line in
 * each block. It is the only way to tell the browser that the widgets IT paints
 * -- the <select> popup, scrollbars, checkboxes, the autofill background, the
 * search field's clear button -- belong to a dark page. Its initial value is
 * `normal`, which resolves to LIGHT, and `prefers-color-scheme` does not change
 * that: an author has to opt in. Without it the option list rendered on a white
 * UA canvas while the options inherited the theme's near-white text, so the
 * dropdowns in both dark themes were white on white and only the row under the
 * OS highlight bar was legible. Author CSS on <option> cannot rescue that on
 * macOS, where the popup ignores author colours entirely -- so app.css styles
 * the options AND every theme declares its scheme. See phase7-repairs/004.
 */

@font-face {
  font-family: 'Inter';
  src: url('/assets/vendor/inter/InterVariable.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --font-body: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-heading: var(--font-body);
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --ok: #8fd3b0;
  --warn: #dcc38c;
  --bad: #e0a0a0;

  /* ===== design-pack structural tokens =====================================
   * Transcribed from handoff-v2/tokens.css. Structure only -- see the file
   * header for why nothing coloured may join them.
   */

  /* -- type scale. Dense on purpose: an operator console read for hours. ---
   * Nothing is below 9px, and 9-10px is reserved for uppercase micro-labels
   * that are letterspaced to stay legible. */
  --fs-micro: 9px;      /* grid header, KPI label, rail section label */
  --fs-micro-2: 9.5px;  /* status bar, pill text */
  --fs-xs: 10px;        /* secondary notes, tab labels */
  --fs-sm: 10.5px;      /* controls, chips, tab strip, mono cells */
  --fs-base: 11px;      /* grid rows, nav items, list rows */
  --fs-md: 11.5px;      /* dialog body, selection detail */
  --fs-lg: 12px;        /* shell base font-size */
  --fs-xl: 12.5px;      /* flow card title, section emphasis */
  --fs-2xl: 13.5px;     /* brand mark, dialog heading */
  --fs-figure: 18px;    /* KPI figure */

  --lh-tight: 1.15;
  --lh-base: 1.45;
  --lh-prose: 1.6;

  --fw-regular: 400;
  --fw-medium: 500;     /* the heaviest weight in the system. Never 600+. */

  --ls-caps: 0.06em;
  --ls-caps-wide: 0.11em;
  --ls-caps-xwide: 0.13em;
  --ls-tight: -0.02em;

  /* -- spacing. 4px-ish but compressed; use these, not arbitrary px. ------ */
  --space-1: 2px;
  --space-2: 4px;
  --space-3: 5px;
  --space-4: 6px;
  --space-5: 7px;       /* grid cell horizontal padding */
  --space-6: 8px;
  --space-7: 9px;       /* card grid gap, card body padding */
  --space-8: 10px;      /* card header padding */
  --space-9: 11px;      /* page padding, card stack gap */
  --space-10: 14px;     /* dialog padding */
  --space-12: 20px;

  /* -- fixed heights. The console is chrome-heavy; these are load-bearing. */
  --h-topbar: 34px;
  --h-tabstrip: 27px;
  --h-tab: 25px;
  --h-viewhead: 27px;
  --h-toolbar: 27px;
  --h-statusbar: 22px;
  --h-control: 22px;
  --h-control-lg: 24px;
  --h-button: 26px;
  --h-field: 28px;
  --h-field-sm: 21px;
  --h-navitem: 21px;
  --h-navsection: 22px;
  --h-row: 27px;        /* grid row, relaxed density */
  --h-row-dense: 23px;  /* grid row, compact density */
  --h-row-header: 26px; /* grid header row */
  --h-listrow: 26px;
  --h-pill: 15px;
  --h-chip: 20px;

  /* -- fixed widths ------------------------------------------------------ */
  --w-sidebar: 198px;
  --w-rail: 212px;
  --w-rail-collapsed: 26px;
  --w-tab-min: 92px;
  --w-tab-max: 190px;
  --w-dialog: 380px;
  --w-dialog-wide: 680px;
  --w-dialog-xw: 900px;
  --w-palette: 520px;

  /* -- radii. The legacy --r/--r2 stay per-theme; these are the new names. */
  --radius-0: 0;
  --radius-xs: 2.5px;
  --radius-sm: 4px;
  --radius-md: 5px;     /* nav item, chip, control (= legacy --r2) */
  --radius-lg: 7px;     /* card, KPI, flow card (= legacy --r) */
  --radius-xl: 10px;
  --radius-pill: 999px;

  /* -- focus. Always this ring, never the browser default. ----------------
   * The colour arrives through --color-accent, which every theme declares, so
   * this resolves per theme and carries no dark value into th-day. */
  --focus-ring: 2px solid var(--color-accent);
  --focus-offset: 2px;

  /* -- motion. There is almost none, on purpose. ------------------------- */
  --dur-fast: 120ms;
  --dur-drawer: 180ms;
  --ease: cubic-bezier(0.2, 0, 0.2, 1);
  --toast-life: 2200ms;
  --spinner: 700ms linear infinite;

  /* -- z-index. A closed list: nothing may invent a layer outside it. -----
   * These are the DESIGN's layers, declared for the screens that adopt them.
   * app.css still carries the console's own older numbering (scrim 50, toast
   * 60, mobile tabs 30); reconciling the two is a shell change, not a theme
   * change, and belongs to the pane wave. */
  --z-grid-header: 2;
  --z-pane-resize: 12;
  --z-dropzone: 14;
  --z-scrim: 40;
  --z-dialog: 41;
  --z-toast: 50;

  /* -- the --grid-* NAMES ------------------------------------------------
   * tokens.css's re-theming contract: every visual property of the grid is a
   * --grid-* token, and app.css maps those onto the vendored theme's --ag-*
   * surface. The names live here so ALL FOUR themes resolve them; the values
   * are indirections through tokens each theme already declares, so ledger,
   * console and day resolve to exactly what they resolved to before this
   * block existed. Nocturne re-points the handful where the design differs.
   *
   * Do not invert this: a --grid-* pointing at a nocturne-only colour would
   * be an invalid value in the other three themes, and an invalid value in a
   * custom property is inherited as the guaranteed-invalid one -- the grid
   * would lose its hover, not fall back to it. */
  --grid-bg: var(--color-surface);
  --grid-fg: var(--color-text);
  --grid-header-bg: var(--head);
  --grid-header-fg: var(--color-neutral-500);
  --grid-border: var(--color-neutral-900);
  --grid-row-border: var(--line2);
  --grid-cell-border: var(--vline);
  --grid-row-hover: var(--row-hover);
  --grid-row-selected: var(--row-selected);
  --grid-row-stripe: var(--row-stripe);
  --grid-totals-bg: var(--sub);
  --grid-sort-indicator: var(--color-accent);
  /* READ SINCE lane W6: app.css styles every scrollbar in the console from
   * these three, so a theme's bars come out of its own neutral ramp. The track
   * is `transparent` rather than a surface colour, as the pack's own rule has
   * it -- a gutter that paints its own ground draws a second border down the
   * side of every scrolling pane. `transparent` is a keyword, not a colour
   * literal, so it is safe on :root where th-day inherits it. */
  --grid-scrollbar-thumb: var(--color-neutral-800);
  --grid-scrollbar-thumb-hover: var(--color-neutral-700);
  --grid-scrollbar-track: transparent;
  /* Heights are declared by the design and ENFORCED IN JS: the vendored grid
   * takes them as row options, not as CSS. grids.js rowHeights() is the one
   * place they are applied, and it now serves 27/23/26 to every theme. */
  --grid-header-height: var(--h-row-header);
  --grid-row-height: var(--h-row);
  --grid-row-height-dense: var(--h-row-dense);
  /* The three the live grid hard-coded. They keep their live values here so
   * the existing themes are untouched; nocturne moves them onto the scale. */
  --grid-cell-padding-x: 9px;
  --grid-font-size: 12px;
  --grid-header-font-size: 10px;
  --grid-scrollbar-size: 9px;
}

/* --- Theme A: Ledger (default, recommended) ------------------------------
 * Rules instead of boxes. Cards have no fill and no border, only a top rule;
 * statuses are coloured text rather than pills; KPIs are columns separated by
 * left rules. The accent is used for the active nav border, the sort arrow,
 * links and the focus ring -- nothing else.
 */
.th-ledger {
  color-scheme: dark;
  --color-bg: #14151a;
  --panel: #101116;
  --bar: #14151a;
  --color-surface: transparent;
  --color-neutral-300: #c8c9d2;
  --color-neutral-400: #9a9db0;
  --color-neutral-500: #82859a;
  --color-neutral-600: #6c7080;
  --color-neutral-700: #4c5060;
  --color-neutral-800: rgba(255, 255, 255, 0.10);
  --color-neutral-900: rgba(255, 255, 255, 0.08);
  --line2: rgba(255, 255, 255, 0.06);
  --vline: transparent;
  --head: transparent;
  --sub: transparent;
  --hair: rgba(255, 255, 255, 0.14);
  --pop: #1c1d24;
  --fibg: rgba(255, 255, 255, 0.03);
  --filine: rgba(255, 255, 255, 0.12);
  --flowbg: rgba(255, 255, 255, 0.02);
  --track: rgba(255, 255, 255, 0.10);
  --color-text: #e9e9ed;
  --color-accent: #9184d9;
  --color-accent-300: #a79bea;
  --color-accent-200: rgba(145, 132, 217, 0.18);
  --color-accent-800: rgba(145, 132, 217, 0.34);
  --r: 0px;
  --r2: 2px;
  --page-gap: 20px;
  --kpi-size: 25px;
  --kpi-weight: 400;

  --chart-clicks: #9184d9;
  --chart-second: #8fd3b0;
  --chart-bots: #6c7080;
  --chart-grid: rgba(255, 255, 255, 0.07);
  --chart-axis: #75798c;

  /* --- lane W1 (estate2-costs) --- the Costs chart's three series.
   * Chosen with the dataviz validator rather than by eye (three hue families,
   * OKLCH lightness inside this mode's band, chroma above the grey floor, every
   * adjacent pair separated under deuteranopia and protanopia, and 3:1 against
   * this theme's own card ground). The chart NEVER puts two of them on one
   * scale -- spend, installs and revenue are three units in two currencies --
   * so these are three band colours, not three lines sharing an axis. */
  --chart-spend: #8f7fe0;
  --chart-installs: #2fa877;
  --chart-revenue: #bd7f1c;

  --row-hover: rgba(255, 255, 255, 0.045);
  --row-selected: var(--color-accent-200);
  --row-stripe: rgba(255, 255, 255, 0.022);
}

/* --- Theme B: Console ----------------------------------------------------
 * Monospace everywhere, zero radius on everything, hard 1px grid, green
 * phosphor accent, lowercase h1.
 */
.th-console {
  color-scheme: dark;
  --font-body: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --font-heading: var(--font-body);
  --color-bg: #0e1013;
  --panel: #0a0c0f;
  --bar: #0e1013;
  --color-surface: #12151a;
  --color-neutral-300: #c2ccd4;
  --color-neutral-400: #8b98a3;
  --color-neutral-500: #74838f;
  --color-neutral-600: #5f6d78;
  --color-neutral-700: #3a444d;
  --color-neutral-800: #242b32;
  --color-neutral-900: #1b2127;
  --line2: #1b2128;
  --vline: #171c22;
  --head: #161b21;
  --sub: #11151a;
  --hair: #242b32;
  --pop: #12161c;
  --fibg: #10141a;
  --filine: #242b32;
  --flowbg: #10141a;
  --track: #1b2127;
  --color-text: #d7e0e6;
  --color-accent: #8fd3b0;
  --color-accent-300: #a9e2c4;
  /* A TINT over a dark ground, not the pale mint that used to sit here.
   * --color-accent-200 is a background in three rules -- .nav-item.on, .chip
   * and .ctl.on -- and #d3f0e2 is a light-theme value: against this theme's own
   * --color-text it measured 1.1:1, so the active nav item was a white block
   * with invisible text. The value below is the tint the theme already names
   * one line down in --row-selected. */
  --color-accent-200: rgba(143, 211, 176, 0.16);
  --color-accent-800: #1d3b2e;
  --r: 0px;
  --r2: 0px;
  --page-gap: 11px;
  --kpi-size: 19px;
  --kpi-weight: 500;

  --chart-clicks: #8fd3b0;
  --chart-second: #cbb98a;
  --chart-bots: #5d6b74;
  --chart-grid: #1b2128;
  --chart-axis: #5f6d78;

  /* --- lane W1 (estate2-costs) --- the Costs chart's three series.
   * Chosen with the dataviz validator rather than by eye (three hue families,
   * OKLCH lightness inside this mode's band, chroma above the grey floor, every
   * adjacent pair separated under deuteranopia and protanopia, and 3:1 against
   * this theme's own card ground). The chart NEVER puts two of them on one
   * scale -- spend, installs and revenue are three units in two currencies --
   * so these are three band colours, not three lines sharing an axis. */
  --chart-spend: #2fa877;
  --chart-installs: #6478d4;
  --chart-revenue: #bd7f1c;

  --row-hover: rgba(255, 255, 255, 0.045);
  --row-selected: rgba(143, 211, 176, 0.16);
  --row-stripe: rgba(255, 255, 255, 0.022);
}

.th-console h1 {
  text-transform: lowercase;
}

/* --- Theme C: Daylight ---------------------------------------------------
 * Warm paper ground, ink text, flat 4px panels, deep indigo accent, outlined
 * pills retained. The semantic trio is re-tuned for a light ground.
 */
.th-day {
  color-scheme: light;
  --color-bg: #eceae4;
  --panel: #e5e2da;
  --bar: #f7f6f2;
  --color-surface: #fbfaf7;
  --color-neutral-300: #383b43;
  --color-neutral-400: #4d5058;
  --color-neutral-500: #63666e;
  --color-neutral-600: #7c7f87;
  --color-neutral-700: #9b9da4;
  --color-neutral-800: #d8d5cd;
  --color-neutral-900: #dedad2;
  --line2: #e7e4dc;
  --vline: #eeebe4;
  --head: #f0eee8;
  --sub: #f2f0ea;
  --hair: #d8d5cd;
  --pop: #ffffff;
  --fibg: #fdfcfa;
  --filine: #d8d5cd;
  --flowbg: #f4f2ed;
  --track: #ded9d0;
  --color-text: #1b1c21;
  --color-accent: #5347a8;
  --color-accent-300: #413794;
  --color-accent-200: #efedfa;
  --color-accent-800: #ddd8f4;
  --r: 4px;
  --r2: 4px;
  --page-gap: 11px;
  --kpi-size: 22px;
  --kpi-weight: 500;

  --ok: #2c7350;
  --warn: #8a6620;
  --bad: #a03f3c;

  --chart-clicks: #5347a8;
  --chart-second: #2c7350;
  --chart-bots: #9b9da4;
  --chart-grid: #e4e1d9;
  --chart-axis: #7c7f87;

  /* --- lane W1 (estate2-costs) --- the Costs chart's three series.
   * Chosen with the dataviz validator rather than by eye (three hue families,
   * OKLCH lightness inside this mode's band, chroma above the grey floor, every
   * adjacent pair separated under deuteranopia and protanopia, and 3:1 against
   * this theme's own card ground). The chart NEVER puts two of them on one
   * scale -- spend, installs and revenue are three units in two currencies --
   * so these are three band colours, not three lines sharing an axis. */
  --chart-spend: #5b4fb5;
  --chart-installs: #00926f;
  --chart-revenue: #a5480d;

  --row-hover: rgba(88, 75, 176, 0.07);
  --row-selected: var(--color-accent-200);
  --row-stripe: rgba(0, 0, 0, 0.022);

  /* The one theme that has to re-point the scrollbar (v2fe lane W6). :root maps
   * the thumb onto --color-neutral-800, which on the three dark themes is a
   * lift off the ground and on this one is #d8d5cd -- a hairline border colour
   * one step from the #eceae4 paper, i.e. an invisible thumb. A light theme's
   * scrollbar has to go DARKER than its ground, so it moves two rungs up the
   * same ramp. Same ramp, same self-consistency rule, opposite direction. */
  --grid-scrollbar-thumb: var(--color-neutral-700);
  --grid-scrollbar-thumb-hover: var(--color-neutral-600);
}

/* --- Theme D: Nocturne ---------------------------------------------------
 * The 2026-08-07 design pack, transcribed. A true-black ground with near-black
 * surfaces; contrast comes from the neutral ramp, not from saturation. The
 * blurple accent is a line, a tint and a glow -- never a large flood. Colour is
 * spent sparingly on purpose: "ok" is neutral text rather than green, and a
 * single amber carries both warning and failure, because an all-green console
 * trains operators to ignore colour.
 *
 * Opt-in: THEMES lists it, the default stays `ledger`.
 *
 * EVERY colour token of the pack lives in this block. Nothing below may be
 * hoisted to :root, however "obviously dark" it looks -- th-day inherits :root.
 */
.th-nocturne {
  color-scheme: dark;

  /* -- ground and surfaces ---------------------------------------------- */
  --color-bg: #000000;      /* app ground, pane body */
  --color-surface: #0b0b0d; /* cards, KPI tiles, active pane tab */
  --panel: #000000;         /* sidebar, tab strip, status bar */
  --bar: #0a0a0c;           /* select background, rotation default card */
  --head: #0e0e12;          /* grid header, totals row */
  --sub: #08080a;           /* toolbar, rule card, flow card ground */
  --pop: #101014;           /* dialog, palette, toast, menu */
  --fibg: #0b0b0d;          /* input / chip fill */
  --track: #26262b;         /* progress + weight bar track */

  /* -- text and lines: the neutral ramp ---------------------------------- */
  --color-text: #f4f4f6;
  --color-neutral-200: #e7e7ea; /* toast text */
  --color-neutral-300: #c9c9cf; /* secondary text, nav section label */
  --color-neutral-400: #a3a3ab; /* control text, nav item */
  --color-neutral-500: #85858e; /* muted label, grid header text */
  --color-neutral-600: #6a6a73; /* placeholder, note text, icon rest */
  --color-neutral-700: #4e4e57; /* disabled text, empty state */
  --color-neutral-800: #26262b; /* control + card border */
  --color-neutral-900: #191920; /* chrome border (sidebar, bars) */
  --line-row: #181820;          /* horizontal row rule inside a grid */
  --line-cell: #141419;         /* vertical cell rule inside a grid */

  /* -- accent (Nocturne blurple) ----------------------------------------
   * Base #9184d9 sits at 3:1+ on the ground: fine for chrome, icons and large
   * text. Paragraph-size accent text uses --color-accent-300. */
  --color-accent: #9184d9;
  --color-accent-100: #f5f4ff;
  /* NOT tokens.css's opaque #e7e5fe. In THIS console --color-accent-200 is a
   * BACKGROUND -- .nav-item.on, .ctl.on and .chip read it -- so on a dark
   * ground the only correct shape for it is a translucent tint. The pack's own
   * value for the active nav item is --accent-tint-15, and that is what this
   * is, written out as a literal rather than as var(--accent-tint-15) because
   * the guard in dark-theme.test.js reads the DECLARATION, not the computed
   * value. th-console carries the scar that made the guard necessary. */
  --color-accent-200: rgba(145, 132, 217, 0.15);
  --color-accent-300: #d2cefd;
  --color-accent-400: #b5abfc;
  --color-accent-500: #968ae0;
  --color-accent-600: #796cbf;
  --color-accent-700: #5d5294;
  --color-accent-800: #423a6a;
  --color-accent-900: #2b2741;

  /* Pre-mixed accent tints, so nothing downstream re-derives them. */
  --accent-tint-04: rgba(145, 132, 217, 0.04);
  --accent-tint-09: rgba(145, 132, 217, 0.09); /* grid row hover */
  --accent-tint-10: rgba(145, 132, 217, 0.10); /* select hover */
  --accent-tint-12: rgba(145, 132, 217, 0.12); /* control .on background */
  --accent-tint-14: rgba(145, 132, 217, 0.14); /* button hover, rail active */
  --accent-tint-15: rgba(145, 132, 217, 0.15); /* nav item active */
  --accent-tint-16: rgba(145, 132, 217, 0.16); /* grid row selected */
  --accent-tint-18: rgba(145, 132, 217, 0.18); /* value chip, palette hit */
  --accent-tint-32: rgba(145, 132, 217, 0.32); /* ::selection */
  --accent-line-35: rgba(145, 132, 217, 0.35); /* accent chip border */
  --accent-line-40: rgba(145, 132, 217, 0.40); /* toast border, chip border */
  --accent-line-55: rgba(145, 132, 217, 0.55); /* control .on border */

  /* Neutral overlays -- hover states that must not read as accent. */
  --overlay-03: rgba(255, 255, 255, 0.03); /* zebra stripe */
  --overlay-04: rgba(255, 255, 255, 0.04); /* nav section hover */
  --overlay-05: rgba(255, 255, 255, 0.05); /* nav item hover */
  --overlay-06: rgba(255, 255, 255, 0.06); /* neutral pill fill */
  --overlay-09: rgba(255, 255, 255, 0.09); /* neutral pill border */

  /* -- semantic tone -----------------------------------------------------
   * If dead has to differ from degraded, change --tone-bad and nothing else
   * depends on it. */
  --tone-ok: #c9c9cf;    /* healthy, allow, sent, positive */
  --tone-warn: #d9a441;  /* fallback, retry, pending, degraded */
  --tone-bad: #d9a441;   /* dead letter, rejected, negative */
  --tone-muted: #85858e; /* n/a, internal-only, not routed, idle */
  --tone-accent: var(--color-accent-300);

  --tone-ok-fill: transparent;
  --tone-warn-fill: rgba(217, 164, 65, 0.14);
  --tone-bad-fill: rgba(217, 164, 65, 0.14);
  --tone-warn-line: rgba(217, 164, 65, 0.30);
  --tone-bad-line: rgba(217, 164, 65, 0.30);
  --tone-warn-note: rgba(217, 164, 65, 0.09); /* inline banner ground */
  --tone-info-note: rgba(145, 132, 217, 0.09);

  /* Profit reads in plain text, loss in the amber. Deliberately not red/green. */
  --money-pos: var(--tone-ok);
  --money-neg: var(--tone-bad);

  /* -- composite borders and shadows -------------------------------------
   * Colour-bearing, so they belong here and not on :root. On a dark ground
   * elevation is an edge plus ambient darkness; never stack the shadows. */
  --border-chrome: 1px solid var(--color-neutral-900);
  --border-control: 1px solid var(--color-neutral-800);
  --border-row: 1px solid var(--line-row);
  --border-cell: 1px solid var(--line-cell);
  --border-strong: 1px solid var(--color-neutral-700);
  --border-accent: 1px solid var(--color-accent);
  --border-dashed: 1px dashed var(--color-neutral-800);
  --border-drop: 1.5px dashed var(--color-accent);

  --shadow-none: none;
  --shadow-sm: 0 0 0 1px var(--color-neutral-800);
  --shadow-md: 0 16px 36px rgba(0, 0, 0, 0.50);
  --shadow-lg: 0 30px 64px rgba(0, 0, 0, 0.60);
  --scrim: rgba(10, 11, 18, 0.55);

  /* -- legacy aliases ----------------------------------------------------
   * The names app.css and the screen modules already read. tokens.css does not
   * declare them; without these the live stylesheet would resolve them to
   * nothing under this theme and the console would render half-unstyled. Each
   * one points at the design token that plays its role. */
  --r: var(--radius-lg);
  --r2: var(--radius-md);
  --ok: var(--tone-ok);
  --warn: var(--tone-warn);
  --bad: var(--tone-bad);
  --line2: var(--line-row);
  --vline: var(--line-cell);
  --hair: var(--color-neutral-800);
  --filine: var(--color-neutral-800);
  --flowbg: var(--sub);
  --page-gap: var(--space-9);
  --kpi-size: var(--fs-figure);
  --kpi-weight: var(--fw-medium);
  --row-hover: var(--accent-tint-09);
  --row-selected: var(--accent-tint-16);
  --row-stripe: var(--overlay-03);

  /* -- the --chart-* family ----------------------------------------------
   * tokens.css OMITS these outright -- a defect by the pack's own §5 rule, and
   * one that paints nothing and warns nobody. The values are read off the
   * pack's own chart rules in assets/console.css:508-513: the clicks line is
   * the accent, the second series is --tone-ok (this theme does not spend a
   * green on it), bots are the disabled neutral, the gridlines are the control
   * border and the axis labels the note neutral. */
  --chart-clicks: var(--color-accent);
  --chart-second: var(--tone-ok);
  --chart-bots: var(--color-neutral-700);
  --chart-grid: var(--color-neutral-800);
  --chart-axis: var(--color-neutral-600);

  /* --- lane W1 (estate2-costs) --- the Costs chart, through THIS theme's own
   * tokens rather than three literals, exactly as the family above it does.
   * Nocturne is deliberately two-hue -- blurple and amber over a neutral ramp,
   * with no green anywhere -- so the installs band takes --tone-ok, which here
   * IS the pale neutral. The dataviz validator marks that neutral below its
   * chroma floor and it is kept anyway: the chart carries identity by BAND,
   * with a direct label inside each band and a legend above them, so no series
   * is told apart by colour alone. Separation between the three still passes. */
  --chart-spend: var(--color-accent);
  --chart-installs: var(--tone-ok);
  --chart-revenue: var(--tone-warn);

  /* -- grid re-points ----------------------------------------------------
   * The --grid-* names live on :root and resolve, for the other three themes,
   * to exactly what the grid resolved to before. These are the members where
   * the design asks for something else. Heights are NOT here: the vendored
   * grid takes them as JS row options, and grids.js now serves the design's
   * 27/23/26 to every theme. */
  --grid-border: var(--color-neutral-800);
  --grid-totals-bg: var(--head);
  --grid-cell-padding-x: var(--space-5);
  --grid-font-size: var(--fs-base);
  --grid-header-font-size: var(--fs-micro);
}
