/* ============================================================
   tokens.css — Design tokens + font declarations
   ============================================================
   Single source of truth for CSS custom properties (variables)
   and self-hosted @font-face declarations. This file is loaded
   first in base.html so every component stylesheet that follows
   can reference var(--color-*), var(--font-*), var(--bs-*), etc.
   without ordering surprises.

   File map / refactor context:
     See markdown/design/DESIGN_DECISIONS_CSS_REFACTOR.md for the
     full split plan. This is commit 1 of 8 — extracting tokens
     out of the legacy monolith style.css.

   Theme blocks (in source order, ascending specificity):
     1. :root                                — light default tokens
        + :root                              — Bootstrap variable bridge
     2. [data-theme="dark"]                  — explicit dark override
        (User.theme = 'dark' on the <html> element)
     3. @media (prefers-color-scheme: dark)  — auto fallback for
        User.theme = 'auto' on a dark-OS device. Guarded by
        :root:not([data-theme]) so explicit user choice wins.
   ============================================================ */

/* ============================================================
   Fonts — Geist Sans (body) + Geist Mono (brand)
   ============================================================
   Self-hosted Vercel Geist (SIL Open Font License). The font-display: swap
   directive means the browser shows the system fallback immediately while
   Geist downloads in the background — no FOIT (flash of invisible text).
   ============================================================ */

@font-face {
    font-family: 'Geist';
    font-style: normal;
    font-weight: 300;
    font-display: swap;
    src: url('/static/fonts/geist/Geist-Light.woff2') format('woff2');
}

@font-face {
    font-family: 'Geist';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/static/fonts/geist/Geist-Regular.woff2') format('woff2');
}

@font-face {
    font-family: 'Geist';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('/static/fonts/geist/Geist-Medium.woff2') format('woff2');
}

@font-face {
    font-family: 'Geist';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('/static/fonts/geist/Geist-SemiBold.woff2') format('woff2');
}

@font-face {
    font-family: 'Geist';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('/static/fonts/geist/Geist-Bold.woff2') format('woff2');
}

@font-face {
    font-family: 'Geist Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/static/fonts/geist-mono/GeistMono-Regular.woff2') format('woff2');
}

/* ============================================================
   Design tokens — CSS custom properties (variables)
   ============================================================
   The single source of truth for colors, type, spacing, radii,
   and shadows. Any rule below should reference these via
   var(--token-name) rather than hard-coding hex values.

   Currently mirrors the values that were hard-coded throughout
   the stylesheet (and via Bootstrap defaults) before pr6 — so
   defining these is purely structural. pr6b will start swapping
   hard-coded values to var() references and refining the palette.
   pr6c adds [data-theme="dark"] overrides.

   Naming: --color-* for color, --space-* for spacing, --radius-*
   for border radii, --font-* for typography, --shadow-* for shadows.
   ============================================================ */

:root {
    /* ---- Typography -------------------------------------- */

    /* Font families — Geist Sans for body, Geist Mono for the brand
       wordmark. The fallback chain is the same system stack that
       Bootstrap defaults to, so the page is fully readable before
       Geist finishes downloading. */
    /* app1 — Transmission body face (Inter Tight). Geist kept as a
       fallback for the brief moment between Google Fonts CDN load and
       paint, so the page stays readable. */
    --font-sans: 'Inter Tight', 'Geist', -apple-system, BlinkMacSystemFont,
        'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    --font-mono: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo,
        Consolas, monospace;
    /* app1 — Transmission terminal display face. Used for the navbar
       wordmark + any opt-in "channel chrome" surfaces. DejaVu Sans Mono
       fallback so PNG-exported renders + CDN-down fallback look terminal-
       appropriate. */
    --font-display: 'VT323', 'DejaVu Sans Mono', monospace;

    /* Type scale — matches what's currently rendering. We only
       have a handful of sizes in use right now (10/11/12/13/14
       and Bootstrap's 1rem default for body). */
    --font-size-xs: 10px;
    /* tiny meta text — flash close button */
    --font-size-sm: 11px;
    /* avatar-sm initial, smallest meta */
    --font-size-md: 12px;
    /* avatar-md, small meta, post flash */
    --font-size-base: 13px;
    /* avatar-lg, comment author, dropdown */
    --font-size-body: 14px;
    /* avatar-xl, post author, post body */
    --font-size-lg: 1rem;
    /* default body */
    --font-size-brand: 1.1rem;
    /* navbar-brand */

    /* Font weights — matches what we use today */
    --font-weight-light: 300;
    --font-weight-regular: 400;
    --font-weight-medium: 500;
    --font-weight-semibold: 600;
    --font-weight-bold: 700;

    /* ---- Colors — neutrals ------------------------------- */

    /* Backgrounds & surfaces. Cool off-white page, white card surface,
       subtly cool tint for avatar/empty backgrounds. Inspired by
       Linear's light variant. */
    /* app1 — Transmission cream page bg (was zinc-50 #fafafa pre-v3.6) */
    --color-bg-page: #f5f1e8;
    --color-bg-surface: #ffffff;
    --color-bg-subtle: #f4f4f5;

    /* Text colors. Near-black with cool cast (vs Bootstrap's warm dark
       gray); zinc-tinted muted gray for timestamps and meta text. */
    --color-text: #0a0a0a;
    --color-text-muted: #71717a;
    /* app1 (round 8) — Aliased to --color-on-accent so the pre-Transmission
       token and the new Transmission token resolve to the same value.
       Was hardcoded #ffffff, which made ~27 surfaces (calendar buttons,
       pills, segmented controls) ship pure white while .btn-primary used
       the cream #f5f1e8 via --color-on-accent — a real, visible drift. */
    --color-text-on-accent: var(--color-on-accent);

    /* Borders. Subtle cool neutrals; the Linear-style understated
       dividers. */
    --color-border: #e4e4e7;
    --color-border-subtle: rgba(0, 0, 0, 0.06);

    /* ---- Colors — accent + status ------------------------ */

    /* Accent: Transmission deep-forest phosphor for light mode
       (app1 — v3.6 brand rollout, Matrix-rain feel; dark-mode
       block uses bright Matrix phosphor #22ff5e). Forest reads
       against the cream page bg without burning out; cream sits
       as the text-on-accent color since black-on-forest is too
       low-contrast at this depth. */
    --color-accent: #03721f;
    --color-accent-hover: #024d15;

    /* app1 — companion tokens that pair with phosphor.
       --color-on-accent is THEME-AWARE because the contract differs:
       on dark-mode bright phosphor #22ff5e, BLACK reads cleanly
       (high contrast). On light-mode deep forest #03721f, CREAM
       reads cleanly (the forest is too dark for black-on-green).
       Set the light value here; the dark-mode block overrides.
       --color-accent-outline stays constant pure-black across both
       themes — the 2px carved outline always pairs phosphor with
       pure black regardless of which side of the theme split. */
    --color-on-accent: #f5f1e8;
    --color-accent-outline: #000000;

    /* app1 (round 5) — Halo/glow RGB triplet. Separate from --bs-primary-rgb
       so halos can run brighter than the solid accent in dark mode without
       making buttons/wordmark blow out. Light mode: same as accent (the
       deep forest reads fine in halos on cream). Dark mode override:
       light Matrix green #5fff8a so halos glow visibly against pure black.
       Used by .has-halo and every rgba(... ) halo box-shadow throughout. */
    --color-halo-rgb: 3, 114, 31;

    /* app1 (round 6) — Column-surface split (kept as separate tokens for
       future flexibility; in dark mode they now equal --color-bg-surface
       after round 7 unified all cards to neutral charcoal). */
    --color-bg-column: var(--color-bg-surface);
    --color-bg-column-header: var(--bs-tertiary-bg);

    /* app1 (round 7) — Navbar surface carve-out. All cards/modals/columns
       use --color-bg-surface (neutral charcoal in dark mode). Navbar gets
       its own token so it can stay green in dark mode — the only surface
       that retains the phosphor-terminal color. Defaults to --color-bg-surface
       in light mode for no behavioral change there. */
    --color-bg-navbar: var(--color-bg-surface);

    /* Status colors — refined for the moody-cool palette.
       Slightly desaturated and chosen to read clearly on the
       cool off-white page background. */
    --color-success: #16a34a;
    /* follow / like / vibe — positive */
    --color-warning: #eab308;
    /* "are you sure" prompts */
    --color-danger: #dc2626;
    /* delete / yeet / block */
    --color-info: #0ea5e9;
    /* informational alerts */

    /* ---- Radii ------------------------------------------- */

    /* Softer/larger radii for the Linear-leaning aesthetic. */
    --radius-sm: 8px;
    /* small interactive elements (dropdown items) */
    --radius-md: 12px;
    /* link previews, small cards */
    --radius-lg: 14px;
    /* main cards, post-menu */
    --radius-pill: 999px;
    /* fully rounded — for badges, avatar */

    /* ---- Shadows ----------------------------------------- */

    /* Today: only one shadow (link-preview hover). Naming for
       three levels gives us room to differentiate components later. */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
    --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.10);
    --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.12);

    /* ---- Spacing ----------------------------------------- */

    /* Spacing scale based on Bootstrap's 0.25rem base unit so
       Bootstrap utility classes (mb-2, mt-3 etc) line up. */
    --space-1: 0.25rem;
    /* 4px */
    --space-2: 0.5rem;
    /* 8px */
    --space-3: 0.75rem;
    /* 12px */
    --space-4: 1rem;
    /* 16px */
    --space-5: 1.5rem;
    /* 24px */
    --space-6: 2rem;
    /* 32px */

    /* ---- Transitions ------------------------------------- */

    /* Snappy for hover/focus, slower for state changes (flash fade). */
    --transition-fast: 100ms ease;
    --transition-medium: 150ms ease;
    --transition-slow: 350ms ease;

    /* ---- Safe-area insets (mobile-spacing-audit-full) ---- */

    /* iOS Safari + Android Chrome both honor env(safe-area-inset-*)
       when the viewport meta has viewport-fit=cover. The variables here
       give every fixed/sticky surface a single canonical name to reach
       for instead of hand-rolling env(...) at each site with inconsistent
       fallback defaults. v4.0.1 hotfix patched two surfaces inline; the
       broader sweep migrates everything to these variables.

       Fallback is always 0px so non-iOS / non-PWA viewports degrade
       gracefully (the inset is just zero, no visual change).

       Usage: bottom: calc(var(--space-3) + var(--safe-area-bottom));
              padding-top: max(var(--space-2), var(--safe-area-top));
    */
    --safe-area-top: env(safe-area-inset-top, 0px);
    --safe-area-right: env(safe-area-inset-right, 0px);
    --safe-area-bottom: env(safe-area-inset-bottom, 0px);
    --safe-area-left: env(safe-area-inset-left, 0px);
}

/* ============================================================
   Bootstrap variable overrides
   ============================================================
   Bootstrap 5 exposes its theme as CSS custom properties (--bs-*).
   Overriding them here propagates the new palette to every Bootstrap
   component (buttons, alerts, dropdowns, modals, form inputs, navbar)
   without touching their selectors directly.

   Each override maps a Bootstrap variable to one of our design tokens,
   keeping our :root tokens as the single source of truth.

   Order of precedence: Bootstrap's CDN CSS loads first (sets defaults),
   our style.css loads second, this :root block runs last and wins.
   ============================================================ */

:root {
    /* Page background — Bootstrap's body uses --bs-body-bg */
    --bs-body-bg: var(--color-bg-page);

    /* Body text color */
    --bs-body-color: var(--color-text);

    /* Muted text (text-muted utility, .small text, secondary content) */
    --bs-secondary-color: var(--color-text-muted);

    /* Borders — used by .card, form inputs, list-group, etc. */
    --bs-border-color: var(--color-border);

    /* Primary brand color — flows into .btn-primary, .text-primary,
       .bg-primary, link colors, focus rings, dropdown-item :active. */
    --bs-primary: var(--color-accent);
    /* app1 — Transmission deep-forest RGB (#03721f, retuned to
       Matrix-rain feel from earlier phosphor #1f9d3e) */
    --bs-primary-rgb: 3, 114, 31;
    /* RGB form needed for rgba() Bootstrap helpers like btn focus shadow */

    /* Status colors */
    --bs-success: var(--color-success);
    --bs-success-rgb: 22, 163, 74;
    --bs-warning: var(--color-warning);
    --bs-warning-rgb: 234, 179, 8;
    --bs-danger: var(--color-danger);
    --bs-danger-rgb: 220, 38, 38;
    --bs-info: var(--color-info);
    --bs-info-rgb: 14, 165, 233;

    /* Link color follows accent */
    --bs-link-color: var(--color-accent);
    /* app1 — matches --bs-primary-rgb (was violet 139, 92, 246) */
    --bs-link-color-rgb: 3, 114, 31;
    --bs-link-hover-color: var(--color-accent-hover);

    /* Component radii — Bootstrap exposes these as variables, so cards,
       buttons, inputs, etc. all inherit our softer aesthetic. */
    --bs-border-radius: var(--radius-md);
    --bs-border-radius-sm: var(--radius-sm);
    --bs-border-radius-lg: var(--radius-lg);

    /* Typography — Bootstrap defaults to its own font stack;
       we override to Geist. */
    --bs-body-font-family: var(--font-sans);
}

/* ============================================================
   Dark theme — pr6c
   ============================================================
   The dark palette overrides the color tokens declared in :root.
   Every rule below this block already references colors via
   var(--color-*) or var(--bs-*), so this is the only place we
   need to redeclare values.

   Three trigger conditions, in increasing specificity:
     1. @media (prefers-color-scheme: dark) on :root with no
        data-theme attribute — the User.theme = 'auto' case
        when the OS is in dark mode.
     2. [data-theme="dark"] — explicit User.theme = 'dark', wins
        over the media query.

   The 'light' case needs no override block — :root already
   defines light. [data-theme="light"] explicitly suppresses the
   media query when the user has chosen light despite OS-dark.
   That's handled by selector specificity alone (the :root rules
   declared first match [data-theme="light"]'s html element, and
   the media query's :root:not([data-theme]) doesn't match because
   data-theme IS set).

   The two trigger blocks below share identical declarations.
   They're written separately for clarity rather than DRY because
   merging them with a comma between selectors that include a
   media query is awkward and slightly less readable.
   ============================================================ */

[data-theme="dark"],
:root[data-theme="dark"] {
    /* ---- Backgrounds (inverted depth pattern) ----
       Light mode: page is off-white, cards are white-on-page.
       Dark mode: cards are LIGHTER than the page (raised surfaces).
       This is the standard Material/Linear dark-mode convention —
       surfaces feel "lifted" rather than inset. */
    /* app1 — Matrix code-rain retune (was midnight #0a0e1a with cool
       cast). Pure black page bg + near-black surfaces with subtle
       green cast give the "phosphor on a CRT in a dark room" feel
       the Transmission concept is going for. */
    --color-bg-page: #000000;
    /* pure black — primary dark page bg */
    --color-bg-surface: #141414;
    /* app1 (round 7) — neutral charcoal for all cards/modals/columns.
       Drops the green undertone so card surfaces don't compete with
       the green-only navbar + accent. The navbar keeps the previous
       forest #0f2a17 via --color-bg-navbar below. */
    --color-bg-subtle: #1f1f1f;
    /* neutral charcoal lift — avatar bg, hover states, dividers */

    /* ---- Text ----
       Warm cream (slightly off-white with a yellow cast) — softer
       on pure black than pure white, matches the Transmission palette's
       cream identity in light mode. Muted text shifts toward a cool
       greenish-gray that fits the phosphor surroundings. */
    --color-text: #d8d2c2;
    --color-text-muted: #7a8a7e;
    /* --color-text-on-accent inherits from :root as an alias of
       --color-on-accent (= cream #f5f1e8 in both themes after the
       round-4 unified-accent change). */

    /* ---- Borders ----
       app1 — deep forest doubles as the border on pure-black surfaces.
       Visible as a thin raised line; same hue family as bg-subtle. */
    --color-border: #1f3a26;
    /* deep forest */
    --color-border-subtle: rgba(95, 255, 138, 0.08);

    /* ---- Accent ----
       app1 — Unified deep-forest accent across both themes
       (#03721f). Earlier rounds shipped bright Matrix phosphor
       #22ff5e here, but it blew out buttons + wordmark against
       the pure-black bg — every accent surface read as a flashlight.
       Deep forest reads as a phosphor terminal that's TURNED ON
       rather than the screen itself glowing. Matches the light-mode
       accent so a single value drives buttons/wordmark/halos
       in both themes; the only thing that flips is bg + body text. */
    --color-accent: #03721f;
    /* deep forest — same in light + dark */
    --color-accent-hover: #0a8a2a;
    /* slightly brighter than light-mode hover (#024d15) — on dark bg
       hover should lighten, not darken */

    /* app1 — dark-mode on-accent.
       With the accent at deep forest (not bright phosphor anymore),
       BLACK text on #03721f fails contrast. Cream — same value used
       in light mode — gives ~7:1 contrast. Means the two-token
       contract is now: same accent, same on-accent across both
       themes. Light/dark differs only in page bg + body text. */
    --color-on-accent: #f5f1e8;

    /* ---- Status colors ----
       Each goes one shade brighter than light mode. Light-mode
       desaturated versions disappear into dark backgrounds. */
    --color-success: #22c55e;
    /* green-500 */
    --color-warning: #fbbf24;
    /* amber-400 */
    --color-danger: #f87171;
    /* red-400 */
    --color-info: #38bdf8;
    /* sky-400 */

    /* ---- Shadows ----
       Shadows on dark backgrounds barely show with light-mode
       alpha values. We bump alpha to ~5x so they actually register. */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.5);
    --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.6);

    /* ---- Bootstrap variable bridge ----
       Same pattern as :root — Bootstrap component variables need
       to be re-mapped to the dark tokens. This catches Bootstrap-
       rendered components (alerts, badges, modals, dropdowns) at
       the :root level. Per-component overrides remain pr6d's job. */
    --bs-body-bg: var(--color-bg-page);
    --bs-body-color: var(--color-text);
    --bs-secondary-color: var(--color-text-muted);
    --bs-border-color: var(--color-border);
    --bs-primary: var(--color-accent);
    /* app1 — Deep-forest RGB (#03721f). Solid accent only — halos
       use --color-halo-rgb (light Matrix green) for visibility on
       pure black. See the dark-mode halo token below. */
    --bs-primary-rgb: 3, 114, 31;
    --bs-link-color: var(--color-accent);
    --bs-link-color-rgb: 3, 114, 31;
    --bs-link-hover-color: var(--color-accent-hover);

    /* app1 (round 5) — Dark-mode halo override. Light Matrix green
       #5fff8a (rgb 95, 255, 138) — no blue cast, reads as phosphor
       CRT glow against pure black. Separates from --bs-primary-rgb
       so the solid accent stays deep forest. */
    --color-halo-rgb: 95, 255, 138;

    /* app1 (round 7) — Column tokens (now equal to --color-bg-surface
       since all cards are unified to neutral charcoal). Kept as
       separate tokens so a future PR can split them again without
       chasing all card selectors. */
    --color-bg-column: #141414;
    --color-bg-column-header: #1f1f1f;

    /* app1 (round 7) — Navbar carve-out. The ONLY surface that keeps
       the forest-green Transmission color in dark mode. All other
       cards/modals/dropdowns use the neutral charcoal --color-bg-surface
       above. The contrast (green navbar above neutral page chrome)
       is intentional — it frames the app as a phosphor terminal
       window rather than tinting every surface green. */
    --color-bg-navbar: #0f2a17;

    /* Bootstrap's --bs-tertiary-bg and --bs-secondary-bg are used
       in column headers, post-detail-panel close hover, dropdowns.
       app1 (round 7) — neutral charcoal lift to match the unified
       card aesthetic. */
    --bs-tertiary-bg: #1f1f1f;
    --bs-secondary-bg: #1f1f1f;

    /* Status RGB triplets (Bootstrap helpers like .alert use them
       in rgba() expressions). */
    --bs-success: var(--color-success);
    --bs-success-rgb: 34, 197, 94;
    --bs-warning: var(--color-warning);
    --bs-warning-rgb: 251, 191, 36;
    --bs-danger: var(--color-danger);
    --bs-danger-rgb: 248, 113, 113;
    --bs-info: var(--color-info);
    --bs-info-rgb: 56, 189, 248;
}

/* OS-level prefers-color-scheme: dark, but only when User.theme
   is 'auto' (no data-theme attribute on <html>). The selector
   :root:not([data-theme]) ensures explicit user choice wins. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme]) {
        /* app1 — Transmission palette mirrored from the explicit
           [data-theme="dark"] block above. This block catches users
           on theme="auto" whose OS is in dark mode; without these
           overrides they'd inherit light-mode tokens (mint-dark on
           cream) on a dark-OS device, which would be jarring. */
        /* app1 — Matrix code-rain retune. Mirrors the explicit
           [data-theme="dark"] block above; same palette so theme="auto"
           dark-OS users get the same look. */
        --color-bg-page: #000000;
        --color-bg-surface: #141414;
        --color-bg-subtle: #1f1f1f;

        --color-text: #d8d2c2;
        --color-text-muted: #7a8a7e;

        --color-border: #1f3a26;
        --color-border-subtle: rgba(95, 255, 138, 0.08);

        --color-accent: #03721f;
        --color-accent-hover: #0a8a2a;
        --color-on-accent: #f5f1e8;

        --color-success: #22c55e;
        --color-warning: #fbbf24;
        --color-danger: #f87171;
        --color-info: #38bdf8;

        --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
        --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.5);
        --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.6);

        --bs-body-bg: var(--color-bg-page);
        --bs-body-color: var(--color-text);
        --bs-secondary-color: var(--color-text-muted);
        --bs-border-color: var(--color-border);
        --bs-primary: var(--color-accent);
        --bs-primary-rgb: 3, 114, 31;
        --bs-link-color: var(--color-accent);
        --bs-link-color-rgb: 3, 114, 31;
        --bs-link-hover-color: var(--color-accent-hover);

        /* app1 (round 5) — Halo override for theme="auto" dark-OS users.
           Mirrors the explicit [data-theme="dark"] block. */
        --color-halo-rgb: 95, 255, 138;

        /* app1 (round 7) — Column tokens + navbar carve-out (auto dark mode).
           Mirrors the [data-theme="dark"] block above. */
        --color-bg-column: #141414;
        --color-bg-column-header: #1f1f1f;
        --color-bg-navbar: #0f2a17;

        --bs-tertiary-bg: #1f1f1f;
        --bs-secondary-bg: #1f1f1f;

        --bs-success: var(--color-success);
        --bs-success-rgb: 34, 197, 94;
        --bs-warning: var(--color-warning);
        --bs-warning-rgb: 251, 191, 36;
        --bs-danger: var(--color-danger);
        --bs-danger-rgb: 248, 113, 113;
        --bs-info: var(--color-info);
        --bs-info-rgb: 56, 189, 248;
    }
}

/* ============================================================
   pal1 — user-selectable accent palettes (dark mode only).
   ============================================================
   Each palette below overrides the accent + halo + navbar + border
   tokens for a given data-palette value. Page bg / surface / text
   stay constant — only the accent dimension changes between palettes.
   matrix-green is the EXISTING default declared in the dark blocks
   above; this section adds the 5 new options. Light-mode coverage
   is filed as the palette-light-mode tracker entry; today's light
   mode uses the matrix-green deep-forest accent regardless of which
   palette the user picked.

   Selector pattern — same belt-and-suspenders shape as the dark
   theme blocks above:
     1. [data-theme="dark"][data-palette="X"]
            explicit dark + explicit palette
     2. @media (prefers-color-scheme: dark) {
            :root[data-palette="X"]:not([data-theme])
        }
            theme="auto" + dark OS + explicit palette
   Identical declarations in both blocks for each palette. Written
   separately for clarity over DRY for the same reason the original
   dark blocks were.

   Tokens each palette overrides (everything else inherits):
     --color-accent          solid accent for buttons + wordmark
     --color-accent-hover    slightly brighter for hover states
     --color-on-accent       text color on accent-bg surfaces
     --color-halo-rgb        glow color for halos + focus rings
     --color-bg-navbar       navbar carve-out (only surface that
                             keeps a palette-tinted bg in dark mode)
     --color-border          card borders, hue-matched to palette
     --bs-primary-rgb        Bootstrap bridge — auto-tracks accent
     --bs-link-color-rgb     Bootstrap bridge — auto-tracks accent
   ============================================================ */

/* ---- cherry-bomb (synthwave pink) ---- */
[data-theme="dark"][data-palette="cherry-bomb"],
:root[data-theme="dark"][data-palette="cherry-bomb"] {
    --color-accent: #db295e;
    --color-accent-hover: #ff4a7d;
    --color-on-accent: #f5f1e8;
    --color-halo-rgb: 255, 88, 134;
    --color-bg-navbar: #3a0e1f;
    --color-border: #2a1219;
    --bs-primary-rgb: 219, 41, 94;
    --bs-link-color-rgb: 219, 41, 94;
}
@media (prefers-color-scheme: dark) {
    :root[data-palette="cherry-bomb"]:not([data-theme]) {
        --color-accent: #db295e;
        --color-accent-hover: #ff4a7d;
        --color-on-accent: #f5f1e8;
        --color-halo-rgb: 255, 88, 134;
        --color-bg-navbar: #3a0e1f;
        --color-border: #2a1219;
        --bs-primary-rgb: 219, 41, 94;
        --bs-link-color-rgb: 219, 41, 94;
    }
}

/* ---- mainframe (electric cyan, Tron/Blade Runner) ---- */
[data-theme="dark"][data-palette="mainframe"],
:root[data-theme="dark"][data-palette="mainframe"] {
    --color-accent: #0aa9e0;
    --color-accent-hover: #36c4f0;
    --color-on-accent: #000000;
    --color-halo-rgb: 100, 220, 255;
    --color-bg-navbar: #0a1f2e;
    --color-border: #0e2a3a;
    --bs-primary-rgb: 10, 169, 224;
    --bs-link-color-rgb: 10, 169, 224;
}
@media (prefers-color-scheme: dark) {
    :root[data-palette="mainframe"]:not([data-theme]) {
        --color-accent: #0aa9e0;
        --color-accent-hover: #36c4f0;
        --color-on-accent: #000000;
        --color-halo-rgb: 100, 220, 255;
        --color-bg-navbar: #0a1f2e;
        --color-border: #0e2a3a;
        --bs-primary-rgb: 10, 169, 224;
        --bs-link-color-rgb: 10, 169, 224;
    }
}

/* ---- 1979 (vintage CRT phosphor amber) ---- */
[data-theme="dark"][data-palette="1979"],
:root[data-theme="dark"][data-palette="1979"] {
    --color-accent: #ff9d00;
    --color-accent-hover: #ffb845;
    --color-on-accent: #000000;
    --color-halo-rgb: 255, 192, 77;
    --color-bg-navbar: #2a1f0a;
    --color-border: #3a2a14;
    --bs-primary-rgb: 255, 157, 0;
    --bs-link-color-rgb: 255, 157, 0;
}
@media (prefers-color-scheme: dark) {
    :root[data-palette="1979"]:not([data-theme]) {
        --color-accent: #ff9d00;
        --color-accent-hover: #ffb845;
        --color-on-accent: #000000;
        --color-halo-rgb: 255, 192, 77;
        --color-bg-navbar: #2a1f0a;
        --color-border: #3a2a14;
        --bs-primary-rgb: 255, 157, 0;
        --bs-link-color-rgb: 255, 157, 0;
    }
}

/* ---- fsociety (Mr. Robot oxblood crimson) ---- */
[data-theme="dark"][data-palette="fsociety"],
:root[data-theme="dark"][data-palette="fsociety"] {
    --color-accent: #e02d3c;
    --color-accent-hover: #ff4a59;
    --color-on-accent: #f5f1e8;
    --color-halo-rgb: 255, 90, 110;
    --color-bg-navbar: #3a0e14;
    --color-border: #2a0e14;
    --bs-primary-rgb: 224, 45, 60;
    --bs-link-color-rgb: 224, 45, 60;
}
@media (prefers-color-scheme: dark) {
    :root[data-palette="fsociety"]:not([data-theme]) {
        --color-accent: #e02d3c;
        --color-accent-hover: #ff4a59;
        --color-on-accent: #f5f1e8;
        --color-halo-rgb: 255, 90, 110;
        --color-bg-navbar: #3a0e14;
        --color-border: #2a0e14;
        --bs-primary-rgb: 224, 45, 60;
        --bs-link-color-rgb: 224, 45, 60;
    }
}

/* ---- purple (the original pre-Transmission violet #8b5cf6) ---- */
[data-theme="dark"][data-palette="purple"],
:root[data-theme="dark"][data-palette="purple"] {
    --color-accent: #8b5cf6;
    --color-accent-hover: #a78bfa;
    --color-on-accent: #f5f1e8;
    --color-halo-rgb: 167, 139, 250;
    --color-bg-navbar: #1f1230;
    --color-border: #2a1f3a;
    --bs-primary-rgb: 139, 92, 246;
    --bs-link-color-rgb: 139, 92, 246;
}
@media (prefers-color-scheme: dark) {
    :root[data-palette="purple"]:not([data-theme]) {
        --color-accent: #8b5cf6;
        --color-accent-hover: #a78bfa;
        --color-on-accent: #f5f1e8;
        --color-halo-rgb: 167, 139, 250;
        --color-bg-navbar: #1f1230;
        --color-border: #2a1f3a;
        --bs-primary-rgb: 139, 92, 246;
        --bs-link-color-rgb: 139, 92, 246;
    }
}

/* ---- ux-color-fu -- custom (random) palette ----

   Unlike the 6 named palettes above, this block doesn't hard-code
   the token values. Instead it reads them from --user-* CSS custom
   properties that base.html emits inline on the <html> element when
   User.palette == 'custom'. That inline emission walks
   User.custom_palette_json and produces:

     <html data-palette="custom" style="
       --user-accent: #...;
       --user-accent-hover: #...;
       --user-on-accent: #...;
       --user-halo-rgb: R,G,B;
       --user-bg-navbar: #...;
       --user-border: #...;
     ">

   The fallback values (after the var() commas) mirror the dark-mode
   defaults at the top of this file so a rolled palette with a
   missing token (shouldn't happen but defensive) degrades to the
   matrix-green look rather than going invisible.

   Live-preview JS on /settings/appearance mutates these inline
   --user-* properties to show a rolled palette before commit; once
   committed, the same inline style is re-emitted on the next page
   render via base.html. */

[data-theme="dark"][data-palette="custom"],
:root[data-theme="dark"][data-palette="custom"] {
    --color-accent: var(--user-accent, #03721f);
    --color-accent-hover: var(--user-accent-hover, #0a8a2a);
    --color-on-accent: var(--user-on-accent, #f5f1e8);
    --color-halo-rgb: var(--user-halo-rgb, 134, 232, 154);
    --color-bg-navbar: var(--user-bg-navbar, #0a1f0e);
    --color-border: var(--user-border, #0e2a14);
    --bs-primary-rgb: var(--user-halo-rgb, 134, 232, 154);
    --bs-link-color-rgb: var(--user-halo-rgb, 134, 232, 154);
}
@media (prefers-color-scheme: dark) {
    :root[data-palette="custom"]:not([data-theme]) {
        --color-accent: var(--user-accent, #03721f);
        --color-accent-hover: var(--user-accent-hover, #0a8a2a);
        --color-on-accent: var(--user-on-accent, #f5f1e8);
        --color-halo-rgb: var(--user-halo-rgb, 134, 232, 154);
        --color-bg-navbar: var(--user-bg-navbar, #0a1f0e);
        --color-border: var(--user-border, #0e2a14);
        --bs-primary-rgb: var(--user-halo-rgb, 134, 232, 154);
        --bs-link-color-rgb: var(--user-halo-rgb, 134, 232, 154);
    }
}

