/* Design tokens for the SIJO launcher glassmorphism pass.
   Every colour used anywhere in app.css must be a token defined here --
   no hardcoded colours in app.css. */

:root {
  /* -- SIJO brand, read from the logo --
     The ONLY place a brand colour is written. Every token below is
     expressed in terms of these five, so re-sampling the logo later is a
     five-line change. */
  --sijo-navy: #0E1B4D;
  --sijo-royal: #2B5CE6;
  --sijo-periwinkle: #6E8BE8;
  --sijo-mist: #A9BDF0;
  --sijo-paper: #F2F6FF;

  /* Royal darkened for hover and visited states. Derived from
     --sijo-royal; not an independent brand colour. */
  --sijo-royal-deep: #1E48C8;
  /* Navy lightened until it clears 4.5:1 on paper -- see
     tests/test_theme_tokens.py::test_light_mode_body_text_meets_aa. */
  --sijo-navy-muted: #5A6A92;

  --base: var(--sijo-paper);
  --ink: var(--sijo-navy);
  --muted: var(--sijo-navy-muted);

  /* Admin surface: navy in both themes, so the common-links page can never
     be mistaken for the personal one at a glance regardless of the
     viewer's light/dark preference. Defined once here rather than
     redefined per theme block, because its value never changes with
     the theme -- that constancy is the point. */
  --admin-surface: var(--sijo-navy);

  /* Off-white ink/glass-text tints used by any surface that is dark
     regardless of the ambient scheme: the dark theme itself, and the
     admin surface above (always navy, even in light mode). Defined once
     here and referenced by both dark-theme blocks below and by
     body.admin in app.css, so the two can never drift the way two
     independent literals would. */
  --dark-ink: #EEF3FF;
  --dark-text-on-glass: #F4F7FF;
  --dark-muted: var(--sijo-mist);

  /* -- Semantic roles --
     app.css references these, never a brand token. */
  --accent: var(--sijo-royal);
  --accent-strong: var(--sijo-royal-deep);
  --focus-ring: var(--sijo-royal);

  /* -- Banner colours --
     Named here so app.css holds no colour literals; today they are defined
     only in light mode, a later task gives them dark-mode values. */
  --banner-bg: #fff3cd;
  --banner-fg: #6b5200;
  --banner-error-bg: #fde2e2;

  /* Dialog backdrop scrim. Derived from --sijo-navy rather than the
     retired near-black so the darkened overlay stays on-brand.

     color-mix() inside a var() substitution that a browser cannot parse
     makes the CONSUMING declaration invalid at computed-value time, which
     resets it to the property's initial value -- transparent, for a
     background -- not "the old colour". The plain declaration right
     before it is a same-property fallback so the cascade degrades to a
     solid colour instead of the scrim vanishing outright. Approximated as
     navy at 45% over --sijo-paper (the light-mode page, this token's
     only declaration site); dark mode reuses the same --backdrop rather
     than overriding it, so an unsupporting browser in dark mode gets this
     same solid approximation too -- a decorative scrim, not text or a UI
     boundary, so it carries no AA floor of its own. */
  --backdrop: #8B93AF;
  --backdrop: color-mix(in srgb, var(--sijo-navy) 45%, transparent);

  --bg: var(--base);
  --text-primary: var(--ink);
  --text-secondary: var(--muted);
  --link: var(--sijo-royal);
  --link-hover: var(--sijo-royal-deep);
  /* --danger is TEXT/BORDER only (tile-invalid border and subtitle, the
     banner error message, dialog field errors -- app.css). --danger-surface
     is the resting BACKGROUND of button.danger, with white text on top;
     --danger-strong is that button's :hover background. Split into three
     tokens because one token cannot be both "light enough to read as text
     on a dark background" and "dark enough for white text to read on it as
     a background" -- see the dark-mode block below for the numbers and the
     app.css:318 button.danger regression that motivated the split. */
  --danger: #c02a2a;
  --danger-surface: #C02A2A;
  --danger-strong: #a01f1f;
  /* The label colour for text sitting ON --danger-surface/--danger-strong
     as a filled background (button.danger's hover/focus fill in app.css --
     the ghost Delete button becomes a solid block only at that moment).
     Always white regardless of theme -- like --admin-surface above, this
     is defined once here rather than duplicated per theme block, because
     its value never changes with the theme. White already clears AA on
     both backgrounds in both themes (5.82:1 / 7.75:1 light, 6.89:1 /
     6.31:1 dark -- see the dark-mode block's --danger-surface comment). */
  --danger-surface-fg: #ffffff;
  --radius: 14px;
  --radius-lg: 20px;
  --page-pad-inline: clamp(1rem, 5vw, 2rem);
  /* Wide enough that at a 1280px viewport the column uses essentially the
     full available width (1280 - 2*page-pad) rather than capping short of
     it; still bounded so line lengths / panel widths stay sane on an
     ultrawide monitor. */
  --content-max-width: 1400px;

  /* Solid (non-glass) card surface -- used only by the edit dialog, which
     needs to stay fully legible over form controls rather than translucent. */
  --surface: #ffffff;

  /* Icon "chip" behind each tile's Font Awesome glyph/image.

     Same color-mix()-has-no-fallback hazard as --backdrop above: each pair
     below carries a plain solid declaration first (royal at its mix % over
     --sijo-paper, this block's --bg) so a browser without color-mix()
     support keeps a chip instead of losing it to transparent. */
  --icon-chip-bg: #D8E2FC;
  --icon-chip-bg: color-mix(in srgb, var(--sijo-royal) 13%, transparent);
  --icon-chip-bg-hover: #C6D4FA;
  --icon-chip-bg-hover: color-mix(in srgb, var(--sijo-royal) 22%, transparent);
  --icon-chip-fg: var(--sijo-royal);

  /* -- Segmented control (the theme toggle) --
     The selected option has to read as lifted out of the track: brighter
     than the track behind it, with an icon that clears 3:1 against its own
     background. An explicit pair per theme rather than a reuse of
     --surface and --accent, because those name other roles -- dark
     --accent is a *background* role (white sits on it), and borrowing it
     as a foreground on --surface is what left the selected icon at 2.70:1
     on a background darker than its own track. Guarded by
     tests/test_theme_tokens.py::test_the_theme_toggle_selected_option_reads_as_selected. */
  --control-selected-bg: #FFFFFF;
  --control-selected-fg: var(--sijo-royal);

  --mesh-opacity: 0.55;

  /* -- Glass surfaces, light mode --
     Two scales: category (outer) panels are dimmer/quieter than the
     brighter tile (inner) rows nested inside them, so the two levels of
     glass read as distinct rather than as mud. */
  --glass-outer-bg: rgba(255, 255, 255, 0.38);
  --glass-outer-border: rgba(255, 255, 255, 0.55);
  --glass-outer-shadow: rgba(40, 44, 90, 0.12);
  --glass-inner-bg: rgba(255, 255, 255, 0.62);
  --glass-inner-bg-hover: rgba(255, 255, 255, 0.78);
  --glass-inner-border: rgba(255, 255, 255, 0.75);
  --glass-inner-shadow: rgba(40, 44, 90, 0.14);
  --glass-blur: 20px;
  --glass-blur-inner: 16px;

  /* Solid fallback for browsers without backdrop-filter support, which
     were tinted to the old palette. */
  --glass-outer-bg-solid: #E7EDFB;
  --glass-inner-bg-solid: #FFFFFF;

  /* Text tokens tuned for AA contrast against the glass surfaces above
     (verified against actual rendered/blurred backgrounds, not just the
     token value in isolation -- see restyle report). */
  --text-on-glass: var(--sijo-navy);
  --text-on-glass-muted: #46557F;

  /* -- Background mesh blooms -- */
  --mesh-bloom-1: var(--sijo-periwinkle);
  --mesh-bloom-2: var(--sijo-mist);
  --mesh-bloom-3: var(--sijo-royal);

  /* -- Pointer-tracking spotlight -- */
  --spotlight-color: rgba(255, 255, 255, 0.55);
  --spotlight-size: 480px;

  /* -- Motion -- */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-entrance: 320ms;
  --stagger-step: 40ms;
  --duration-hover: 160ms;
  --duration-fade: 180ms;

  /* -- Type -- */
  --font-display: "Space Grotesk", "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-body: Inter, system-ui, -apple-system, "Segoe UI", sans-serif;
}

:root[data-theme="dark"] {
  --base: var(--sijo-navy);
  --ink: var(--dark-ink);
  --muted: var(--sijo-mist);
  --bg: var(--base);
  --text-primary: var(--ink);
  --text-secondary: var(--muted);
  --link: var(--sijo-mist);
  --link-hover: #FFFFFF;
  --card-shadow: rgba(0, 0, 0, 0.4);

  --accent: var(--sijo-royal);
  /* A *darkening* of royal, as in light mode. app.css puts `color: #fff`
     on every button and uses --accent-strong as the hover background, so
     this token carries a contract: white text must clear AA on it.
     Lightening it towards periwinkle broke that -- white sat at 3.22:1;
     --sijo-royal-deep restores it to 7.46:1. Guarded by
     tests/test_theme_tokens.py::test_button_label_meets_aa_on_the_accent. */
  --accent-strong: var(--sijo-royal-deep);
  --focus-ring: var(--sijo-mist);

  /* Navy lifted, so a dialog reads as a surface above the page rather
     than a hole in it. */
  --surface: #16244F;

  /* Warning banner stays in the amber family but darkens to sit on navy
     instead of the page-white it assumes in light mode. */
  --banner-bg: #332508;
  --banner-fg: #FCD675;

  /* #c02a2a (the light-mode --danger) computes to roughly 2.1-2.6:1 against
     the dark surfaces it renders text on -- --sijo-navy, --surface, the
     glass-inner tile -- well under the 4.5:1 AA floor for body text. Tinted
     50/50 with white so it stays legible as TEXT in dark mode: 6.89:1 on
     --sijo-navy, 6.31:1 on --surface, 5.18:1 on the translucent glass-inner
     tile over navy (the strictest of the three, since it is the lightest
     backdrop) -- see tests/test_theme_tokens.py::test_dark_mode_danger_text_meets_aa.
     --danger is a semantic red, not one of the five --sijo-* brand hues, so
     there is no brand token to derive it from; it is lightened from its own
     light-mode literal instead of an unrelated new hue. TEXT/BORDER role
     only: white button labels on #E09494 as a *background* are only
     2.38:1, which is why button.danger's resting background is a separate
     token below rather than this one. */
  --danger: #E09494;
  /* --danger-surface / --danger-strong are button.danger's resting and
     :hover backgrounds (app.css:318-319), both opaque with white text on
     top, so unlike --danger above they don't need to double as legible
     text on navy -- they just need white to clear AA on each, which both
     of the light-mode literals already do (5.82:1 / 7.75:1), so dark mode
     reuses that same pair rather than inventing new reds.
     The roles are swapped versus light mode, though: there resting is the
     lighter of the two (#C02A2A) and :hover the darker (#A01F1F); here
     resting is the darker (#A01F1F) and :hover the lighter (#C02A2A), so
     hovering brightens the button -- consistent with every other
     light-on-dark hover pair in this block (--icon-chip-bg-hover,
     --glass-inner-bg-hover, ...). Both orderings clear AA on their own, so
     this isn't a contrast requirement -- it's deliberate for visual
     consistency, the same way --accent-strong above is deliberately kept
     a *darkening* of --accent in both themes rather than "corrected" per
     theme. Don't swap these back to match light mode's assignment. */
  --danger-surface: #A01F1F;
  --danger-strong: #C02A2A;
  /* .banner.error renders its text with --danger (#E09494 above, the TEXT
     role -- not --danger-surface, which never renders text). #E09494 on
     the light #fde2e2 this background used to keep is 1.94:1 (both are
     pale, low-separation colours), so the background darkens here too:
     45% of the original #c02a2a into --sijo-navy, landing at 4.98:1
     against #E09494 -- see
     tests/test_theme_tokens.py::test_dark_mode_danger_text_meets_aa. */
  --banner-error-bg: #5E223D;

  /* color-mix() inside a var() substitution that a browser cannot parse
     makes the CONSUMING declaration invalid at computed-value time, which
     resets it to transparent rather than "the old colour" -- see the
     --backdrop declaration in :root for the full explanation. Each pair
     below carries a plain solid fallback first, approximated as periwinkle
     at its mix % over --sijo-navy (this block's --bg). */
  --icon-chip-bg: #21316C;
  --icon-chip-bg: color-mix(in srgb, var(--sijo-periwinkle) 20%, transparent);
  --icon-chip-bg-hover: #2D3F7F;
  --icon-chip-bg-hover: color-mix(in srgb, var(--sijo-periwinkle) 32%, transparent);
  --icon-chip-fg: var(--sijo-periwinkle);

  /* See the light-mode declaration for why this pair exists. Periwinkle
     lifted off navy sits brighter than the track (which is periwinkle at
     20% over the same navy), and paper on it clears 3:1 comfortably.
     Both colours here are fully opaque, so the mix result does not depend
     on whatever is behind it -- the fallback below is the exact resolved
     colour, not an approximation, and needs no rationale beyond that. */
  --control-selected-bg: #3C5197;
  --control-selected-bg: color-mix(in srgb, var(--sijo-periwinkle) 48%, var(--sijo-navy));
  --control-selected-fg: var(--sijo-paper);

  --mesh-opacity: 0.32;
  --mesh-bloom-1: #23347A;
  --mesh-bloom-2: #1B4A7A;
  --mesh-bloom-3: var(--sijo-royal);

  --glass-outer-bg: rgba(255, 255, 255, 0.06);
  --glass-outer-border: rgba(255, 255, 255, 0.10);
  --glass-outer-shadow: rgba(0, 0, 0, 0.45);
  --glass-inner-bg: rgba(255, 255, 255, 0.10);
  --glass-inner-bg-hover: rgba(255, 255, 255, 0.16);
  --glass-inner-border: rgba(255, 255, 255, 0.16);
  --glass-inner-shadow: rgba(0, 0, 0, 0.50);

  --glass-outer-bg-solid: #142055;
  --glass-inner-bg-solid: #1A2A62;

  --text-on-glass: var(--dark-text-on-glass);
  --text-on-glass-muted: var(--sijo-mist);

  /* Same color-mix()-has-no-fallback hazard as above: mist at 14% over
     --sijo-navy (this block's --bg). */
  --spotlight-color: #243264;
  --spotlight-color: color-mix(in srgb, var(--sijo-mist) 14%, transparent);
}

/* Respect the user's OS-level dark preference when the app hasn't set an
   explicit data-theme (mirrors how :root[data-theme="dark"] is authored
   above -- any future 'light' override lives in a sibling selector that
   simply doesn't redefine these). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --base: var(--sijo-navy);
    --ink: var(--dark-ink);
    --muted: var(--sijo-mist);
    --bg: var(--base);
    --text-primary: var(--ink);
    --text-secondary: var(--muted);
    --link: var(--sijo-mist);
    --link-hover: #FFFFFF;
    --card-shadow: rgba(0, 0, 0, 0.4);

    --accent: var(--sijo-royal);
    /* A *darkening* of royal, as in light mode. app.css puts `color: #fff`
       on every button and uses --accent-strong as the hover background, so
       this token carries a contract: white text must clear AA on it.
       Lightening it towards periwinkle broke that -- white sat at 3.22:1;
       --sijo-royal-deep restores it to 7.46:1. Guarded by
       tests/test_theme_tokens.py::test_button_label_meets_aa_on_the_accent. */
    --accent-strong: var(--sijo-royal-deep);
    --focus-ring: var(--sijo-mist);

    /* Navy lifted, so a dialog reads as a surface above the page rather
       than a hole in it. */
    --surface: #16244F;

    /* Warning banner stays in the amber family but darkens to sit on navy
       instead of the page-white it assumes in light mode. */
    --banner-bg: #332508;
    --banner-fg: #FCD675;

    /* #c02a2a (the light-mode --danger) computes to roughly 2.1-2.6:1 against
       the dark surfaces it renders text on -- --sijo-navy, --surface, the
       glass-inner tile -- well under the 4.5:1 AA floor for body text. Tinted
       50/50 with white so it stays legible as TEXT in dark mode: 6.89:1 on
       --sijo-navy, 6.31:1 on --surface, 5.18:1 on the translucent glass-inner
       tile over navy (the strictest of the three, since it is the lightest
       backdrop) -- see tests/test_theme_tokens.py::test_dark_mode_danger_text_meets_aa.
       --danger is a semantic red, not one of the five --sijo-* brand hues, so
       there is no brand token to derive it from; it is lightened from its own
       light-mode literal instead of an unrelated new hue. TEXT/BORDER role
       only: white button labels on #E09494 as a *background* are only
       2.38:1, which is why button.danger's resting background is a separate
       token below rather than this one. */
    --danger: #E09494;
    /* --danger-surface / --danger-strong are button.danger's resting and
       :hover backgrounds (app.css:318-319), both opaque with white text on
       top, so unlike --danger above they don't need to double as legible
       text on navy -- they just need white to clear AA on each, which both
       of the light-mode literals already do (5.82:1 / 7.75:1), so dark mode
       reuses that same pair rather than inventing new reds.
       The roles are swapped versus light mode, though: there resting is the
       lighter of the two (#C02A2A) and :hover the darker (#A01F1F); here
       resting is the darker (#A01F1F) and :hover the lighter (#C02A2A), so
       hovering brightens the button -- consistent with every other
       light-on-dark hover pair in this block (--icon-chip-bg-hover,
       --glass-inner-bg-hover, ...). Both orderings clear AA on their own, so
       this isn't a contrast requirement -- it's deliberate for visual
       consistency, the same way --accent-strong above is deliberately kept
       a *darkening* of --accent in both themes rather than "corrected" per
       theme. Don't swap these back to match light mode's assignment. */
    --danger-surface: #A01F1F;
    --danger-strong: #C02A2A;
    /* .banner.error renders its text with --danger (#E09494 above, the TEXT
       role -- not --danger-surface, which never renders text). #E09494 on
       the light #fde2e2 this background used to keep is 1.94:1 (both are
       pale, low-separation colours), so the background darkens here too:
       45% of the original #c02a2a into --sijo-navy, landing at 4.98:1
       against #E09494 -- see
       tests/test_theme_tokens.py::test_dark_mode_danger_text_meets_aa. */
    --banner-error-bg: #5E223D;

    /* color-mix() inside a var() substitution that a browser cannot parse
       makes the CONSUMING declaration invalid at computed-value time, which
       resets it to transparent rather than "the old colour" -- see the
       --backdrop declaration in :root for the full explanation. Each pair
       below carries a plain solid fallback first, approximated as periwinkle
       at its mix % over --sijo-navy (this block's --bg). */
    --icon-chip-bg: #21316C;
    --icon-chip-bg: color-mix(in srgb, var(--sijo-periwinkle) 20%, transparent);
    --icon-chip-bg-hover: #2D3F7F;
    --icon-chip-bg-hover: color-mix(in srgb, var(--sijo-periwinkle) 32%, transparent);
    --icon-chip-fg: var(--sijo-periwinkle);

    /* See the light-mode declaration for why this pair exists. Periwinkle
       lifted off navy sits brighter than the track (which is periwinkle at
       20% over the same navy), and paper on it clears 3:1 comfortably.
       Both colours here are fully opaque, so the mix result does not depend
       on whatever is behind it -- the fallback below is the exact resolved
       colour, not an approximation, and needs no rationale beyond that. */
    --control-selected-bg: #3C5197;
    --control-selected-bg: color-mix(in srgb, var(--sijo-periwinkle) 48%, var(--sijo-navy));
    --control-selected-fg: var(--sijo-paper);

    --mesh-opacity: 0.32;
    --mesh-bloom-1: #23347A;
    --mesh-bloom-2: #1B4A7A;
    --mesh-bloom-3: var(--sijo-royal);

    --glass-outer-bg: rgba(255, 255, 255, 0.06);
    --glass-outer-border: rgba(255, 255, 255, 0.10);
    --glass-outer-shadow: rgba(0, 0, 0, 0.45);
    --glass-inner-bg: rgba(255, 255, 255, 0.10);
    --glass-inner-bg-hover: rgba(255, 255, 255, 0.16);
    --glass-inner-border: rgba(255, 255, 255, 0.16);
    --glass-inner-shadow: rgba(0, 0, 0, 0.50);

    --glass-outer-bg-solid: #142055;
    --glass-inner-bg-solid: #1A2A62;

    --text-on-glass: var(--dark-text-on-glass);
    --text-on-glass-muted: var(--sijo-mist);

    /* Same color-mix()-has-no-fallback hazard as above: mist at 14% over
       --sijo-navy (this block's --bg). */
    --spotlight-color: #243264;
    --spotlight-color: color-mix(in srgb, var(--sijo-mist) 14%, transparent);
  }
}
