/* Material — Google's Material Design 3 (Material You). See themes/README.md
   for the contract. Loaded after public/css/styles.css, so it wins on source
   order — no !important anywhere.

   ============================================================ SEED COLOUR ==
   Seed hue: a saturated BLUE-leaning-indigo, Lab hue 282° (hex #305da5 at
   the "40" tone). Not M3's own baseline purple (Lab hue ~330-350 in this
   space) — that is the theme every "give me a Material app" demo lands on,
   and it reads as a design-tool default rather than a decision. Blue was
   chosen over the alternatives actually on the table: SCP's own brand mark
   already owns cyan-teal (#00b5d0) and Cyberpunk already owns cyan plus
   magenta, so a green or teal seed would fight the app's own identity and a
   magenta seed would collide with the theme next to it in the picker. Blue
   reads as distinctly "Google Material" without impersonating SCP's own
   colour, and is the second most common real M3 seed after purple, so it
   does not read as an invented eccentric choice either.

   Every colour below is a real Material tonal palette: one seed hue per
   role, a fixed chroma for that role, and Material's own standard TONE
   stops (10/20/30/40/50/60/70/80/90 for the chromatic roles, plus the extra
   0/4/6/12/17/20/22/24/87/92/94/96/98/99/100 stops the surface-container
   ladder needs). Tones were generated in CIELAB LCh — L* is literally the
   dimension Material's own HCT "tone" is calibrated against (HCT's tone is
   CAM16 J, built to track L*) — then converted to sRGB with the standard
   Lab→XYZ→sRGB matrices and hard-coded here as hex, rather than shipped as
   live CSS colour functions, so the exact colour is guaranteed everywhere.
   A first pass used OKLCH instead (the more commonly-reached-for CSS colour
   space) and it was wrong: OKLCH's lightness compresses shadows differently
   from L*, and neutral tone 6 rendered as #000101 — display-indistinguishable
   from pure black, not the "dark GREY" the brief specifically asks for.
   Measured with a screenshot of the dashboard in dark mode, not caught by
   reading the numbers. Switching the generator to CIELAB fixed it: the same
   tone 6 is #131315, a real dark grey with visible separation from black.

   Hues used, all facts about ONE seed:
     primary          H 282°, C 44   — the seed itself. Clear blue-indigo.
     secondary        H 282°, C 12   — same hue, low chroma: Material's own
                                       rule for the secondary role (a
                                       desaturated version of the seed, used
                                       for lower-emphasis chips and controls).
     tertiary         H 320°, C 28   — a violet/plum accent, Material's own
                                       "contrasting accent" role for things
                                       that want to read as "different from
                                       the main action" without inventing an
                                       unrelated colour.
     neutral          H 282°, C 1.5  — the seed hue at almost no chroma: a
                                       faint cool cast on every surface, which
                                       is what keeps a "grey" app from reading
                                       as generic Bootstrap grey.
     neutral-variant  H 282°, C 4    — same idea, a little more chroma, for
                                       borders and muted text that need to
                                       sit a step apart from plain neutral.
     error            H 30°,  C 55   — NOT derived from the seed. Material's
                                       error role is always a fixed red
                                       regardless of seed, precisely so an
                                       error never reads as "on brand."

   Contrast, measured (WCAG relative-luminance formula against the actual
   rendered background, not asserted):
     light  on-surface / surface                    16.37 : 1
     light  on-surface-variant (muted) / surface      8.94 : 1
     light  on-primary (white) / primary              6.49 : 1
     light  field-error text / surface                6.11 : 1
     light  sidebar muted text / sidebar surface       8.48 : 1
     dark   on-surface / surface                     14.35 : 1
     dark   on-surface-variant (muted) / surface     10.88 : 1
     dark   on-primary / primary                       7.26 : 1
     dark   field-error text / surface                 9.53 : 1
     dark   sidebar muted text / sidebar surface      10.09 : 1
   Every pairing clears AA (4.5:1) with real headroom — the tightest is the
   light on-error-container pairing, computed separately at 9.63:1 — and
   these are deliberately not the inflated 9-11:1 figures the OKLCH draft
   produced, which came from pushing chroma harder than sRGB can actually
   hold at the light/dark extremes. Real M3 reference palettes sit in this
   6-11:1 band too; forcing more would mean fighting the colour space rather
   than using it.

   ================================================================ TYPE =====
   Roboto is Material's own face — using it is most of what makes an interface
   read as M3 at a glance, more than any single colour choice. It is loaded
   here via @import rather than a hook in header.ejs: that file's one Google
   Fonts <link> is shared by every theme and already requests Outfit, Karla,
   Chakra Petch and JetBrains Mono unconditionally for the same reason (the
   active theme lives in localStorage, invisible to the server, so nothing can
   be fetched conditionally without a page-load flash). Adding Roboto to that
   shared request belongs to whoever edits header.ejs next, but this theme
   does not need that edit: CSS lets a stylesheet pull in its own font
   stylesheet, and the app's CSP already allows fonts.googleapis.com in
   style-src and fonts.gstatic.com in font-src (middleware/securityHeaders.js)
   for exactly this reason, so the import resolves under the real CSP with no
   extra hook. If header.ejs is ever revisited, folding Roboto into the shared
   request would save the second round-trip this causes — flagged here rather
   than done unasked, since I was told not to touch that file.
   Unlike SCP Colours' Outfit/Karla split (a display face for headings, a
   different one for body), Material uses ONE family for every type role,
   varied by size and weight — so both --pico-font-family and
   --heading-font-family point at Roboto. That is not a simplification, it is
   the M3 type system: Display/Headline/Title/Label/Body are one type ramp.

   ============================================================== LAYOUT =====
   Kept: the wide sidebar-as-navigation-drawer shape, not converted to an
   icon rail. Considered and rejected: Material's own spec names a narrow
   icon-plus-label "navigation rail" for exactly this window width, and it
   would have been the more show-offy choice. But it needs an icon per
   destination, and this app's nav (views/partials/nav.ejs) has 13 links,
   several multi-word ("Check-outs", "Import CSV", "Audit Log") with no icon
   markup at all — the README is explicit that a theme cannot add DOM. A rail
   built by inventing icon glyphs in CSS content or squeezing "Import CSV"
   under a 72px-wide icon would look like a rail and read worse than the menu
   it replaced, which is the failure mode I was warned against.
   What IS genuinely Material about the shell, done without new markup:
     - The drawer is retinted to Material's own tonal system instead of the
       fixed dark VS-Code-style chrome the base theme (and Cyberpunk) use —
       surface-container-low, following light/dark like the rest of the page,
       because a permanently-dark drawer next to a light body is exactly the
       "same chrome regardless of theme" pattern Material replaces with tone.
     - The active item is Material's own navigation-drawer indicator: a full
       stadium pill in the secondary-container tone (not a solid brand-colour
       block), inset from the column's edges.
     - Every interactive control (buttons, nav links, the Appearance trigger)
       gets a Material STATE LAYER: a transparent overlay of the control's own
       ink colour, faded in at 8% on hover / 10% on keyboard focus / 12% on
       press, layered ON TOP of its resting colour rather than swapping to a
       different flat colour. That overlay technique (a ::after covering the
       control, opacity-only) is what actually reads as "Material" up close,
       more than the palette does.
     - Shape by role, not one radius everywhere: buttons and pills are full
       stadiums, cards and menus use Material's "medium" (12px) corner, and
       text fields use Material's FILLED style — a tonal fill, square at the
       bottom, rounded only at the top, with a coloured indicator line that
       thickens on focus instead of Pico's ambient focus glow.

   THAT SIDEBAR RETINTING IS LOAD-BEARING FOR SOMETHING ELSE: the Appearance
   control's base rules (in packages/hub-chrome/public/css/chrome.css since
   2026-09-02 — before that they sat UNSCOPED in cyberpunk.css, the first theme
   built, which was backlog T1) colour the trigger with the --sidebar-* tokens,
   so THIS theme renders through them for anything it does not override with
   higher specificity of its own. The Appearance panel's fixed left offset
   (`calc(224px + 0.5rem)`) is such a rule, and it is safe here ONLY because
   this theme keeps the sidebar's 224px width — a theme that resized the
   sidebar would need to reposition the panel itself, per the README's own
   warning. (cyberpunk.css still carries one bare rule, `.sidebar-nav a`'s
   padding, which every theme also inherits.) */

/* Roboto is requested from views/partials/header.ejs alongside the app's other
   faces, NOT with an @import here. An @import is a blocking SEQUENTIAL fetch —
   the browser cannot begin the font request until this file has been downloaded
   and parsed, so the theme's own type arrives last and the page reflows. The
   agent that wrote this file used @import correctly, having been told not to
   touch shared files; moving it is a change only the owner of header.ejs should
   make. */

:root[data-palette="material"] {
  /* ---------------------------------------------------------- Shape ----
     Material's shape scale, applied by role rather than uniformly (the
     brief's own instruction). --pico-border-radius drives Pico's cards,
     dropdown, tooltip and (before the filled-field override further down
     replaces it) form elements — "medium", Material's own Card shape.
     Buttons are overridden separately, below, to the full stadium Material
     buttons actually use. */
  --pico-border-radius: 0.75rem;

  --heading-font-family: 'Roboto', var(--pico-font-family-sans-serif);
  --pico-font-family: 'Roboto', var(--pico-font-family-sans-serif);

  /* OPTIONAL UI SOUND (X1, 2026-09-04). This theme had no `--theme-sound` at
     all, so its Console-sound control was HIDDEN (public/js/themeToggle.js
     hides the field unless the selected theme declares one) — one of four
     themes with no sound and no visible way to turn it on. The CHIME voice,
     not a new one built for this theme: reusing an existing, already-tuned
     voice is the two-line fix; a Material-specific voice is a bigger,
     separate piece of creative work. See public/js/uiSound.js. */
  --theme-sound: 1;
  --theme-voice: chime;
}

/* ======================================================================
   LIGHT — the default variant of a two-variant theme. The registry that says so is
   packages/hub-chrome/themes.js (`variants: ['light', 'dark']`), and
   views/chrome/head.ejs DERIVES the pre-paint dark-only map from it, so there is
   no hand-kept list to disagree with any more. Applies
   whenever data-theme isn't explicitly "dark": explicit "light", or absent
   with the OS in light mode (the dark media-query block below overrides this
   for "absent with the OS in dark mode").
   ====================================================================== */
:root[data-palette="material"]:not([data-theme="dark"]) {
  /* Material role tokens. Named for what they ARE (Material's own role
     names), not for the hex — the mapping onto --pico-* below is where the
     decisions about what plays which role live, and re-reading them without
     chasing the hue math is the point of naming things this way. */
  --m3-primary: #305da5;
  --m3-primary-rgb: 48, 93, 165;
  --m3-on-primary: #ffffff;
  --m3-primary-container: #c2e1ff;
  --m3-on-primary-container: #001c57;
  --m3-primary-hover: #00468a;

  --m3-secondary: #585e71;
  --m3-secondary-rgb: 88, 94, 113;
  --m3-on-secondary: #ffffff;
  --m3-secondary-container: #dce2f9;
  --m3-on-secondary-container: #151b2b;
  --m3-secondary-hover: #414659;

  --m3-tertiary: #73537c;
  --m3-on-tertiary: #ffffff;
  --m3-tertiary-container: #fcd6ff;
  --m3-on-tertiary-container: #2b1034;

  --m3-error: #aa3534;
  --m3-error-rgb: 170, 53, 52;
  --m3-on-error: #ffffff;
  --m3-error-container: #ffbdb1;
  --m3-on-error-container: #530000;

  --m3-surface: #f9f9fc;
  --m3-on-surface: #1b1b1d;
  --m3-surface-variant: #e0e2ea;
  --m3-on-surface-variant: #45464d;
  --m3-outline: #75777e;
  --m3-outline-variant: #c4c6ce;
  --m3-surface-dim: #d9dadd;
  --m3-surface-bright: #f9f9fc;
  --m3-surface-container-lowest: #feffff;
  --m3-surface-container-low: #f3f3f6;
  --m3-surface-container: #edeef1;
  --m3-surface-container-high: #e7e8eb;
  --m3-surface-container-highest: #e2e2e5;
  --m3-inverse-surface: #303032;
  --m3-inverse-on-surface: #f0f1f3;

  /* -------------------------------------------- Base surface + ink ---- */
  --pico-background-color: var(--m3-surface);
  --pico-color: var(--m3-on-surface);
  --pico-muted-color: var(--m3-on-surface-variant);
  --pico-h1-color: var(--m3-on-surface);
  --pico-h2-color: var(--m3-on-surface);
  --pico-h3-color: var(--m3-on-surface);
  --pico-h4-color: var(--m3-on-surface);
  --pico-h5-color: var(--m3-on-surface);
  --pico-h6-color: var(--m3-on-surface);

  /* --------------------------------------------------------- Primary -- */
  --pico-primary: var(--m3-primary);
  --pico-primary-background: var(--m3-primary);
  --pico-primary-inverse: var(--m3-on-primary);
  --pico-primary-hover: var(--m3-primary-hover);
  --pico-primary-hover-background: var(--m3-primary-hover);
  --pico-primary-underline: rgba(var(--m3-primary-rgb), 0.5);
  --pico-primary-focus: rgba(var(--m3-primary-rgb), 0.35);

  /* -------------------------------------------------------- Secondary -- */
  --pico-secondary: var(--m3-secondary);
  --pico-secondary-background: var(--m3-secondary);
  --pico-secondary-inverse: var(--m3-on-secondary);
  --pico-secondary-hover: var(--m3-secondary-hover);
  --pico-secondary-hover-background: var(--m3-secondary-hover);
  --pico-secondary-focus: rgba(var(--m3-secondary-rgb), 0.25);

  /* <mark> takes the tertiary role — Material's own "contrasting accent for
     heightened attention", which is exactly what a highlighted expiry date
     or overdue mark is for. */
  --pico-mark-background-color: var(--m3-tertiary-container);
  --pico-mark-color: var(--m3-on-tertiary-container);

  /* ----------------------------------------------------------- Error --
     Material's error role drives every ERROR-meaning token Pico exposes —
     invalid form fields and the inline field-error text
     (--pico-del-color, read by .field-error and .field-group-note in
     styles.css) — never the primary. This is the one place "use the error
     role for errors" is literal. */
  --pico-form-element-invalid-border-color: var(--m3-error);
  --pico-form-element-invalid-active-border-color: var(--m3-error);
  --pico-form-element-invalid-focus-color: rgba(var(--m3-error-rgb), 0.35);
  --pico-del-color: var(--m3-error);

  /* ------------------------------------------------------------- Cards -- */
  --pico-card-background-color: var(--m3-surface-container);
  --pico-card-sectioning-background-color: var(--m3-surface-container-high);
  --pico-card-border-color: var(--m3-outline-variant);
  --pico-border-color: var(--m3-outline);
  --pico-muted-border-color: var(--m3-outline-variant);

  /* ------------------------------------------------------ Form elements --
     Colours only here; the FILLED-field shape (flat bottom, rounded top,
     indicator line) is applied further down against the plain element
     selectors, shared by both variants. */
  --pico-form-element-background-color: var(--m3-surface-container-highest);
  --pico-form-element-border-color: var(--m3-outline);
  --pico-form-element-color: var(--m3-on-surface);
  --pico-form-element-placeholder-color: var(--m3-on-surface-variant);
  --pico-form-element-active-background-color: var(--m3-surface-container-highest);
  --pico-form-element-active-border-color: var(--m3-primary);
  --pico-form-element-focus-color: var(--m3-primary);
  --pico-form-element-selected-background-color: var(--m3-secondary-container);

  --pico-table-border-color: var(--m3-outline-variant);
  --pico-table-row-stripped-background-color: rgba(var(--m3-primary-rgb), 0.035);

  --pico-code-background-color: var(--m3-surface-container-high);
  --pico-code-color: var(--m3-on-surface-variant);
  --pico-blockquote-border-color: var(--m3-primary);

  --pico-dropdown-background-color: var(--m3-surface-container);
  --pico-dropdown-border-color: var(--m3-outline-variant);
  --pico-dropdown-hover-background-color: var(--m3-surface-container-high);

  --pico-switch-background-color: var(--m3-surface-container-highest);
  --pico-switch-checked-background-color: var(--m3-primary);
  --pico-range-thumb-color: var(--m3-primary);

  /* Tooltips use Material's INVERSE-surface pairing — a small dark chip even
     inside the light theme, which is the actual Material tooltip look. */
  --pico-tooltip-background-color: var(--m3-inverse-surface);
  --pico-tooltip-color: var(--m3-inverse-on-surface);

  --scroll-shadow-color: rgba(3, 3, 5, 0.16);

  /* --------------------------------------------------- Navigation drawer --
     Retinted onto the tonal system instead of the base theme's fixed dark
     chrome — see the big comment at the top of this file for why that is
     the layout decision here. Follows light/dark like the rest of the page,
     which the base convention (and Cyberpunk) deliberately does not. */
  --sidebar-bg: var(--m3-surface-container-low);
  --sidebar-ink: var(--m3-on-surface);
  --sidebar-muted: var(--m3-on-surface-variant);
  --sidebar-link: var(--m3-on-surface-variant);
  --sidebar-link-active: var(--m3-on-secondary-container);
  --sidebar-hover-bg: var(--m3-surface-container-high);
  --sidebar-active-bg: var(--m3-secondary-container);
}

/* ======================================================================
   DARK — OS-driven half. Applies when data-palette is material, data-theme
   is absent (no explicit choice saved) AND the OS is in dark mode. Mirrors
   :root[data-theme="dark"] below; kept as a literal duplicate rather than a
   shared rule because that is the pattern the base stylesheet already uses
   for the same reason (see :root[data-theme="dark"] vs the media query
   above it in styles.css) — a mixin-style abstraction here would be the one
   surprising thing in an otherwise plain-CSS theme layer.
   These are NOT the light values with darker numbers — Material's dark
   scheme is its own tonal palette: darker, LOWER-chroma neutrals (chroma 1.5/
   4 throughout, same as light — dark surfaces read as grey, not as a tinted
   black) and a LIGHTER, less saturated primary (tone 80 rather
   than tone 40, which is what actually reads as "less saturated": the same
   chroma spread across more lightness headroom desaturates by construction).
   ====================================================================== */
@media (prefers-color-scheme: dark) {
  :root[data-palette="material"]:not([data-theme="light"]) {
    --m3-primary: #a5c5ff;
    --m3-primary-rgb: 165, 197, 255;
    --m3-on-primary: #003070;
    --m3-primary-container: #00468a;
    --m3-on-primary-container: #c2e1ff;
    --m3-primary-hover: #c2e1ff;

    --m3-secondary: #c0c6dc;
    --m3-secondary-rgb: 192, 198, 220;
    --m3-on-secondary: #2a3041;
    --m3-secondary-container: #414659;
    --m3-on-secondary-container: #dce2f9;
    --m3-secondary-hover: #dce2f9;

    --m3-tertiary: #dfbae8;
    --m3-on-tertiary: #42254b;
    --m3-tertiary-container: #5a3b63;
    --m3-on-tertiary-container: #fcd6ff;

    --m3-error: #ffa196;
    --m3-error-rgb: 255, 161, 150;
    --m3-on-error: #6e0009;
    --m3-error-container: #8c161f;
    --m3-on-error-container: #ffbdb1;

    --m3-surface: #131315;
    --m3-on-surface: #e2e2e5;
    --m3-surface-variant: #45464d;
    --m3-on-surface-variant: #c4c6ce;
    --m3-outline: #8f9097;
    --m3-outline-variant: #45464d;
    --m3-surface-dim: #131315;
    --m3-surface-bright: #39393b;
    --m3-surface-container-lowest: #0d0e11;
    --m3-surface-container-low: #1b1b1d;
    --m3-surface-container: #1f1f21;
    --m3-surface-container-high: #292a2c;
    --m3-surface-container-highest: #343537;
    --m3-inverse-surface: #e2e2e5;
    --m3-inverse-on-surface: #303032;

    --pico-background-color: var(--m3-surface);
    --pico-color: var(--m3-on-surface);
    --pico-muted-color: var(--m3-on-surface-variant);
    --pico-h1-color: var(--m3-on-surface);
    --pico-h2-color: var(--m3-on-surface);
    --pico-h3-color: var(--m3-on-surface);
    --pico-h4-color: var(--m3-on-surface);
    --pico-h5-color: var(--m3-on-surface);
    --pico-h6-color: var(--m3-on-surface);

    --pico-primary: var(--m3-primary);
    --pico-primary-background: var(--m3-primary);
    --pico-primary-inverse: var(--m3-on-primary);
    --pico-primary-hover: var(--m3-primary-hover);
    --pico-primary-hover-background: var(--m3-primary-hover);
    --pico-primary-underline: rgba(var(--m3-primary-rgb), 0.5);
    --pico-primary-focus: rgba(var(--m3-primary-rgb), 0.4);

    --pico-secondary: var(--m3-secondary);
    --pico-secondary-background: var(--m3-secondary);
    --pico-secondary-inverse: var(--m3-on-secondary);
    --pico-secondary-hover: var(--m3-secondary-hover);
    --pico-secondary-hover-background: var(--m3-secondary-hover);
    --pico-secondary-focus: rgba(var(--m3-secondary-rgb), 0.3);

    --pico-mark-background-color: var(--m3-tertiary-container);
    --pico-mark-color: var(--m3-on-tertiary-container);

    --pico-form-element-invalid-border-color: var(--m3-error);
    --pico-form-element-invalid-active-border-color: var(--m3-error);
    --pico-form-element-invalid-focus-color: rgba(var(--m3-error-rgb), 0.35);
    --pico-del-color: var(--m3-error);

    --pico-card-background-color: var(--m3-surface-container);
    --pico-card-sectioning-background-color: var(--m3-surface-container-high);
    --pico-card-border-color: var(--m3-outline-variant);
    --pico-border-color: var(--m3-outline);
    --pico-muted-border-color: var(--m3-outline-variant);

    --pico-form-element-background-color: var(--m3-surface-container-highest);
    --pico-form-element-border-color: var(--m3-outline);
    --pico-form-element-color: var(--m3-on-surface);
    --pico-form-element-placeholder-color: var(--m3-on-surface-variant);
    --pico-form-element-active-background-color: var(--m3-surface-container-highest);
    --pico-form-element-active-border-color: var(--m3-primary);
    --pico-form-element-focus-color: var(--m3-primary);
    --pico-form-element-selected-background-color: var(--m3-secondary-container);

    --pico-table-border-color: var(--m3-outline-variant);
    --pico-table-row-stripped-background-color: rgba(var(--m3-primary-rgb), 0.06);

    --pico-code-background-color: var(--m3-surface-container-high);
    --pico-code-color: var(--m3-on-surface-variant);
    --pico-blockquote-border-color: var(--m3-primary);

    --pico-dropdown-background-color: var(--m3-surface-container);
    --pico-dropdown-border-color: var(--m3-outline-variant);
    --pico-dropdown-hover-background-color: var(--m3-surface-container-high);

    --pico-switch-background-color: var(--m3-surface-container-highest);
    --pico-switch-checked-background-color: var(--m3-primary);
    --pico-range-thumb-color: var(--m3-primary);

    --pico-tooltip-background-color: var(--m3-inverse-surface);
    --pico-tooltip-color: var(--m3-inverse-on-surface);

    --scroll-shadow-color: rgba(219, 222, 226, 0.16);

    --sidebar-bg: var(--m3-surface-container-low);
    --sidebar-ink: var(--m3-on-surface);
    --sidebar-muted: var(--m3-on-surface-variant);
    --sidebar-link: var(--m3-on-surface-variant);
    --sidebar-link-active: var(--m3-on-secondary-container);
    --sidebar-hover-bg: var(--m3-surface-container-high);
    --sidebar-active-bg: var(--m3-secondary-container);
  }
}

/* ======================================================================
   DARK — explicit-toggle half. Same values as the media-query block above;
   this is the "the user actually clicked dark" case, unconditional on the
   OS. Keep both in step — see the same requirement stated on the base
   theme's own pair in styles.css.
   ====================================================================== */
:root[data-palette="material"][data-theme="dark"] {
  --m3-primary: #a5c5ff;
  --m3-primary-rgb: 165, 197, 255;
  --m3-on-primary: #003070;
  --m3-primary-container: #00468a;
  --m3-on-primary-container: #c2e1ff;
  --m3-primary-hover: #c2e1ff;

  --m3-secondary: #c0c6dc;
  --m3-secondary-rgb: 192, 198, 220;
  --m3-on-secondary: #2a3041;
  --m3-secondary-container: #414659;
  --m3-on-secondary-container: #dce2f9;
  --m3-secondary-hover: #dce2f9;

  --m3-tertiary: #dfbae8;
  --m3-on-tertiary: #42254b;
  --m3-tertiary-container: #5a3b63;
  --m3-on-tertiary-container: #fcd6ff;

  --m3-error: #ffa196;
  --m3-error-rgb: 255, 161, 150;
  --m3-on-error: #6e0009;
  --m3-error-container: #8c161f;
  --m3-on-error-container: #ffbdb1;

  --m3-surface: #131315;
  --m3-on-surface: #e2e2e5;
  --m3-surface-variant: #45464d;
  --m3-on-surface-variant: #c4c6ce;
  --m3-outline: #8f9097;
  --m3-outline-variant: #45464d;
  --m3-surface-dim: #131315;
  --m3-surface-bright: #39393b;
  --m3-surface-container-lowest: #0d0e11;
  --m3-surface-container-low: #1b1b1d;
  --m3-surface-container: #1f1f21;
  --m3-surface-container-high: #292a2c;
  --m3-surface-container-highest: #343537;
  --m3-inverse-surface: #e2e2e5;
  --m3-inverse-on-surface: #303032;

  --pico-background-color: var(--m3-surface);
  --pico-color: var(--m3-on-surface);
  --pico-muted-color: var(--m3-on-surface-variant);
  --pico-h1-color: var(--m3-on-surface);
  --pico-h2-color: var(--m3-on-surface);
  --pico-h3-color: var(--m3-on-surface);
  --pico-h4-color: var(--m3-on-surface);
  --pico-h5-color: var(--m3-on-surface);
  --pico-h6-color: var(--m3-on-surface);

  --pico-primary: var(--m3-primary);
  --pico-primary-background: var(--m3-primary);
  --pico-primary-inverse: var(--m3-on-primary);
  --pico-primary-hover: var(--m3-primary-hover);
  --pico-primary-hover-background: var(--m3-primary-hover);
  --pico-primary-underline: rgba(var(--m3-primary-rgb), 0.5);
  --pico-primary-focus: rgba(var(--m3-primary-rgb), 0.4);

  --pico-secondary: var(--m3-secondary);
  --pico-secondary-background: var(--m3-secondary);
  --pico-secondary-inverse: var(--m3-on-secondary);
  --pico-secondary-hover: var(--m3-secondary-hover);
  --pico-secondary-hover-background: var(--m3-secondary-hover);
  --pico-secondary-focus: rgba(var(--m3-secondary-rgb), 0.3);

  --pico-mark-background-color: var(--m3-tertiary-container);
  --pico-mark-color: var(--m3-on-tertiary-container);

  --pico-form-element-invalid-border-color: var(--m3-error);
  --pico-form-element-invalid-active-border-color: var(--m3-error);
  --pico-form-element-invalid-focus-color: rgba(var(--m3-error-rgb), 0.35);
  --pico-del-color: var(--m3-error);

  --pico-card-background-color: var(--m3-surface-container);
  --pico-card-sectioning-background-color: var(--m3-surface-container-high);
  --pico-card-border-color: var(--m3-outline-variant);
  --pico-border-color: var(--m3-outline);
  --pico-muted-border-color: var(--m3-outline-variant);

  --pico-form-element-background-color: var(--m3-surface-container-highest);
  --pico-form-element-border-color: var(--m3-outline);
  --pico-form-element-color: var(--m3-on-surface);
  --pico-form-element-placeholder-color: var(--m3-on-surface-variant);
  --pico-form-element-active-background-color: var(--m3-surface-container-highest);
  --pico-form-element-active-border-color: var(--m3-primary);
  --pico-form-element-focus-color: var(--m3-primary);
  --pico-form-element-selected-background-color: var(--m3-secondary-container);

  --pico-table-border-color: var(--m3-outline-variant);
  --pico-table-row-stripped-background-color: rgba(var(--m3-primary-rgb), 0.06);

  --pico-code-background-color: var(--m3-surface-container-high);
  --pico-code-color: var(--m3-on-surface-variant);
  --pico-blockquote-border-color: var(--m3-primary);

  --pico-dropdown-background-color: var(--m3-surface-container);
  --pico-dropdown-border-color: var(--m3-outline-variant);
  --pico-dropdown-hover-background-color: var(--m3-surface-container-high);

  --pico-switch-background-color: var(--m3-surface-container-highest);
  --pico-switch-checked-background-color: var(--m3-primary);
  --pico-range-thumb-color: var(--m3-primary);

  --pico-tooltip-background-color: var(--m3-inverse-surface);
  --pico-tooltip-color: var(--m3-inverse-on-surface);

  --scroll-shadow-color: rgba(219, 222, 226, 0.16);

  --sidebar-bg: var(--m3-surface-container-low);
  --sidebar-ink: var(--m3-on-surface);
  --sidebar-muted: var(--m3-on-surface-variant);
  --sidebar-link: var(--m3-on-surface-variant);
  --sidebar-link-active: var(--m3-on-secondary-container);
  --sidebar-hover-bg: var(--m3-surface-container-high);
  --sidebar-active-bg: var(--m3-secondary-container);
}

/* ======================================================================
   Component rules below apply to BOTH variants (they read tokens, they
   don't set them) so they live once, outside the light/dark blocks above.
   ====================================================================== */

/* ---------------------------------------------------------- Type roles --
   Material's headline/title styles are REGULAR weight at a larger size, not
   bold — the base stylesheet's Outfit heading font leans on weight for
   hierarchy, Material leans on size and a tighter negative tracking. Applied
   only to h1/h2 (Display/Headline territory); h3-h6 keep the base weight,
   since Material's own Title style is medium-weight and that already
   matches what Pico ships. */
:root[data-palette="material"] h1,
:root[data-palette="material"] h2 {
  font-weight: 400;
  letter-spacing: -0.01em;
}

/* ------------------------------------------------------------- Shape:
   buttons are Material's full-stadium shape, layered with a real state
   layer (see the file-top comment). Excludes .th-sort — that control is
   deliberately stripped back to bare header text by styles.css itself
   (`th > .th-sort { background:none; border:0; box-shadow:none; ...}`) and
   is a <button> only for click-target reasons; giving it a pill and an
   overlay would put a floating oval in the middle of a table header.
   Excludes controls inside [role=group]/[role=search] (the topbar search's
   Find button, the list/report toolbar's inline buttons): Pico flushes
   those against their neighbouring input using ITS OWN shared corner
   radius, and a full pill on just the button half of that seam looks like
   a mismatched fragment, not two Material components side by side. */
:root[data-palette="material"] :is(button, [type="submit"], [type="button"], [type="reset"], [role="button"]):not(.th-sort):not([role="group"] *):not([role="search"] *) {
  position: relative;
  overflow: hidden;
  border-radius: 999px;
}

:root[data-palette="material"] :is(button, [type="submit"], [type="button"], [type="reset"], [role="button"]):not(.th-sort):not([role="group"] *):not([role="search"] *)::after {
  content: '';
  position: absolute;
  inset: 0;
  background-color: currentColor;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease;
}

/* Ordered hover / focus-visible / active so a control in more than one state
   at once (mouse hover AND keyboard focus, say) shows the LATER, more
   emphatic layer — equal specificity throughout, so source order alone
   decides, the same equal-specificity discipline styles.css itself uses for
   its sort-arrow rules. Material's own three stops: 8% hover, 10% focus,
   12% pressed. */
:root[data-palette="material"] :is(button, [type="submit"], [type="button"], [type="reset"], [role="button"]):not(.th-sort):not([role="group"] *):not([role="search"] *):hover::after {
  opacity: 0.08;
}
:root[data-palette="material"] :is(button, [type="submit"], [type="button"], [type="reset"], [role="button"]):not(.th-sort):not([role="group"] *):not([role="search"] *):focus-visible::after {
  opacity: 0.1;
}
:root[data-palette="material"] :is(button, [type="submit"], [type="button"], [type="reset"], [role="button"]):not(.th-sort):not([role="group"] *):not([role="search"] *):active::after {
  opacity: 0.12;
}

/* Filled text fields — Material's real shape: a tonal fill, square at the
   bottom, rounded only at the top corners, with a coloured indicator line
   instead of Pico's ambient focus glow. Excludes the control types that
   already have their own Material-adjacent shape (checkbox/radio are
   handled by Pico as small squares/circles; range is a track+thumb; file
   has its own button; [role=search]/[type=search] are already a full pill
   via Pico's own CSS and look wrong flattened). */
:root[data-palette="material"] input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="search"]),
:root[data-palette="material"] select,
:root[data-palette="material"] textarea {
  border-radius: 0.25rem 0.25rem 0 0;
  border: none;
  border-bottom: 1px solid var(--pico-form-element-border-color);
}

:root[data-palette="material"] input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="search"]):focus,
:root[data-palette="material"] select:focus,
:root[data-palette="material"] textarea:focus {
  border-bottom-width: 2px;
  border-bottom-color: var(--pico-primary);
  /* Replaces Pico's box-shadow focus ring outright: Material's filled field
     communicates focus with the indicator line alone, not an ambient glow
     around the whole control. */
  box-shadow: none;
}

/* ------------------------------------------------------------- Cards ----
   article>header/footer sit on the sectioning tone (one step up from the
   card body) rather than a plain border — a second surface tone reads as
   Material's own "this is a distinct region" cue where the base theme uses
   a rule line. */
:root[data-palette="material"] article > header,
:root[data-palette="material"] article > footer {
  background: var(--pico-card-sectioning-background-color);
}

/* ------------------------------------------------------- Focus ring ------
   A visible keyboard-focus outline in the primary role, on top of whatever
   focus treatment an individual control already carries above — this is the
   catch-all for links, table sort headers, and anything else that doesn't
   go through the button/field rules. Both tones were measured against their
   own page background — 6.18:1 light, 10.63:1 dark, both far past the 3:1 a
   non-text UI indicator needs — so the ring itself is never the thing that's
   hard to see. */
:root[data-palette="material"] :focus-visible {
  outline: 2px solid var(--pico-primary);
  outline-offset: 2px;
}

/* ---------------------------------------------- Navigation drawer ------
   The active-item indicator: Material's full-stadium pill in the
   secondary-container tone, replacing the base theme's edge-to-edge flat
   block. Text colour is overridden explicitly because styles.css hard-codes
   `color: #fff` on .sidebar-nav a.active — correct against the base theme's
   always-dark active block, but unreadable against this theme's pastel
   secondary-container fill in light mode. */
:root[data-palette="material"] .sidebar-nav a {
  border-radius: 999px;
}

:root[data-palette="material"] .sidebar-nav a.active {
  color: var(--sidebar-link-active);
  font-weight: 500;
}

/* The Appearance trigger reads as a peer of the nav links above it (it
   already inherits their hover/active colour tokens from the base rule in
   chrome.css — see the file-top comment) — this just brings its corner in
   line with the pill shape used everywhere else in the drawer. */
:root[data-palette="material"] .appearance-trigger {
  border-radius: 999px;
}

/* The Appearance panel is a floating surface, Material's "extra-large"
   shape (28px) and a real two-layer elevation shadow — resting surfaces in
   Material read through tone alone, but a panel that floats OVER the page
   like this one earns actual shadow on top of that, the same distinction
   Material draws between a card and a menu. Wins over chrome.css's base
   `.appearance-panel` rule (border-radius 0.6rem, a flatter shadow) on
   specificity: this selector carries the [data-palette] attribute, that one
   doesn't. */
:root[data-palette="material"] .appearance-panel {
  border-radius: 1.75rem;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3), 0 4px 8px 3px rgba(0, 0, 0, 0.15);
}

:root[data-palette="material"][data-theme="dark"] .appearance-panel {
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5), 0 4px 8px 3px rgba(0, 0, 0, 0.3);
}

/* Dropdown menus (the column chooser, any details.dropdown) get the same
   floating-surface elevation treatment as the Appearance panel. */
:root[data-palette="material"] details.dropdown > summary + ul {
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3), 0 4px 8px 3px rgba(0, 0, 0, 0.15);
}

:root[data-palette="material"][data-theme="dark"] details.dropdown > summary + ul {
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5), 0 4px 8px 3px rgba(0, 0, 0, 0.3);
}

/* Filter chips (/checkouts, report pages): styles.css hard-codes the SCP
   brand teal (#00838f) as the hover border on every theme, which is a stray
   off-palette accent here — swapped for this theme's own primary. The
   "alert" (something overdue) variant is untouched: that colour is
   semantic, not brand, and stays exactly as base styles.css defines it. */
:root[data-palette="material"] .filter-chip:hover,
:root[data-palette="material"] .filter-chip:focus-visible {
  border-color: var(--pico-primary);
}

/* Motion: state-layer fades and the invalid-field indicator both use short
   transitions already; nothing here relies on movement to be understood, so
   reduced-motion only needs the transition removed, not a redesign. */
@media (prefers-reduced-motion: reduce) {
  :root[data-palette="material"] :is(button, [type="submit"], [type="button"], [type="reset"], [role="button"])::after {
    transition: none;
  }
}

/* ---------------------------------------------------- attention tiles -------
   The five dashboard attention tiles were left carrying the base theme's
   hardcoded palette — SCP's warm amber #7f5d09 and salmon #914131 — which the
   agent flagged honestly rather than hiding. On M3's cooler tonal surfaces they
   read as a different design showing through.

   Mapped onto M3 ROLES, not onto raw hex, so they move with the tonal system:
   error-container for a problem, tertiary-container for "soon", and
   secondary-container for "in flight". That is the roles' actual purpose —
   error is error, and the two low-emphasis accent containers are what M3 uses
   for supporting emphasis.

   PRIMARY IS DELIBERATELY NOT USED HERE. Primary is the theme's own accent, and
   a tile whose colour means "on brand" instead of "this needs you" has stopped
   carrying information — which is the entire job of the attention row. The
   quiet tile keeps a plain surface container, because "nothing to do" should
   not compete for attention at all. */
:root[data-palette="material"] .stat-tile-salmon {
  background: var(--m3-error-container);
  color: var(--m3-on-error-container);
  border: 1px solid transparent;
}

/* "Soon" gets a WARNING pair defined here rather than M3's tertiary role, and
   this is a deliberate departure. Mapping it to tertiary is the M3-pure answer
   and it renders PINK from a blue-indigo seed — measured rgb(252,214,255) — which
   does not read as "this is coming due". M3 simply has no warning role; error,
   primary, secondary and tertiary are the whole set, and tertiary means
   "contrasting accent", not "caution".
   So: an amber container built the way M3 builds one — a high-tone, low-chroma
   fill with a low-tone on-colour — keeping the theme's construction while
   letting the tile carry its actual meaning. Semantic colour staying semantic
   outranks role purity; a tile nobody reads as a warning is not a warning. */
:root[data-palette="material"] .stat-tile-amber {
  background: #ffe1a8;
  color: #4a3000;
  border: 1px solid transparent;
}

:root[data-palette="material"][data-theme="dark"] .stat-tile-amber {
  background: #4a3714;
  color: #ffdfa6;
}

:root[data-palette="material"] .stat-tile-teal {
  background: var(--m3-secondary-container);
  color: var(--m3-on-secondary-container);
  border: 1px solid transparent;
}

:root[data-palette="material"] .stat-tile-quiet {
  background: var(--m3-surface-container);
  color: var(--m3-on-surface-variant);
  border: 1px solid var(--m3-outline-variant);
}

/* The figure and its caption inherit the tile's own on-container colour rather
   than the accent, or the hue carrying urgency stops being legible exactly
   where it matters most. */
:root[data-palette="material"] .stat-tile-salmon .stat-tile-value,
:root[data-palette="material"] .stat-tile-amber .stat-tile-value,
:root[data-palette="material"] .stat-tile-teal .stat-tile-value,
:root[data-palette="material"] .stat-tile-quiet .stat-tile-value {
  color: inherit;
}

:root[data-palette="material"] .stat-tile-salmon .stat-tile-label,
:root[data-palette="material"] .stat-tile-amber .stat-tile-label,
:root[data-palette="material"] .stat-tile-teal .stat-tile-label,
:root[data-palette="material"] .stat-tile-salmon .stat-tile-caveat,
:root[data-palette="material"] .stat-tile-amber .stat-tile-caveat,
:root[data-palette="material"] .stat-tile-teal .stat-tile-caveat {
  color: inherit;
  opacity: 0.8;
}
