/* Design tokens — the Modern Fintech design system.
 *
 * Layered on top of the existing :root custom-property mechanism: this file owns
 * COLORS plus the non-color design primitives (radius, shadow, spacing, typography).
 * components.css + app.css consume these vars.
 *
 * One-key palette, light + dark twins (2026-09-11, docs/plans/2026-09-11-light-palettes.md): ONE
 * pick skins BOTH modes. A `dark-<key>` class on <html> re-colours dark mode, a `light-<key>`
 * class re-colours light mode, and shell.js adds/removes them together from the SAME stored key
 * (`localStorage.darkpalette` — the name is unchanged, test-guarded). CSS decides which half is
 * live purely by the presence of `.dark` on <html>. Classic is the no-class default in both
 * modes. This is not a return of the old `theme-<name>` axis (Ocean/Teal/Mono/Warm/Contrast/
 * Violet/Forest, removed 2026-09-04) — it's a light twin for each existing dark palette, picked
 * by the same one control.
 *
 * Liquid Glass (2026-09-11, docs/plans/2026-09-11-liquid-glass.md): every palette's `--bg`/
 * `--panel` were renamed to `--bg-solid`/`--panel-solid` (opaque ground truth), and each
 * palette's old hardcoded `--bd`/`--bd2`/`--hover` hex were REMOVED (not just renamed) — those
 * three are now derived ONCE from `--fg` in the "Liquid Glass tokens" section at the bottom of
 * this file, and `--bg`/`--panel` are derived from `--bg-solid`/`--panel-solid` there too. This
 * is a deliberate refinement of the plan's literal snippet: keeping the old hex in place would
 * out-specificity a same-selector `:root{}` derivation for every `.dark-<key>` block (`:is(:root.
 * dark,.dkprev).dark-x` has higher specificity than plain `:root`), so the derivation would
 * silently never apply to any dark palette. Removing the source hex leaves exactly one
 * definition site per property, so specificity can't fight it. */

:root,.ltprev{
  --on-media:#f4f6fa; /* text over dark image/hero bands (mode-independent) */
  /* --- non-color design primitives (shared by every palette) --- */
  --radius:14px;            /* cards */
  --radius-sm:10px;         /* buttons, inputs, small chips */
  --radius-pill:999px;      /* recent-ticker pills */
  --shadow:0 6px 24px rgba(0,0,0,.07);     /* soft card shadow */
  --shadow-sm:0 2px 8px rgba(0,0,0,.08);   /* dropdowns, toast */
  /* density 2026-09-18 (owner: "Use compact as default appearance. Remove normal/compact"): the
     former Compact mode's values ARE the appearance now -- there is no second density and no
     `:root.compact` class any more. This supersedes the 2026-09-11 ruling that made the denser
     set an opt-in mode. */
  --gap:.85rem;
  --pad-card:1rem;
  --font:14px/1.45 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  /* field-sizing plan (2026-09-04): the ONE input/select recipe lives on --field-* so the two
     can never drift apart again (addendum: "identical in height, padding, border, radius"). */
  --field-pad-y:.38rem; --field-pad-x:.5rem; --field-bd-w:1px;

  /* --- Classic (default) · light --- */
  color-scheme:light;
  /* fix round (pool-gaps, finding 11): #6b7280 measured 4.33:1 against --ground (#f2f2f7), under
     AA's 4.5:1 floor -- #5f6976 (same hue family, darkened) clears it with margin (4.99:1 vs
     ground, 5.57:1 vs --bg-solid/--panel-solid, both only ever getting SAFER as the surface
     lightens). The select chevron's own baked stroke colour (below) is kept in sync, same as the
     comment there already documents. */
  --bg-solid:#ffffff; --fg:#1a1d23; --muted:#5f6976; --panel-solid:#f6f7f9;
  --accent:#2962ff; --accent-fg:#ffffff; --link:#2962ff;
  --up:#0a8438; --down:#d12c2c;
  /* Empty-state illustrations (2026-10-16, lab 06): clay ramps (-0 highlight, -1 body, -2 shade) read by
     the shared radial gradients in core/static/js/empty-art.js; the dark block only deepens the shadow
     and adds a filter. --px-* is the pixel mascot's fixed 16-colour sprite palette (art, same in both modes). */
  --clay-blue-0:#c9dafe; --clay-blue-1:#8eaefc; --clay-blue-2:#5b80e6;
  --clay-peach-0:#ffe6d2; --clay-peach-1:#ffc39d; --clay-peach-2:#ec9a6c;
  --clay-mint-0:#dcf7e8; --clay-mint-1:#a3e2c2; --clay-mint-2:#6cc29c;
  --clay-lav-0:#efe6ff; --clay-lav-1:#c8b4f8; --clay-lav-2:#9c84df;
  --clay-cream-0:#fffdf6; --clay-cream-1:#f6ecda; --clay-cream-2:#e3d2b4;
  --clay-coral-0:#ffd0c6; --clay-coral-1:#ff9a88; --clay-coral-2:#e06855;
  --clay-orange-0:#ffdcae; --clay-orange-1:#ffb062; --clay-orange-2:#ea8433;
  --clay-grey-0:#ffffff; --clay-grey-1:#dfe2e8; --clay-grey-2:#aab0bc;
  --clay-glass:#e3ecff; --clay-white:#ffffff; --clay-black:#000000;
  --clay-edge:#e3d2b4; --clay-paper:#eadfca; --clay-metal:#9aa1b0; --clay-ink:#4a4a52;
  --clay-navy:#1f2f5c; --clay-blue-deep:#3e5fcc; --clay-brown:#b08c5a; --clay-plum:#5b4a8a;
  --clay-blush:#ff9fb0; --clay-green-ink:#0b4a30;
  --clay-shadow:rgba(30,40,70,.22); --clay-filter:none;
  --px-G:#2f7d4f; --px-g:#63c585; --px-k:#26392d; --px-m:#e2f6e5; --px-e:#1b2420; --px-c:#f3a3a3;
  --px-w:#ffffff; --px-p:#fff6e3; --px-s:#c5cad4; --px-S:#7d8798; --px-b:#a77b55; --px-B:#6b4b33;
  --px-y:#ffcc55; --px-o:#f2894a; --px-r:#e45b5b; --px-u:#9cc8ff;
  /* warning toast (amber) — palette-independent so alerts read as warnings in every theme */
  --toast-bg:#fff3cd; --toast-bd:#e0c060; --toast-fg:#5c4500;
  /* celebrate.js particle inks (gold / flame); palette-independent */
  --cele-gold:#b07800; --cele-flame:#f2601d; --cele-flame2:#ffb020;
  /* success toast (green) — palette-independent, same rationale as the warning toast above */
  --toast-ok-bg:#e3f6e9; --toast-ok-bd:#8fd6a8; --toast-ok-fg:#0f5c2c;
  /* chip STATUS tones (round 2, G1 leftover 2): five fixed, palette-INDEPENDENT bg/fg pairs for the
     `.chip--ok/--warn/--bad/--info/--muted` pool variants (components.css) -- same rationale as the
     toast pair above (a status colour that stays readable and recognisable regardless of which of
     the 8 named palettes is active), and the only workable one: a per-palette DERIVED tone (this
     leg tried `--up`/`--down`/`--accent` at their own palette hex first) has almost no AA headroom
     to begin with -- classic light `--up` (#0a8438) is only 4.80:1 against a white cell RAW, and
     even a light 4% tone-tinted background pushes it to 4.56:1 and a 6% tint already fails (WCAG
     sRGB contrast math, this file's own values) -- there is no tint percentage that stays safely
     >=4.5:1 across all 8 palettes' own `--up`/`--down`/`--accent` hexes at once. `--ok`/`--warn`
     reuse the EXISTING toast pair (already vetted, above); `--bad`/`--info`/`--muted` are new,
     chosen and verified the same way (>=5.4:1 light, >=6:1 dark, sRGB alpha-blend + WCAG relative-
     luminance math). This supersedes the tint-cut approach the --seg-track/--chip-fill comment
     documents just below (those two tokens are restored to the mock's own .13/.26 here, since the
     AA problem they were cut to solve is fully addressed by THESE fixed status pairs + `--fg`
     TEXT on unselected/plain chips and seg labels, verified separately: worst case 5.71:1 light,
     8.99:1 dark, both with wide margin). */
  --chip-bad-bg:#fde8e8; --chip-bad-fg:#9b1c1c;
  --chip-info-bg:#dbeafe; --chip-info-fg:#1d4ed8;
  --chip-muted-bg:#e8e8ec; --chip-muted-fg:#54575c;
  /* shared <select> chevron (field-sizing addendum): a mask-image ::after is not possible on
     <select>, so the SVG's stroke colour is baked per theme and swapped through this var instead
     of relying on currentColor inside a background-image (unreliable across engines). Stroke is
     --muted's light hex (#5f6976, fix round pool-gaps #11) so the affordance reads quiet next to
     the field's --fg text. */
  --select-chevron:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%235f6976' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  /* today-focus-widgets Leg E (2026-09-11): the queue's circle checkbox check mark -- same
     "baked stroke colour, swapped per theme" trick as --select-chevron above (a background-image
     data URI cannot read a CSS custom property), stroke = this theme's own --accent-fg. */
  --check-mark:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5 10.5l3 3 7-7' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
:root.dark,.dkprev{
  color-scheme:dark;
  --bg-solid:#15171c; --fg:#e6e8ec; --muted:#9aa3b2; --panel-solid:#1e2128;
  --accent:#5b8cff; --accent-fg:#0b0e14; --link:#5b8cff;
  --up:#3fb950; --down:#f85149;
  --clay-shadow:rgba(0,0,0,.55); --clay-filter:saturate(.88) brightness(.9);
  --shadow:0 6px 24px rgba(0,0,0,.4); --shadow-sm:0 2px 8px rgba(0,0,0,.5);
  --toast-bg:#3a2f12; --toast-bd:#7a6320; --toast-fg:#ffe08a;
  --cele-gold:#f0b429; --cele-flame:#ff7a33; --cele-flame2:#ffc145;
  --toast-ok-bg:#123a1f; --toast-ok-bd:#2f7a4d; --toast-ok-fg:#8affb0;
  /* chip STATUS tones, dark half -- see the light block's comment for the full rationale. */
  --chip-bad-bg:#3a1616; --chip-bad-fg:#ff8a8a;
  --chip-info-bg:#152a4a; --chip-info-fg:#93c5fd;
  --chip-muted-bg:#2c2e33; --chip-muted-fg:#a8adb5;
  /* one dark chevron for every dark palette below -- their --fg/--muted values all land in the
     same light-gray/white band, so a single stroke colour reads correctly on all seven without a
     per-palette redefinition. */
  --select-chevron:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%239aa3b2' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  /* one dark check mark for every dark palette below -- their --accent-fg values all land in the
     same near-black band (same "one dark value covers all seven" precedent as --select-chevron). */
  --check-mark:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5 10.5l3 3 7-7' fill='none' stroke='%230b0e14' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* ===== Dark palettes (owner ask 2026-09-04: "keep all" seven candidates from the dark-palette study,
   picked from a new Account-menu setting). The ONLY palette axis (Leg 1, 2026-09-04, removed the
   former light `theme-<name>` axis entirely): `dark-<key>` on <html> (persisted in localStorage
   `darkpalette`, owned by shell.js) re-colours dark mode. Classic dark = no class = the
   :root.dark block above. `.dkprev` is the in-app preview card: the same blocks paint a
   <div class="dkprev dark-<key>"> inside the picker dialog, so the preview and the real thing can
   never drift (one source of hex). */
:is(:root.dark,.dkprev).dark-graphite{
  --bg-solid:#0f1115; --fg:#eceef2; --muted:#9ea6b3; --panel-solid:#191c22;
  --accent:#6f9dff; --accent-fg:#0a0d14; --link:#7ea8ff;
  --up:#3ddc84; --down:#ff6166;
}
:is(:root.dark,.dkprev).dark-midnight{
  --bg-solid:#0b1220; --fg:#e4ecf8; --muted:#93a4c0; --panel-solid:#121b2d;
  --accent:#7aa5ff; --accent-fg:#07101f; --link:#8db3ff;
  --up:#3dd6a3; --down:#ff6b7a;
}
:is(:root.dark,.dkprev).dark-ink{
  --bg-solid:#08090b; --fg:#f3f4f6; --muted:#a3a8b3; --panel-solid:#141518;
  --accent:#8db4ff; --accent-fg:#06080d; --link:#9abdff;
  --up:#4ade80; --down:#f87171;
}
:is(:root.dark,.dkprev).dark-slate{
  --bg-solid:#0f172a; --fg:#e2e8f0; --muted:#94a3b8; --panel-solid:#1e293b;
  --accent:#60a5fa; --accent-fg:#0b1220; --link:#7cb4fb;
  --up:#34d399; --down:#fb7185;
}
:is(:root.dark,.dkprev).dark-mocha{
  --bg-solid:#181825; --fg:#cdd6f4; --muted:#a6adc8; --panel-solid:#1e1e2e;
  --accent:#89b4fa; --accent-fg:#11111b; --link:#89b4fa;
  --up:#a6e3a1; --down:#f38ba8;
}
:is(:root.dark,.dkprev).dark-nord{
  --bg-solid:#242933; --fg:#eceff4; --muted:#a9b3c6; --panel-solid:#2e3440;
  --accent:#88c0d0; --accent-fg:#1a2029; --link:#8fbcbb;
  --up:#a3be8c; --down:#e3909a;
}
:is(:root.dark,.dkprev).dark-ember{
  --bg-solid:#131110; --fg:#f1ebe4; --muted:#aaa093; --panel-solid:#1c1917;
  --accent:#e9a466; --accent-fg:#1a120b; --link:#f0b077;
  --up:#5ccb86; --down:#ff7264;
}

/* ===== Light palette twins (2026-09-11, docs/plans/2026-09-11-light-palettes.md): one pick skins
   BOTH modes now -- each dark-<key> block above has a light-<key> twin here, applied via
   `:is(:root:not(.dark),.ltprev).light-<key>` (specificity 0,3,0, beats the plain :root{}
   definitions of --ground/--cell-solid/etc. further down the file regardless of source order).
   `.ltprev` is the light half of a Settings preview card. Roles: ground=--ground, bg=--bg-solid,
   panel=--panel-solid, cell=--cell-solid. Every value is AA-tuned (>=4.5:1) against its own
   ground/bg/panel/cell -- see the dev-log contrast table. */
:is(:root:not(.dark),.ltprev).light-graphite{
  --ground:#ececef; --bg-solid:#ffffff; --panel-solid:#f3f3f5; --cell-solid:#ffffff;
  --fg:#16181d; --muted:#666b75;
  --accent:#3d5bd9; --accent-fg:#ffffff; --link:#3d5bd9;
  /* --up darkened from the plan's #0e843f (4.06:1 vs --ground) to clear 4.5:1 AA -- contrast
     verification, docs/plans/2026-09-11-light-palettes.md */
  --up:#0d7b3b; --down:#c92a2a;
}
:is(:root:not(.dark),.ltprev).light-midnight{
  --ground:#edf1f8; --bg-solid:#ffffff; --panel-solid:#f3f6fb; --cell-solid:#ffffff;
  --fg:#101a33; --muted:#5f6d8a;
  --accent:#2457d6; --accent-fg:#ffffff; --link:#2457d6;
  /* --up/--down darkened from the plan's #0d8463/#d0364f (4.12:1/4.29:1 vs --ground) to clear
     4.5:1 AA -- contrast verification */
  --up:#0c7d5e; --down:#ca344d;
}
:is(:root:not(.dark),.ltprev).light-ink{
  --ground:#f4f4f5; --bg-solid:#ffffff; --panel-solid:#f1f1f3; --cell-solid:#ffffff;
  --fg:#0a0b0e; --muted:#565b66;
  --accent:#1d4ed8; --accent-fg:#ffffff; --link:#1d4ed8;
  --up:#067a35; --down:#b91c1c;
}
:is(:root:not(.dark),.ltprev).light-slate{
  --ground:#f1f5f9; --bg-solid:#ffffff; --panel-solid:#f8fafc; --cell-solid:#ffffff;
  --fg:#0f172a;
  /* --muted/--up/--down darkened from the plan's #64748b/#05845d/#e11d48 (4.34:1/4.29:1/4.29:1
     vs --ground) to clear 4.5:1 AA -- contrast verification */
  --muted:#617187;
  --accent:#2563eb; --accent-fg:#ffffff; --link:#2563eb;
  --up:#05805a; --down:#da1c46;
}
:is(:root:not(.dark),.ltprev).light-mocha{
  --ground:#e6e9ef; --bg-solid:#eff1f5; --panel-solid:#e6e9ef; --cell-solid:#f4f5f9;
  --fg:#4c4f69;
  /* --muted/--accent/--link/--up/--down darkened from the plan's #686b80/#1d62eb/#1d62eb/
     #317921/#d20f39 (4.31:1/4.32:1/4.32:1/4.44:1/4.46:1 vs --ground) to clear 4.5:1 AA --
     contrast verification */
  --muted:#65687c;
  --accent:#1c5fe4; --accent-fg:#ffffff; --link:#1c5fe4;
  --up:#307720; --down:#d00f38;
}
:is(:root:not(.dark),.ltprev).light-nord{
  --ground:#e5e9f0; --bg-solid:#eceff4; --panel-solid:#e5e9f0; --cell-solid:#f2f4f8;
  --fg:#2e3440; --muted:#4c566a;
  /* --accent/--link/--up darkened from the plan's #4c6c98/#4c6c98/#4d7532 (4.42:1/4.42:1/4.41:1
     vs --ground) to clear 4.5:1 AA -- contrast verification */
  --accent:#4a6a95; --accent-fg:#ffffff; --link:#4a6a95;
  --up:#4b7331; --down:#b3404b;
}
:is(:root:not(.dark),.ltprev).light-ember{
  --ground:#f3eee6; --bg-solid:#fffdf9; --panel-solid:#f6f1ea; --cell-solid:#fffdf9;
  --fg:#241c15;
  /* --muted/--accent/--up/--down darkened from the plan's #7a6e63/#b5561c/#297f51/#d23c2c
     (4.29:1/4.22:1/4.28:1/4.11:1 vs --ground) to clear 4.5:1 AA -- contrast verification;
     --link (#a84e18) already cleared 4.5:1, unchanged */
  --muted:#756a5f;
  --accent:#ac521b; --accent-fg:#ffffff; --link:#a84e18;
  --up:#287b4f; --down:#c53829;
}

/* ===== Design language v2 (leg 6, ADR 0004) — additive; palettes above untouched ===== */
:root,.ltprev{
  --fs-hero:clamp(1.6rem,3.5vw,2.3rem); --fs-display:1.3rem; --fs-title:1.05rem;
  /* phone shell A leg 2 (2026-10-23): the phone page title (iOS large title, 34px) + its tight tracking; phone header only (shell.css) */
  --fs-large-title:2.125rem; --ls-tight:-.02em;
  --font-serif:ui-serif,"New York",Georgia,"Times New Roman",serif;   /* phone diary titles (Journal); a system serif, no webfont */
  /* round 7 E1 (2026-09-19, docs/plans/2026-09-19-todo-owner-edits-round7.md): a step between
     --fs-body (15px) and --fs-caption (.78rem/12.5px) that a plain 14px page-base step down would
     have landed ON — To-Do's entry-row/My-Lists titles use this, not a literal size. */
  --fs-body:15px; --fs-small:.8125rem; --fs-caption:.78rem; --fs-micro:.7rem; --lh-tight:1.25; --lh-normal:1.5; --fw-strong:650;
  --sp-1:4px; --sp-2:8px; --sp-3:10px; --sp-4:14px; --sp-5:20px; --sp-6:28px; --sp-7:36px; --sp-8:44px;
  /* shell-coexistence 2026-09-18: the ONE inset between the sticky shell bar and a page's own
     first element (module title, list column, context line), so every module's first heading lands
     on the same y. Derives from --sp-4 (14px since the density collapse, 2026-09-18). */
  --page-gap-top:var(--sp-4);
  /* single-column module page widths (module-ui-review Leg C, docs/plans/2026-09-04-module-ui-
     review.md): list pages (journal/inventory/orders) vs form/reading pages (mail/requests/
     settings/lifeos app pages/ask) — was 680-820px each, wasted inside a ~1260px content area. */
  --page-list:72rem; --page-read:60rem;
  --ease:cubic-bezier(.22,1,.36,1); --dur-fast:120ms; --dur:240ms; --dur-slow:420ms;
  --shadow-1:0 1px 3px rgba(0,0,0,.06),0 2px 8px rgba(0,0,0,.06);
  --shadow-2:0 4px 12px rgba(0,0,0,.08),0 12px 32px rgba(0,0,0,.10);
}
:root.dark,.dkprev{
  --shadow-1:0 1px 3px rgba(0,0,0,.35),0 2px 8px rgba(0,0,0,.35);
  --shadow-2:0 4px 12px rgba(0,0,0,.45),0 12px 32px rgba(0,0,0,.50);
}

/* ===== Calendar Leg 1 (docs/plans/2026-09-03-calendar.md §6.1): "calendars" source colours,
   palette-independent like the toast colours above -- every palette/dark-mode combination reads
   correctly without a second set of per-palette rules, because calendar.css only ever consumes
   these through color-mix() (fill) / var() (border, dot, text stays var(--fg)). --cal-event
   deliberately ALIASES --accent (own-calendar rows use the current palette's accent, not a fixed
   hue) so it re-themes with every palette for free; the other five are fixed hues shared by every
   palette, redefined once for dark mode. ===== */
:root,.ltprev{
  /* --cal-bill deliberately avoids the old warm-palette accent/link hex, removed platform-wide
     for failing AA contrast (leg 6 s10) and hard-gated to zero occurrences in this file by
     test_leg6_s10_a11y_wired; #b3550b is the same amber hue at a contrast ratio that passes. */
  --cal-event:var(--accent); --cal-todo:#0b8a4c; --cal-bill:#b3550b; --cal-order:#7c3aed;
  --cal-games:#0e7490; --cal-other:#6b7280;
  /* routines/projects (2026-10-02, D24): the ONE new source hue, a rose no other --cal-* uses
     (event accent blue, todo green, bill amber, order violet, games cyan, other grey). A SOURCE hue
     only (Today queue rail, calendar source) -- anything belonging to ONE project paints in that
     project's own list colour (--lc-*). Light #be185d is 5.1-6.0:1 on every light ground; the dark
     twin follows the lighter-tint pattern (>=4.72:1 on every dark palette ground). */
  --cal-project:#be185d; --cal-birthday:#4d7c0f;
  /* "soon / at risk" ink (a countdown under 24h, status-dot--warn): a yellow-gold apart from
     --cal-bill's orange; tuned to AA TEXT (light #8a6100 >=4.56:1 on every light ground, dark
     #eab308 >=6.5:1). --danger/--down stay for MISSED / late; this never means "late". */
  --warn-ink:#8a6100;
  /* item rarity 1-6 (Endfield database tile stripe): grey, green, blue, purple, gold, orange */
  --rar-1:#6b7280; --rar-2:#15803d; --rar-3:#1d4ed8; --rar-4:#7c3aed; --rar-5:#a16207; --rar-6:#c2410c;
  /* Endfield factory simulator canvas (efsim-draw.js reads these): ground, grid, area ring, in-game-style top view (same dark game palette in both themes)
     (dark metal frame + plate tinted by category), belt / pipe / item, port marks, source diamond, outlines */
  --es-ground:#161c27; --es-cell:#1f2837; --es-cell-strong:#2e3b52; --es-ring:#0c1017; --es-hatch:#1a2230; --es-edge:#e0b344;
  --es-frame:#0b0e14; --es-prod:#3d5a80; --es-logi:#55606e; --es-power:#b8892a; --es-depot:#2f7a68; --es-core:#a8573f;
  --es-belt:#2a3445; --es-chev:#cfe8ff; --es-pipe:#3aa0e0; --es-item:#ffd25a; --es-liquid:#7fd6ff; --es-port:#dfe6ee;
  --es-source:#f5a524; --es-warn:#ff5a4d; --es-sel:#8fd0ff; --es-ink:#e6ebf2; --es-ink-out:#8f9bb0;
  --es-in:#4aa8ff; --es-out:#ffb02e; --es-cyan:#3ee0ff;
  /* Blueprint view (efsim): deep blue paper, fine grid, category outlines, status dots */
  --es-bp-bg:#0d2438; --es-bp-grid:#15344f; --es-bp-grid2:#21496b; --es-bp-line:#d6ecff; --es-bp-bus:#3fc1a5;
  --es-bp-ok:#4be08a; --es-bp-idle:#8aa0b8; --es-bp-bad:#ff5a4d; --es-bp-pow:#ffc23d;
  --es-bp-prod:#5ab4ff; --es-bp-logi:#a9b8cc; --es-bp-power:#ffc23d; --es-bp-depot:#3fc1a5; --es-bp-core:#ff8a5c;
}
:root.dark,.dkprev{
  --cal-todo:#3ddc84; --cal-bill:#f5a524; --cal-order:#b295f8; --cal-games:#22d3ee;
  --cal-other:#9aa3b2; --cal-project:#f472b6; --cal-birthday:#a3e635; --warn-ink:#eab308;
  --rar-1:#9aa3b2; --rar-2:#4ade80; --rar-3:#60a5fa; --rar-4:#b295f8; --rar-5:#facc15; --rar-6:#fb923c;
  --es-ground:#161c27; --es-cell:#1f2837; --es-cell-strong:#2e3b52; --es-ring:#0c1017; --es-hatch:#1a2230; --es-edge:#e0b344;
  --es-frame:#0b0e14; --es-prod:#3d5a80; --es-logi:#55606e; --es-power:#b8892a; --es-depot:#2f7a68; --es-core:#a8573f;
  --es-belt:#2a3445; --es-chev:#cfe8ff; --es-pipe:#3aa0e0; --es-item:#ffd25a; --es-liquid:#7fd6ff; --es-port:#dfe6ee;
  --es-source:#f5a524; --es-warn:#ff5a4d; --es-sel:#8fd0ff; --es-ink:#e6ebf2; --es-ink-out:#8f9bb0;
  --es-in:#4aa8ff; --es-out:#ffb02e; --es-cyan:#3ee0ff;
  /* Blueprint view (efsim): deep blue paper, fine grid, category outlines, status dots */
  --es-bp-bg:#0d2438; --es-bp-grid:#15344f; --es-bp-grid2:#21496b; --es-bp-line:#d6ecff; --es-bp-bus:#3fc1a5;
  --es-bp-ok:#4be08a; --es-bp-idle:#8aa0b8; --es-bp-bad:#ff5a4d; --es-bp-pow:#ffc23d;
  --es-bp-prod:#5ab4ff; --es-bp-logi:#a9b8cc; --es-bp-power:#ffc23d; --es-bp-depot:#3fc1a5; --es-bp-core:#ff8a5c;
}

:root,.dkprev,.ltprev{
  /* list colour palette (moved from todo.css 2026-10-02; Apple's fixed system palette -- the same value in
     light and dark, a list/project's own identity colour, never a theme colour) */
  --lc-red:#ff3b30; --lc-orange:#ff9500; --lc-yellow:#ffcc00; --lc-green:#34c759;
  --lc-mint:#00c7be; --lc-teal:#30b0c7; --lc-cyan:#32ade6; --lc-blue:#007aff;
  --lc-indigo:#5856d6; --lc-purple:#af52de; --lc-pink:#ff2d55; --lc-brown:#a2845e;
  --lc-grey:#8e8e93;
}

/* ===== Liquid Glass tokens (2026-09-11, docs/plans/2026-09-11-liquid-glass.md §1-2) =====
   ONE derivation of --bg/--panel/--hover/--bd/--bd2 from --bg-solid/--panel-solid/--fg follows
   every palette (light + classic dark + all seven dark-<key> blocks + .dkprev), because each of
   those five properties now has exactly one definition site (the old per-palette hex for bd/bd2/
   hover was removed above, not just renamed — see the file-header note). */
:root,.dkprev,.ltprev{
  --bg:    color-mix(in srgb, var(--bg-solid) 62%, transparent);
  --panel: color-mix(in srgb, var(--panel-solid) 70%, transparent);
  --hover: color-mix(in srgb, var(--fg) 6%, transparent);
  /* re-glass 2026-09-18 (docs/plans/2026-09-18-reglass.md): the glass press (rim/lens brighten via
     filter:brightness(1.06) saturate(1.05), glass.css) is back, so button/.btn no longer reaches
     for this flat fill step on :active/.pressed -- left defined, unused by the button press, for
     any future plain-opaque control (e.g. a non-glass surface) that wants a one-level press tint. */
  --press: color-mix(in srgb, var(--fg) 12%, transparent);
  --bd:    color-mix(in srgb, var(--fg) 12%, transparent);
  --bd2:   color-mix(in srgb, var(--fg) 7%, transparent);
  /* journal-redesign (2026-09-18): the ONE add-entry ghost/placeholder recipe's dashed border --
     one step darker than --bd so the dashed rectangle stays legibly a placeholder against every
     palette + both themes (components.css's .ghost-box). */
  --ghost-bd: color-mix(in srgb, var(--fg) 24%, transparent);
}

/* @property registrations: without these, getComputedStyle(...).getPropertyValue('--bg') returns
   the raw unresolved "color-mix(...)" string instead of a resolved rgba() — required because
   stocks' chartTheme() (modules/stocks/static/js/app.js) reads --fg/--bd2 through
   getPropertyValue. inherits:true because these are :root-level tokens every descendant expects
   to inherit like the plain hex they replace. initial-value is the Classic-light resting value so
   an element with no matching rule still gets a legal color instead of the guaranteed-invalid
   value a color-typed custom property has by default. */
@property --bg{ syntax:'<color>'; inherits:true; initial-value:#ffffff; }
@property --panel{ syntax:'<color>'; inherits:true; initial-value:#f6f7f9; }
@property --hover{ syntax:'<color>'; inherits:true; initial-value:#f0f2f5; }
@property --bd{ syntax:'<color>'; inherits:true; initial-value:#e3e6ea; }
@property --bd2{ syntax:'<color>'; inherits:true; initial-value:#eef0f3; }
/* Verifier round (LOW): the glass fills/tint read through getComputedStyle the same way --bg
   etc. do (e.g. glass.js's morph/segmented-thumb code) and need the same registration. */
@property --glass-fill{ syntax:'<color>'; inherits:true; initial-value:rgba(255,255,255,.60); }
@property --glass-fill-strong{ syntax:'<color>'; inherits:true; initial-value:rgba(255,255,255,.86); }
@property --glass-fill-soft{ syntax:'<color>'; inherits:true; initial-value:rgba(255,255,255,.70); }
@property --glass-tint{ syntax:'<color>'; inherits:true; initial-value:rgba(41,98,255,.14); }
/* Liquid Glass v2: the lens recipe's ring/glow are also read through getComputedStyle by the same
   glass.js callers (morph/segmented-thumb code) that already needed --glass-fill/--glass-tint
   registered; --cell-bd is the new opaque-content-cell hairline, same reasoning. */
@property --glass-ring{ syntax:'<color>'; inherits:true; initial-value:rgba(255,255,255,.55); }
@property --glass-lens{ syntax:'<color>'; inherits:true; initial-value:rgba(255,255,255,.45); }
@property --cell-bd{ syntax:'<color>'; inherits:true; initial-value:rgba(26,29,35,.10); }

:root,.dkprev,.ltprev{
  --radius:16px; --radius-sm:11px; --radius-lg:22px; --radius-xl:28px;   /* concentric ladder; the
     two inner steps are the former Compact values (density collapse 2026-09-18) */
  --radius-xs:4px;   /* mini-mark radius (heat cells, timeline bars/diamonds, rails): the ladder's
     --radius-sm is far too round for a 10-14px mark (routines/projects, 2026-10-02) */
  /* fix round (pool-gaps, finding 4): the `.cell--side` sidebar-panel radius (mock: "sidebars 20")
     sits one step off the ladder above (11/16/22/28) -- its own token rather than reusing
     --radius-lg (22, a step too far past the mock's own number). */
  --radius-side:20px;
  /* Liquid Glass v2 (2026-09-11, docs/plans/2026-09-11-liquid-glass-v2.md): glass is the FLOATING
     CHROME layer only (bars/rails/menus/sheets/floating buttons) -- content (cards/fields/tables)
     is opaque (see --cell-bd + the "Liquid Glass — light mode" cell tokens below), so --glass-fill
     no longer has to double as a content-cell fill. --glass-fill-soft stays for the still-glass
     "soft" affordances (buttons, #pfbar.sel, the custom select-alike pickers) that are chrome-ish
     but not blurred. (round 2, G1 leftover 17.5: `.bal-tb` dropped from this list -- stale, see
     glass.css's own button-rim group comment: the balance module's container renamed from
     `.bal-toolbar` to `.bal-tb` because this glass paint was matching a plain layout row, not a
     themed button group, and was removed from the actual selector there; this comment just never
     caught up.)
     Plain liquid-glass (2026-09-25, docs/plans/2026-09-25-plain-liquid-glass.md, P1): retuned from
     the approved mock -- no refraction, one directional rim (bright top-left / dim bottom-right)
     replaces the old lens/ring/shade stack for CHROME (glass.css's ONE `.glass` recipe); the
     control-layer recipes (buttons/pickers/capsules) this leg leaves untouched still read
     --glass-ring/--glass-lens/--glass-shade below. See DESIGN.md's Elevation & Depth ruling. */
  --glass-fill:        color-mix(in srgb, var(--bg-solid) 62%, transparent);   /* bars, rail, menus, tabbar, dock */
  --glass-fill-strong: color-mix(in srgb, var(--bg-solid) 86%, transparent);   /* menus, dialogs, sheets, toasts, popovers */
  --glass-fill-soft:   color-mix(in srgb, var(--bg-solid) 70%, transparent);   /* soft-glass affordances: buttons/pickers (no blur) */
  /* post-pass (2026-09-26, item F1): `.glass-panel--thick` -- a denser tint for a panel sitting
     over rich PHOTOGRAPHIC imagery (Map's Satellite base layer), where `--glass-fill`'s normal
     62% mix lets enough of a bright/dark real-world tile bleed through to fail AA for the text on
     top of it. Calibrated by real pixel sampling (Playwright + PIL, same method as the map post-
     pass's own AA fix): loaded /map with Satellite active, read the LIVE composited pixel next to
     the real rendered `.ctl-quiet--muted` Edit/Remove buttons plus `--link`/`--fg`, and scanned
     fill percentages until every text role cleared 4.5:1 against the worst sampled tile (a dark
     teal/green patch measured near the Saved-places section, PLUS a synthetic pure-black/white
     safety margin) -- `--link` was the actual bottleneck in both modes, not `--muted` (matching
     the map agent's own item-10 finding that `--link` measures worse than `--muted` there).
     98%/97% (not 100%) still leaves a hairline of true glass; anything lower measurably failed,
     verified against the panel's OWN true background (elementFromPoint-confirmed sample points,
     excluding a nested child like the "Find a place" `.composer` box, which carries its own
     SEPARATE, more-transparent `--c-fill` cell paint that isn't part of this fix). */
  --glass-fill-thick:  color-mix(in srgb, var(--bg-solid) 98%, transparent);
  /* selection = a FLAT accent tint, never mixed into the glass fill any more (v2 fault #2: the
     old --glass-tint recipe painted a second rim on top of an already-glass group -- glass never
     stacks on glass). Consumers drop their own box-shadow to none when applying this. */
  --glass-tint:        color-mix(in srgb, var(--accent) 14%, transparent);
  /* the CONTROL-layer lens recipe (v2 fault #5, unchanged by the 2026-09-25 pass -- P1 is chrome
     only, P2 owns the pool's button/field/chip recipes that still read these): a bright top rim, a
     1px inner ring, a soft inner glow, a soft bottom shade. */
  --glass-rim:  rgba(255,255,255,.96);      /* top specular */
  --glass-rim2: rgba(255,255,255,.5);       /* plain-glass (2026-09-25): the CHROME directional rim's dim bottom-right twin */
  --glass-rim-w: 1.5px;
  --glass-ring: rgba(255,255,255,.55);      /* 1px inner ring (control layer) */
  --glass-lens: rgba(255,255,255,.45);      /* inner glow (control layer) */
  --glass-lens-r: 18px;                     /* inner glow radius */
  --glass-shade: rgba(16,20,28,.05);        /* bottom lens shade (control layer) */
  --glass-edge:  rgba(20,23,28,.09);        /* outer hairline (replaces border) */
  --glass-blur:22px; --glass-blur-clear:12px; --glass-sat:170%;
  --glass-shadow:      0 1px 2px rgba(15,20,30,.05), 0 10px 30px rgba(15,20,30,.10);
  --glass-shadow-float:0 2px 6px rgba(0,0,0,.06), 0 18px 50px rgba(0,0,0,.16);
  /* plain liquid-glass (2026-09-25): THE chrome recipe's one box-shadow list -- directional rim +
     the outer hairline, composed once here and read by glass.css's `.glass` class. No inner
     ring/glow/shade layering on chrome -- that stays a control-layer (lens) idiom, see above. */
  --glass-lit: inset 1px 1.2px 0 0 var(--glass-rim), inset -1px -1.2px 0 0 var(--glass-rim2), 0 0 0 .5px var(--glass-edge);
  --scrim:rgba(15,17,20,.25);
  /* fix round 1 (pool, finding 20): the four literal rgba() colours glass.css's own file-header
     rule flagged itself as a hook ("tokens only... except the rgba() alpha values that are
     THEMSELVES defined in tokens.css") -- named here, mode-agnostic (both were already used
     identically in light and dark with no separate rule), shape offsets (the "0 1px 3px"/"0 2px
     6px" part of each box-shadow) stay inline as ordinary geometry, only the colour moves. */
  --glass-thumb-shadow: rgba(0,0,0,.12);       /* segmented-thumb pill's own drop shadow */
  --glass-spec-light: rgba(255,255,255,.35);   /* pointer specular highlight, rest + coarse */
  /* content-cell hairline (v2 fault #1): cards/fields/tables are opaque --cell-solid boxes with
     this ONE hairline, never the glass rim -- see the "Liquid Glass — light mode" section below
     for --cell/--cell-solid themselves. */
  --cell-bd: color-mix(in srgb, var(--fg) 10%, transparent);
  --ease-spring: cubic-bezier(.34,1.2,.64,1);   /* the morph + the press release */
  --ease-out: cubic-bezier(.16,1,.3,1);
  --dur-morph:360ms;
  /* glass press (owner 2026-09-11, "iOS liquid-glass button click animation -- current is just a
     shadow"): iOS 26 LIFTS a glass control on touch-down (a hair larger + brighter, the lens
     blooms from the finger) and lets it spring back on release. glass.css's press section reads
     these; the JS side (glass.js, .pressed) only guarantees a quick tap still shows it. */
  /* re-glass 2026-09-18: restored to 1.05 -- the shell-coexistence tamed value (1.02) paired with
     the flat --press fill step, which is gone again now that the glass lens/rim brighten is back. */
  --press-scale:1.05; --dur-press:90ms;
  --glass-rim-press: rgba(255,255,255,.95); --glass-lens-press: rgba(255,255,255,.72);
  --glass-fill-press: var(--glass-fill-strong);
  --glass-bloom: rgba(255,255,255,.45);      /* the ::after bloom disc on neutral glass */
  /* Phone chrome Leg A (2026-09-12, docs/plans/2026-09-12-phone-glass-lens.md, addendum "level 3
     Regular" table): the two phone bottom bars + the compact topbar read CLEARER than the desktop/
     menu --glass-fill -- the owner's "toolbar clearer to the content behind it" ruling. Plain
     liquid-glass (2026-09-25) leaves these values as-is: the survey flagged the mock's flat 62%
     everywhere as an open confirm-with-owner item, so this executor keeps the existing explicit
     phone-clearer ruling rather than overriding it unasked. --cap-fill/--cap-blur (capsule groups)
     land here too. */
  --bar-fill:  color-mix(in srgb, var(--bg-solid) 45%, transparent);
  --bar-blur:  16px;
  --cap-fill:  color-mix(in srgb, var(--bg-solid) 35%, transparent);
  --cap-blur:  14px;
  /* plain liquid-glass (2026-09-25): the segmented-thumb's own track/fill (glass.css's plain pill,
     replacing the droplet lens) + the shared chrome float geometry (inset + radius, shell.css).
     Fix round 1 (finding 11) CUT this from the mock's 13%/26% (dark below) to 4%/8% because --muted
     TEXT painted on this same grey (stocks' unselected tab labels, via --chip-fill just below onto
     .tagchip) fell as low as 3.92:1. Round 2 (G1 leftover 2) RESTORES the mock's own 13%/26% --
     the material was nearly invisible at 4% (see the round-1 recheck's evidence,
     vfinal/track/head-viewsw-1.png) -- and passes AA the mock's own way instead: unselected seg
     labels and plain chip text read `--fg`, not `--muted` (verified: --fg on this restored track
     is 5.71:1 light / 8.99:1 dark WORST CASE across all 8 palettes, wide margin -- `--muted` was
     the actual problem, not the tint strength). A STATUS-toned chip (`.chip--ok` etc, below in this
     same file) never mixes tone colour into this shared track at all -- seek that comment for why.
     fix round (pool-gaps-2, ORCHESTRATOR finding 26): the approved mock's Apple "systemFill" grey
     (named `--sys-fill` just below) was pasted as a bare colour literal 12 times across this file
     (4 as a baked-alpha translucent form for the always-glass track/chip below and in the dark
     block, 8 as an opaque `color-mix(...,var(--ground))` form for the Solid/reduced-transparency
     axis, each of those four duplicated once more since a class and a media query can't share one
     selector) instead of being named once; ditto the "no-blur field fill" `#fff`-into-`--ground`
     pair (also duplicated once for the same reason). Named here, referenced by every one of those
     twelve/four sites below -- one value to retune everywhere, and no literal left for a design-
     hook ignore-value to need scoping around. */
  --sys-fill: rgb(118 118 128);
  --field-fill-flat-light: color-mix(in srgb, #fff 78%, var(--ground));
  --field-fill-flat-dark: color-mix(in srgb, #fff 7%, var(--ground));
  --seg-track:      color-mix(in srgb, var(--sys-fill) 13%, transparent);
  --seg-thumb-fill: rgba(255,255,255,.94);
  --field-fill:     rgba(255,255,255,.78);
  --chrome-inset: var(--sp-3);
  --phonehead-h: calc(44px + env(safe-area-inset-top));   /* phone v2 leg 0b: the fixed compact header (#phonehead), safe-area included */
  /* the ONE header line (2026-10-16): every rail page's header row spans --head-top .. --head-top + --head-h, centred on the rail's first icon */
  --head-top: calc(var(--sp-3) + var(--sp-1));   /* the floating inset + 4, in Flush too (owner 2026-10-19 "header spacing": Flush had put the line 4px under the window top) */
  --head-h: 34px;
  --head-gap: 16px;   /* header row bottom -> first content box (the sp scale has no 16) */
  --radius-chrome: 24px;
  /* fix round 1 (2026-09-25, finding 1): the phone topbar draws as a full pill at rest (the mock's
     capsule shape), which a literal `--radius-pill` in shell.css can't ever un-round for Flush --
     a SECOND token, zeroed by chrome-flush right alongside --radius-chrome, keeps the phone bar
     tokens-only too. */
  --radius-chrome-phone: var(--radius-pill);
  /* Chrome layout: Floating | Flush (2026-09-25, owner ruling 5) -- the rail's own width is a
     token too (never a literal in shell.css) so BOTH layouts read it the same way; the :root.
     chrome-flush override two blocks down only ever touches --chrome-inset/--radius-chrome. */
  --rail-w: 12rem;   /* owner 2026-10-19: tried 10rem, "shown version previous one is better" */
  --rail-w-icons: 3rem;   /* slimmer 2026-10-19 (owner "siderail can be slimmer"; was 3.5rem) */   /* icon-only rail (owner 2026-10-01 "3 steps: full, icon-only, hide") */
  /* R3 A1 (2026-09-27, owner #6): #railtoggle (the rail's collapse toggle, now the canvas's 34px
     round `.ib`/`.lsopen` icon button) sits concentric with the rail's own rounded corner --
     --radius-chrome(24px) minus half the button's 34px = 7px. A flat literal, not a --radius-chrome
     calc(), because Flush zeroes --radius-chrome to 0 (a squared-off corner) while the SAME 7px
     inset still reads right there too -- one number for both layouts, per the plan. */
  --rail-toggle-inset: 7px;
  /* flat-buttons 2026-10-16: primary/dock tint is the literal 16/24/32% color-mix in glass.css -- the old
     --accent-rim/-ring/-shade/-edge/-glow, --accent-fill-pct/-up, --glass-btn-shadow, --accent-bloom tokens are gone. */
  /* plain liquid-glass P2 (2026-09-25, docs/plans/2026-09-25-plain-liquid-glass.md, docs/plans/
     …/survey/pool.full.json): the CONTENT-layer material the button/field/chip/card recipes in
     glass.css consume -- token-only, on purpose, so `.games-keep` (further down) can re-pin
     EXACTLY these names back to their pre-P2 values without touching a single selector (the games
     freeze's own hard rule: re-pin tokens on the content subtree, never restyle games markup).
     --c-fill/--c-shadow: the thin-glass "cell" a card/stat/composer now sits in (no blur, unlike
     chrome) -- directional inset rim (reusing --glass-rim2/--glass-edge, the SAME dim/edge chrome
     already computes) + a soft shadow, replacing the old opaque --cell-solid fill. --field-shadow/
     --field-min-h: a field's box goes from an OUTER 1px ring to an INSET hairline + a faint inner
     shadow (mock .field), with a 36px floor. --chip-fill/--chip-shadow: the chip/tag pill's own
     fill, reusing the segmented track's colour family but as its OWN token (never --seg-track
     itself, so a games-keep re-pin of one never touches the other's still-accepted seg-thumb
     change, see the games-keep block's comment). --switch-thumb-fill: P1 left the switch thumb
     reading `var(--bg)`, which renders a DARK thumb in dark mode (the mock's own bug list) -- one
     explicit white in both themes fixes it. */
  --c-fill: color-mix(in srgb, var(--cell-solid) 68%, transparent);
  --c-shadow: inset .8px 1px 0 0 var(--glass-rim2), 0 0 0 .5px var(--glass-edge), 0 1px 2px rgba(0,0,0,.04);
  --field-shadow: inset 0 0 0 .5px var(--bd), inset 0 1px 2px rgba(0,0,0,.03);
  --field-min-h: 2.25rem;
  /* round 2 (G1 leftover 2): restored to the mock's 13% -- same token, same reasoning, see
     --seg-track's own comment above (fix round 1's AA cut, and why round 2 undoes it, in full). */
  --chip-fill: color-mix(in srgb, var(--sys-fill) 13%, transparent);
  --chip-shadow: none;
  --switch-thumb-fill: #fff;
}
:root.dark,.dkprev{
  /* owner 2026-09-11 ("not good transparency. contents overlapping, hard to look"): dark menus /
     popovers sit on a near-black ground where any bright control behind them (a primary button)
     reads straight through the fill -- the strong fill stays well above the resting fill in dark
     so the blurred backdrop is a hint, never competing content. */
  /* plain liquid-glass (2026-09-25): folded into this SAME 4th dark block per the survey (never a
     5th) -- --glass-rim2/--seg-track/--seg-thumb-fill/--field-fill are new; the rest are retuned. */
  --glass-fill:        color-mix(in srgb, color-mix(in srgb, var(--panel-solid) 90%, #fff) 56%, transparent);
  --glass-fill-strong: color-mix(in srgb, var(--panel-solid) 88%, rgba(255,255,255,.05));
  /* post-pass (2026-09-26, item F1): dark half of --glass-fill-thick above -- deliberately NOT
     the same "panel-solid + a little white" lightening --glass-fill/-strong both use (measured:
     that lightening pushes --link's own dark hex, #5b8cff, under 4.5:1 against the tile even at
     100% opacity -- lightening a dark surface is exactly the wrong direction for light-on-dark
     contrast). Plain --panel-solid darkens toward it instead, which is what actually clears AA. */
  --glass-fill-thick: color-mix(in srgb, var(--panel-solid) 97%, transparent);
  /* light-mode plan (2026-09-11): dark keeps the pre-existing 42% (unchanged pixel-for-pixel) --
     see the base :root definition above for why light itself moved to 70%. */
  --glass-fill-soft: color-mix(in srgb, var(--bg-solid) 42%, transparent);
  --glass-rim: rgba(255,255,255,.30); --glass-rim2: rgba(255,255,255,.09);
  --glass-ring: rgba(255,255,255,.10); --glass-lens: rgba(255,255,255,.06);
  --glass-shade: rgba(0,0,0,.25); --glass-edge: rgba(0,0,0,.55); --glass-sat:160%;
  --glass-tint: color-mix(in srgb, var(--accent) 22%, transparent);
  --glass-rim-press: rgba(255,255,255,.5); --glass-lens-press: rgba(255,255,255,.16); --glass-bloom: rgba(255,255,255,.2);
  --scrim: rgba(0,0,0,.45);
  --glass-shadow:      0 1px 2px rgba(0,0,0,.35), 0 12px 34px rgba(0,0,0,.5);
  --glass-shadow-float:0 2px 6px rgba(0,0,0,.4), 0 18px 50px rgba(0,0,0,.6);
  /* round 2 (G1 leftover 2): dark half of the light --seg-track restoration above (mock's 26%). */
  --seg-track:      color-mix(in srgb, var(--sys-fill) 26%, transparent);
  --seg-thumb-fill: rgba(255,255,255,.18);
  --field-fill:     rgba(255,255,255,.07);
  /* light-mode plan (2026-09-11): --ground/--cell-solid folded into this SAME shared dark block
     (rather than two more standalone dark-selector openers) -- test_dark_palette_setting_wired
     guards the count of that exact block-opener string at 4, and dark stays pixel-identical
     either way (both values just mirror the light-mode roles onto dark's already-correct
     tokens). See the "Liquid Glass — light mode" section below for what these mean. */
  --ground:var(--bg-solid);
  --cell-solid:var(--panel-solid);
  /* Phone chrome Leg A: dark half of the level-3 fills above -- blur/pct tokens are unchanged
     between modes (declared once in the light block) so only the fill colours repeat here. */
  --bar-fill: color-mix(in srgb, var(--panel-solid) 50%, rgba(255,255,255,.05));
  --cap-fill: color-mix(in srgb, var(--panel-solid) 40%, rgba(255,255,255,.05));
  /* plain liquid-glass P2: dark half of --c-fill/--c-shadow/--chip-fill above (folded into this
     SAME shared dark block, never a 5th -- --field-shadow/--field-min-h/--switch-thumb-fill are
     mode-independent, declared once in the light block). */
  --c-fill: rgba(255,255,255,.055);
  --c-shadow: inset .8px 1px 0 0 var(--glass-rim2), 0 0 0 .5px var(--glass-edge), 0 1px 2px rgba(0,0,0,.25);
  /* round 2 (G1 leftover 2): dark half of the light --chip-fill restoration above (mock's 26%). */
  --chip-fill: color-mix(in srgb, var(--sys-fill) 26%, transparent);
}
@media (prefers-reduced-transparency: reduce){
  /* fix round 1 (finding 2): `color-mix(in srgb, var(--bg-solid) 96%, transparent)` measures as
   * 96% opaque in devtools/Playwright's bundled engine, but real WebKit (WebProbe, the owner's
   * actual Safari) composites it far more transparently than that -- a scrolled card's own text
   * (medium --muted grey, not even full black) stayed CRISPLY LEGIBLE straight through it, worse
   * than Glass's blurred version at the same scroll position, exactly backwards from "reduce
   * transparency"'s intent. Isolated the cause with a controlled A/B at the same scroll position:
   * a PLAIN `rgba(255,255,255,.96)` (no color-mix) on the same element shows only the faint,
   * near-invisible ghost 96% opacity actually predicts; the color-mixed value does not -- so this
   * is real WebKit's `color-mix(...,transparent)` interpolation, not a percentage picked too low.
   * These three tokens are the only "Solid/reduce-transparency" fills still built that way (every
   * sibling on this line -- --glass-fill-strong, --panel -- was already a PLAIN opaque value and
   * never showed the bug); dropping the color-mix entirely (this axis wants full opacity anyway,
   * "Solid = opaque fills" per this file's own header comment above) sidesteps the engine behaviour
   * rather than fighting it. Kept in sync with the :root.solid twin below by construction (a media
   * query and a class can't share one rule). */
    --glass-fill: var(--bg-solid);
    --glass-fill-strong: var(--bg-solid);
    --glass-fill-soft: var(--bg-solid);
    --bg: var(--bg-solid); --panel: var(--panel-solid);
    --bar-fill: var(--glass-fill-strong); --cap-fill: var(--glass-fill-strong);
    --seg-thumb-fill: var(--bg-solid); --glass-rim2: transparent;
    /* round 2 (G1, cleanup-list "Material Solid P2 token opacity"): this block only ever opacified
       the CHROME tokens (P1's own layer) -- the P2 pool tokens (cell/chip/track/field fills, all
       still `color-mix(...,transparent)`/low-alpha `rgba()`) stayed translucent regardless, so
       "reduce transparency" left every card/chip/segmented-track still see-through. --cell-solid/
       --panel-solid are this palette's own OPAQUE surfaces already (tokens.css, declared above),
       reused here rather than inventing new fixed hex. */
    --c-fill: var(--cell-solid);
    /* fix round 1 (pool, finding 8): --panel-solid is too close to --ground (#f6f7f9 vs #f2f2f7)
       and to a white --cell-solid alike -- a field/track/chip painted with it nearly vanishes on
       either surface, and the white --seg-thumb-fill pill merges into a track the same colour as
       itself. An OPAQUE flattening of the same glass tint (its own colour/alpha, pre-mixed onto
       --ground instead of layered translucently) keeps the same visual STRUCTURE the mock's glass
       version reads by, just without the transparency -- --seg-track/--chip-fill share one glass
       colour (rgba(118 118 128, .13) here; the .dark block below carries dark's .26), --field-fill
       is glass's own white-based tint (.78 here; dark's .07 below). */
    --field-fill: var(--field-fill-flat-light);
    --chip-fill: color-mix(in srgb, var(--sys-fill) 13%, var(--ground));
    --seg-track: color-mix(in srgb, var(--sys-fill) 13%, var(--ground)); }
  /* dark half of the fix above -- same reasoning, dark's own glass alpha (.26 track/chip, .07
     field, tokens.css's own dark glass block) pre-mixed onto dark's --ground instead of reusing
     --panel-solid, which in dark equals --cell-solid exactly (a field used to match the cell it
     sits on, invisible). */
  :root.dark{
    --field-fill: var(--field-fill-flat-dark);
    --chip-fill: color-mix(in srgb, var(--sys-fill) 26%, var(--ground));
    --seg-track: color-mix(in srgb, var(--sys-fill) 26%, var(--ground));
  }
}
@media (prefers-reduced-motion: reduce){
  :root{ --press-scale:1; }   /* press still brightens, never moves/stretches */
}
/* Material: Glass | Solid (2026-09-25, docs/plans/2026-09-25-plain-liquid-glass.md, Settings ->
   Appearance): a class-based twin of the prefers-reduced-transparency block above -- shell.js sets
   html.solid at first paint from localStorage.material so a user can turn the glass material off
   without depending on the OS-level media query (the two never need to diverge -- "solid" is just
   this account's own opt-in to the same opaque/no-blur fallback). */
/* fix round 1 (finding 2): --glass-fill/--glass-fill-soft/--bg dropped their `color-mix(...,
 * transparent)` mix for a plain opaque value -- see the prefers-reduced-transparency twin above
 * for the full real-WebKit diagnosis (its own alpha math doesn't hold in the owner's actual
 * Safari, so the topbar/rail stayed legible-through at any percentage short of dropping the mix
 * entirely; kept in sync with that block by construction, a class and a media query can't share
 * one rule). */
:root.solid{ --glass-blur:0px; --glass-blur-clear:0px; --glass-sat:100%;
  --glass-fill: var(--bg-solid);
  --glass-fill-strong: var(--bg-solid);
  --glass-fill-soft: var(--bg-solid);
  --bg: var(--bg-solid); --panel: var(--panel-solid);
  --bar-fill: var(--glass-fill-strong); --cap-fill: var(--glass-fill-strong);
  --seg-thumb-fill: var(--bg-solid); --glass-rim2: transparent;
  /* round 2 (G1, cleanup-list): same P2 content-layer gap as the prefers-reduced-transparency twin
     above -- cards/fields/chips/segmented-tracks stayed translucent under Solid, contradicting the
     setting's own "opaque, no blur" promise (Settings -> Appearance, this file's own header
     comment). Kept in sync with that block by construction, not by a shared selector (`:root.solid`
     and `@media(prefers-reduced-transparency)` can't share one rule), same as the six tokens above. */
  --c-fill: var(--cell-solid);
  /* fix round 1 (pool, finding 8): same fix as the prefers-reduced-transparency twin above, kept
     in sync with it by construction rather than a shared selector (a class and a media query can't
     share one rule) -- see that block's own comment for the full reasoning. */
  --field-fill: var(--field-fill-flat-light);
  --chip-fill: color-mix(in srgb, var(--sys-fill) 13%, var(--ground));
  --seg-track: color-mix(in srgb, var(--sys-fill) 13%, var(--ground));
}
:root.dark.solid{
  --field-fill: var(--field-fill-flat-dark);
  --chip-fill: color-mix(in srgb, var(--sys-fill) 26%, var(--ground));
  --seg-track: color-mix(in srgb, var(--sys-fill) 26%, var(--ground));
  /* fix round (pool-gaps-2, ORCHESTRATOR finding 29): `:root.solid`'s own `--seg-thumb-fill:
     var(--bg-solid)` is correct in LIGHT (white, unambiguously lighter than light's own grey-
     tinted track above) but was never re-overridden HERE for dark -- inherited unchanged, it
     stayed `--bg-solid` (dark's near-black opaque ground), painting a near-black selected thumb on
     a LIGHTER 26%-grey track and reading as a hole rather than a raised selection (the reverse of
     iOS/Glass-dark's own "selected reads lighter than its track" convention). An opaque mix of
     white into --bg-solid (not the track's own --sys-fill grey, so it never converges toward the
     track's own colour as either token is retuned) keeps the thumb reliably lighter regardless of
     exactly how light the track's own 26% mix lands. */
  --seg-thumb-fill: color-mix(in srgb, #fff 26%, var(--bg-solid));
}

/* Chrome layout: Floating | Flush (2026-09-25, docs/plans/2026-09-25-plain-liquid-glass.md, owner
   ruling 5, verbatim: "keep version that rail and navbar aren't floating, but the current as well,
   for optional appearance"). Default is Floating (no class, the tokens already declared above);
   `html.chrome-flush` (localStorage `chrome`, shell.js first paint, Settings -> Appearance "Layout")
   zeroes the float inset + corner radius -- TOKENS ONLY, so #shell/.rail-nav's own geometry rules
   (shell.css) never hardcode a second value of their own and every page reads correctly in both. */
:root.chrome-flush{ --chrome-inset:0px; --radius-chrome:0px; --radius-chrome-phone:0px; }

/* ===== Liquid Glass — light mode (2026-09-11, docs/plans/2026-09-11-liquid-glass-light.md) =====
   Diagnosis: light mode read flat because --bg-solid (pure white) was ALSO the page ground, so
   white glass sat on a white ground and the material was invisible. Apple's light Liquid Glass
   grounds on a light grey (systemGroupedBackground #f2f2f7); glass bars/cards are whiter than
   that ground with a specular rim + shadow, and content cells are white
   (secondarySystemGroupedBackground) with grey insets inside them (tertiarySystemGroupedBackground
   -- the same tone as the ground). --bg-solid stays #ffffff in light: it is still the opaque WHITE
   surface every --bg/glass fill derives from (glass must be whiter than the ground, the whole
   point) -- only the page GROUND moves to grey. Dark is untouched pixel-for-pixel: --ground is
   var(--bg-solid) there (folded into the shared :root.dark,.dkprev block above, next to the
   other liquid-glass dark overrides), exactly what body's background already was before this
   section existed. */
:root,.ltprev{ --ground:#ffffff; }   /* topbar-free shell (2026-10-01, owner: "can white be main background color instead?"): Classic light ground is white; cells/cards/rail keep a --bd hairline edge (components.css/shell.css pool recipes) */
/* The white ground means every cell/card/rail/glass surface needs a visible edge on it. One pool token,
   Classic light only (other light palettes keep their own tinted grounds + edges, dark is untouched):
   --glass-edge is the .5px outer hairline --glass-lit / --c-shadow / the rail, tiles, widgets, ledger
   cards and stats boxes all draw -- darkened here so they read as edged on #fff. */
:root:not(.dark):not([class*="light-"]){ --glass-edge:rgba(20,23,28,.2); }

/* games freeze (2026-09-25, plain-liquid-glass P2, fix round 1 finding 10): `--select-chevron`'s
   own re-pin lives HERE rather than glass.css's games-keep block (core/static/css/glass.css) --
   colocated with the four other --select-chevron/--check-mark definitions above, and, since this
   file sits outside core/ui_pool.py's `_CORE_CSS` scan list, its baked SVG's literal `w3.org`
   substring can't trip the "unregistered core class" guard the way it would inside glass.css
   (which had never contained that substring before). Light mode only -- dark's chevron stroke was
   never retuned for AA, so games-keep never needed a dark twin of this line either. --select-
   chevron itself never varies by NAMED palette (only by light/dark mode, see the two plain
   `--select-chevron` definitions above), so re-pinning it unconditionally across every light
   palette is correct as-is -- unlike `--muted` just below in glass.css's own games-keep block,
   which DOES need a Classic-only guard (round-2 G1 finding 6: the un-pinned per-palette --muted
   hex differs, so pinning it everywhere would repaint every OTHER light palette's games text with
   Classic's hex). Round 2 G1: content-root scope widened from `:is(main, #gp-shell)` (missed 9 of
   26 games pages whose content root is neither) to every non-chrome child of `.shell-page` (or, on
   planner.html, of `<body>` itself -- that page has no shell.js chrome at all, see glass.css's
   games-keep block for the full derivation) -- see that block's own header comment for the DOM
   walk this is built from. */
:root:not(.dark).games-keep .shell-page > :not(#shell,#usermenu,#dock,#dockback,#dockcapturepanel),
:root:not(.dark).games-keep body > :not(#rail,.rail-backdrop,.shell-page,#tabbar,.toast,#usermenu,#lsdlg,#reauthdlg,.dpick){
  --select-chevron:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%236b7280' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* games freeze: named FROZEN tokens (round 2 G1, cleanup-list.md "hook" items) -- the games-keep
   block in glass.css used to pin these as bare rgba()/hex literals directly in a selector's
   box-shadow/custom-property value, which this file's own header rule ("Tokens only — no literal
   px/ms/hex outside tokens.css") flags as a hook for a module leg to clean up. Named here instead,
   at their FROZEN (pre-P1/P2, "today's") values -- glass.css's games-keep block now reads these
   through var() rather than repeating the literal. `--keep-muted-light` is Classic light's OLD
   `--muted` hex (fix round pool-gaps #11 later retuned the platform's own `--muted` to #5f6976 for
   AA; games content keeps the original #6b7280 it always had). `--keep-glass-rim-*`/`--keep-glass-
   edge-*` are the pre-P1 button rim/outer-edge pair P1's own chrome retune changed the shared
   `--glass-rim`/`--glass-edge` tokens away from (`--glass-ring` is untouched pre/post-P1 in both
   modes, so that one stays token-driven with no frozen twin needed -- see glass.css's own comment
   on this same re-pin). */
:root{
  --keep-muted-light:#6b7280;
  /* fix round (pool-gaps-2, games freeze regression, planner's `#browse-btn.tab-btn`): the pre-P2
     literal weight `modules/games/static/css/app.css`'s own `.tab-btn` rule always carried --
     named here (not left a bare literal in glass.css) per this file's own "tokens only" rule. */
  --keep-tab-btn-weight:500;
  --keep-glass-rim-light:rgba(255,255,255,.95); --keep-glass-edge-light:rgba(16,20,28,.14);
  --keep-glass-rim-dark:rgba(255,255,255,.28); --keep-glass-edge-dark:rgba(0,0,0,.55);
  /* (2026-10-02 DE-GLASS: the `--keep-accent-*` / `--keep-glass-blur-clear` / `--keep-glass-sat-*` twins that
     froze `.primary`'s 09-18 glass recipe lived here -- gone with it; games' accent button is B's flat
     `background:var(--accent)` again, see glass.css's games-keep block.) */
  /* fix round 1 (pool, finding 18/E3): games-keep never re-pinned `--glass-fill-soft` (every
     button's own background) or `--seg-thumb-fill` (the phone seg-thumb pill, fix round 1 finding
     2) at all -- under Glass/reduce-transparency:no-preference their LIVE value already equals
     what it always was (P1's own header: "P1 does not touch the pool's button/field/chip/card
     recipes"), so nothing leaked; Material=Solid is a BRAND NEW third axis this whole branch adds
     (base has no such concept), and its `:root.solid` block DOES retune both -- with no games-keep
     counterpart, that retuning reaches games content too (226 computed diffs vs base under Solid,
     0 under Glass/Flush). Named here at their NORMAL (always-glass) formula, split light/dark like
     the `--keep-glass-rim-*` pair above, so games-keep can re-pin them regardless of which Material
     is active -- the same "games content never changes" contract every other games-keep token
     already honours for Glass vs Solid was simply never extended to these two. */
  --keep-glass-fill-soft-light: color-mix(in srgb, var(--bg-solid) 70%, transparent);
  --keep-glass-fill-soft-dark: color-mix(in srgb, var(--bg-solid) 42%, transparent);
  --keep-seg-thumb-fill-light: rgba(255,255,255,.94);
  --keep-seg-thumb-fill-dark: rgba(255,255,255,.18);
  /* fix round (pool-gaps-2, games freeze regression found while re-verifying finding 1 with the
     extended games_keep_ab.py --solid matrix): `--glass-fill-strong` is the SAME "brand-new Solid
     axis, no pre-existing games behaviour to match" case finding 18/E3 already fixed for
     --glass-fill-soft/--seg-thumb-fill above -- missed there because it is normally read only by
     the platform's own menus/dialogs/popovers group (chrome, not games content), but story-line.css
     (a GAMES module file) reads it DIRECTLY on its own `.sl-pop` popup dialog
     (`background:var(--glass-fill-strong)`), so :root.solid's opaque override
     (`--glass-fill-strong:var(--bg-solid)`) reached it with no games-keep counterpart. */
  --keep-glass-fill-strong-light: color-mix(in srgb, var(--bg-solid) 86%, transparent);
  --keep-glass-fill-strong-dark: color-mix(in srgb, var(--panel-solid) 88%, rgba(255,255,255,.05));
  /* fix round 1 (pool, finding 18/E3), same reasoning: `--bg`/`--panel` are the general liquid-
     glass surface pair (many games rules, e.g. story-line's `.sl-card{background:var(--panel)}`,
     were already written against them long before this branch) -- Solid opacifies both platform-
     wide (`--panel:var(--panel-solid)`) with no games-keep counterpart. Unlike --glass-fill-soft,
     their formula's PERCENTAGE (62/70) doesn't vary by mode -- only --bg-solid/--panel-solid does,
     already mode-aware by inheritance -- so one mode-agnostic pin covers both modes. */
  /* 2026-10-02 DE-GLASS (owner: "review games db wiki ui. fix contents and cards element, which
     overdone during whole web ui change to liquid-glass" / "approved what's in canvas"): the pins
     above and in glass.css's games-keep block froze games content at its 2026-09-11/09-18 GLASS-era
     values (--keep-bg/-panel at 62%/70% alpha, the 09-18 button rim, ...), not at what the owner's
     ruling 2 meant -- the look BEFORE any glass work (commit 45fe0188, 2026-09-10). The surface
     pair is OPAQUE again (the `-solid` twins each palette already carries, which equal B's old
     `--bg`/`--panel` hex palette-for-palette); the rest of B's content tokens live in the
     `--keep-*` set below and are applied by glass.css's games-keep block. */
  --keep-bg: var(--bg-solid);
  --keep-panel: var(--panel-solid);
  /* B's content geometry/type ramp (45fe0188 tokens.css `:root`), shared by light and dark. */
  --keep-radius:14px; --keep-radius-sm:10px;
  --keep-gap:1rem; --keep-pad-card:1.25rem;
  --keep-font:15px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --keep-field-pad-y:.45rem; --keep-field-pad-x:.55rem;
  --keep-fs-hero:clamp(1.8rem,4vw,2.6rem); --keep-fs-display:1.45rem; --keep-fs-title:1.15rem; --keep-fs-caption:.82rem;
  --keep-sp-3:12px; --keep-sp-4:16px; --keep-sp-5:24px; --keep-sp-6:32px; --keep-sp-7:40px; --keep-sp-8:48px;
  --keep-scrim:rgba(15,17,20,.4);
  /* B's SOLID hairlines + hover step (Classic light; Classic dark + the 7 dark palettes override
     below; a named LIGHT palette -- which did not exist at B -- derives the same three from its own
     --fg over its own solid, the closest "opaque equivalent" of B's recipe). */
  --keep-bd:#e3e6ea; --keep-bd2:#eef0f3; --keep-hover:#f0f2f5;
}
:root:not(.dark)[class*="light-"]{
  --keep-bd: color-mix(in srgb, var(--fg) 12%, var(--bg-solid));
  --keep-bd2: color-mix(in srgb, var(--fg) 7%, var(--bg-solid));
  --keep-hover: color-mix(in srgb, var(--fg) 6%, var(--bg-solid));
}
:root.dark{ --keep-bd:#2b2f38; --keep-bd2:#23262d; --keep-hover:#2c313a; --keep-scrim:rgba(0,0,0,.6); }
:root.dark.dark-graphite{ --keep-bd:#2c3039; --keep-bd2:#23272e; --keep-hover:#23272f; }
:root.dark.dark-midnight{ --keep-bd:#25344c; --keep-bd2:#1b283b; --keep-hover:#1a2942; }
:root.dark.dark-ink{ --keep-bd:#2c2e34; --keep-bd2:#202226; --keep-hover:#1c1e23; }
:root.dark.dark-slate{ --keep-bd:#334155; --keep-bd2:#283548; --keep-hover:#263349; }
:root.dark.dark-mocha{ --keep-bd:#313244; --keep-bd2:#2a2a3c; --keep-hover:#26263a; }
:root.dark.dark-nord{ --keep-bd:#3f4759; --keep-bd2:#363d4c; --keep-hover:#3b4252; }
:root.dark.dark-ember{ --keep-bd:#302a25; --keep-bd2:#26221e; --keep-hover:#28231f; }

/* 2026-10-02 DE-GLASS: `--live-*` -- :root-level SNAPSHOTS of the live glass-era tokens that glass.css's
   games-keep block re-pins (to B's pre-glass values) on the games content root. A custom
   property's `var()` is substituted where the declaration sits, so `--live-bd:var(--bd)` here freezes
   whatever :root's `--bd` is (palette/mode/Solid included) and that resolved value then inherits
   unchanged through the content root's re-pin. The few CHROME pieces that live INSIDE a games content
   root (`#gp-nav` tools nav, `#gswitch` game switcher + its menu -- owner ruling 2026-09-25: chrome
   stays glass) re-declare the real tokens from these, so the de-glass never reaches them. */
:root{
  --live-bg:var(--bg); --live-panel:var(--panel); --live-bd:var(--bd); --live-bd2:var(--bd2);
  --live-hover:var(--hover); --live-radius:var(--radius); --live-radius-sm:var(--radius-sm);
  --live-c-fill:var(--c-fill); --live-c-shadow:var(--c-shadow); --live-field-shadow:var(--field-shadow);
  --live-chip-fill:var(--chip-fill); --live-chip-shadow:var(--chip-shadow);
  --live-field-pad-y:var(--field-pad-y); --live-field-pad-x:var(--field-pad-x);
  --live-gap:var(--gap); --live-pad-card:var(--pad-card); --live-scrim:var(--scrim); --live-font:var(--font);
  --live-fs-hero:var(--fs-hero); --live-fs-display:var(--fs-display); --live-fs-title:var(--fs-title);
  --live-fs-caption:var(--fs-caption);
  --live-sp-3:var(--sp-3); --live-sp-4:var(--sp-4); --live-sp-5:var(--sp-5);
  --live-sp-6:var(--sp-6); --live-sp-7:var(--sp-7); --live-sp-8:var(--sp-8);
  --live-hub-bd:var(--hub-bd); --live-hub-radius:var(--hub-radius);
  --live-hub-bg:var(--hub-bg); --live-hub-bg2:var(--hub-bg2); --live-hub-panel:var(--hub-panel);
  --live-bg2:var(--bg2); --live-panel2:var(--panel2); --live-head:var(--head);
  --live-g-bg:var(--g-bg); --live-g-bg2:var(--g-bg2);
}

/* --cell/--cell-solid: a row/box whose backdrop is the GROUND directly (not an inset inside a
   white --bg/--bg-solid card). --panel means "grey inset inside a white surface"; in dark that
   tone is already lighter than the dark ground so a --panel row on the ground still reads fine,
   but in light --panel-solid (#f6f7f9) is now within a few RGB levels of the new grey ground
   (#f2f2f7) and would visually vanish there -- --cell is the same role as --panel, one step
   whiter, for exactly that ground-level case. Dark's --cell-solid is --panel-solid (already
   correct there, so dark stays pixel-identical, folded into the shared dark block above) -- see
   glass.css/DESIGN.md for the migrated selector list. */
:root,.ltprev{ --cell-solid:#ffffff; }
:root,.dkprev,.ltprev{ --cell: color-mix(in srgb, var(--cell-solid) 70%, transparent); }
/* @property registration mirrors --panel above (same reasoning: getComputedStyle callers need a
   resolved rgba(), not the raw color-mix(...) string). */
@property --cell{ syntax:'<color>'; inherits:true; initial-value:#ffffff; }


