/* Canonical theme palette — the single source of truth for every page (SPA and the standalone
   server-rendered pages: /features, /invoices, /payroll, /audit, /changelog, sign-in).
   Keyed on html[data-theme] so the app's own toggle governs, NOT the OS preference.
   Per-instance brand overrides are injected after this (see branding.theme_head / applyBrand). */
:root {
      /* Tells the browser which way to render the controls IT draws — the date picker's glyph and panel,
         the number spinner, an unstyled checkbox, native scrollbars. CSS can paint an input's box but not
         those, so without this a dark page gets light native chrome sitting inside dark fields.
         Set here, on the same selectors the palette is keyed to, so it flips with the app's own toggle
         rather than with the OS. Individual `color-scheme: dark` rules elsewhere predate this and are now
         redundant; they are left alone because they are harmless and removing them is churn. */
      color-scheme: light;
      --brand: #45235f; --brand-deep: #2f1640; --brand-bright: #7a4bb0;
      --bg: #f4f1f8; --panel: #ffffff; --panel-2: #f2edf8; --line: #e4dcef;
      --text: #251b33; --muted: #635b72; --accent: #5a2d8a; --accent-press: #43206a;
      /* The accent when it is TEXT or a border on a surface, as opposed to a fill with white on it.
         Two tokens because one cannot serve both: the two uses move in exact opposition, and walking the
         dark accent's lightness (hue 262deg, sat 56% fixed, as 6.70.1 did for --ok/--warn) they only cross
         at 4.50/4.50 — no margin on either side. Measured on the dark palette: at L58 white-on-accent is
         4.93 and accent-as-text on --panel-2 is 3.20; at L66 they are 3.46 and 4.55.
         Light needs no adjustment (this palette had zero contrast failures), so it is the accent itself. */
      --accent-text: var(--accent);
      /* Text that sits ON --brand-bright. It flips by theme because --brand-bright itself does: it is the
         dark-on-light brand color in this palette and the light-on-dark one in the other, so a single
         foreground cannot serve both. White on the light-theme #7a4bb0 measures 6.07; white on the
         dark-theme #c7a9f0 measures 2.03, which is what the rail's count badge was doing. */
      --on-brand-bright: #ffffff;
      /* Text ON --brand, the standalone pages' top bar (7.410.0). The same flip as --on-brand-bright: white on
         this theme's #45235f measures 12.66; on the other theme's #c3a9ec white measured 2.06. */
      --on-brand: #ffffff;
      /* The standalone pages' top bar lifts off the page with this, in both themes (7.410.0). */
      --shadow-bar: 0 1px 8px rgba(0,0,0,.18);
      /* A toast floats over the page in the corner, in both themes (7.459.0): the value it has always had. */
      --shadow-toast: 0 8px 24px rgba(0,0,0,.28);
      /* Text ON a filled tone: a solid ok, warn or err pill, and the neutral solid (7.308.0). The tones are
         dark in this palette and light in the other, the --on-brand-bright problem again, so one foreground
         cannot serve both. White here measures 5.49 on --ok, 5.54 on --warn, 5.44 on --err, 6.42 on --muted. */
      --on-tone: #ffffff;
      /* Text that sits ON --accent, i.e. the ink of a filled accent button or a selected segment.
         Defined once rather than per theme, because --accent is a fill in both palettes and white is
         the foreground in both: measured 4.98 on the dark --accent #8257cf, and the light palette had
         zero contrast failures at all (see --accent-text above, which is the token for the OPPOSITE
         use — the accent as ink on a surface).
         It exists because 25 rules across the six stylesheet parts spell this `#fff` inline, which is
         a literal that cannot follow a per-instance brand override. Those are left alone; this is what
         a new component uses so the count stops growing. */
      --on-accent: #ffffff;
      /* --ok and --warn were darkened in 6.70.1: at #2f9e6b and #b5790a they measured 3.37:1 and
         3.68:1 on white, failing WCAG AA for normal text, and both are used as TEXT in ~30 places.
         Hue and saturation are unchanged (152deg / 39deg) — only lightness moved, by the smallest step
         that clears 4.5:1 on the tightest surface they sit on, --panel-2 (#f2edf8), not just on white.
         Measured: --ok 5.49:1 on white / 4.77:1 on --panel-2; --warn 5.54:1 / 4.81:1.
         The dark values were already fine (7.84:1 and 9.44:1) and are untouched. */
      --ok: #237750; --warn: #8e5f08; --err: #c0392b;

      /* NO COLOR REACHES 4.5:1 ON BOTH THE LIGHT AND THE DARK SURFACES (measured 7.203.0). It would
         need luminance <= 0.1833 against #ffffff AND >= 0.2501 against dark --panel-2 (#271f35); that
         window is negative, so this is arithmetic rather than a search anyone can win. 3:1 IS
         reachable — the window is 0.150-0.300, and the three light values above already clear it on
         all four surfaces: --ok 5.49/4.91/3.18/3.41, --warn 5.54/4.96/3.15/3.38, --err
         5.44/4.86/3.21/3.45 (light --panel / light --bg / dark --panel / dark --bg).

         So: an artifact that must work in both themes with ONE palette — a standalone SVG under a
         sandbox CSP, a diagram that gets mailed, anything that cannot read [data-theme] — may carry
         status as a SHAPE but never as colored TEXT. The better move is usually to remove the
         constraint rather than satisfy it: give the artifact its own background and only one surface
         exists, where these values work as text at ~5.5:1. `.ui-figure` exists for that case.

         `@media (prefers-color-scheme)` is NOT the escape hatch. The dark block below is guarded by
         :root:not([data-theme="light"]) precisely so an explicit app setting beats the OS, and a
         standalone document cannot see that attribute — it would track the OS against the user's
         stated choice. */
      --link: #2f5fd0;
      /* Outlook availability, for the calendar's event bars and dots. Categorical rather than semantic —
         "tentative" is not a warning and "free" is not a success — so these are their own tokens instead
         of being bent into --ok/--warn. Hue is fixed per state and only lightness differs by theme.
         Light values clear 4:1 on --panel, comfortably over the 3:1 a non-text indicator needs; the old
         hardcoded values turned out to BE the dark values in three of four cases, which is what the
         audit meant by "chosen for a dark ground". Measured light: 4.16 / 4.08 / 4.53 / 4.09. */
      --cal-tentative: #a4731d; --cal-free: #428c5f; --cal-oof: #b0559e; --cal-elsewhere: #328a8a;
      /* Management priority badge (7.5.0). Categorical, not semantic — a priority of 2 is not a
         "success" and an 8 is not an "error" — so these are their own tokens, the same argument the
         --cal-* availability colors are here for.

         Defined ONCE rather than per theme, and deliberately: each is a fill carrying its own
         foreground, so the pair's contrast does not depend on the page behind it. Measured text-on-fill:
         none 4.83, low 8.09, medium 5.54, high 4.83 — all clear 4.5:1 in both themes because neither
         value moves. Yellow and orange take dark ink for that reason; gray and red take white.

         --prio-ring is the white border the badge is specified to have. It is what separates the badge
         from a dark card; against a light card white-on-white would vanish, so the badge also carries a
         hairline shadow (see .prio-badge) which is what gives it an edge in the light theme. */
      --prio-none: #6b7280; --prio-none-ink: #ffffff;
      --prio-low: #eab308; --prio-low-ink: #1f2430;
      --prio-medium: #f97316; --prio-medium-ink: #1f2430;
      --prio-high: #dc2626; --prio-high-ink: #ffffff;
      --prio-ring: #ffffff;
      /* Detection severity (7.92.0). Categorical like --prio-* and --cal-*, and defined
         ONCE for the same reason: each is a fill carrying its own foreground, so the pair's contrast
         does not depend on the page behind it. Measured ink-on-fill: critical 4.83, high 5.54,
         medium 8.09, low 4.83 — all clear 4.5:1 in both themes because neither value moves.

         The values start equal to the priority ramp deliberately: it is a proven four-step scale with
         measured pairs, and copying it beats inventing colors. They are SEPARATE TOKENS so the two can
         diverge — a detection's severity and a card's priority are different scales that happen to
         agree today, and coupling them would mean retuning one silently moved the other.

         The band comes from the security console's own `severity_label`, never from thresholding the 0-100 score:
         the console's banding is authoritative and a second opinion here would disagree with it.
         `low` and `informational` share a fill on purpose — neither is actionable, and the pill carries
         the word, so color reinforces rather than carries (the same rule --prio-* states). */
      --sev-critical: #dc2626; --sev-critical-ink: #ffffff;
      --sev-high: #f97316;     --sev-high-ink: #1f2430;
      --sev-medium: #eab308;   --sev-medium-ink: #1f2430;
      --sev-low: #6b7280;      --sev-low-ink: #ffffff;
      --scroll: #cabbe3;
      --shadow: 0 1px 2px rgba(47,22,64,.06), 0 4px 14px rgba(47,22,64,.05);
      /* The dim behind a dialog (7.255.0). One value for both themes, like the `.overlay` modals have always
         used: it darkens whatever is behind, and a lighter dim in the dark theme would lift the page instead. */
      --scrim: rgba(0,0,0,.45);
    }
html[data-theme="dark"] {
      color-scheme: dark;
      --brand: #c3a9ec; --brand-deep: #d6c7f4; --brand-bright: #c7a9f0;
      --bg: #14101c; --panel: #1d1727; --panel-2: #271f35; --line: #362c49;
      --text: #ece8f3; --muted: #a79fb8; --accent: #8257cf; --accent-press: #6f44bb;
      /* Overridden below where color-mix is available; this is the no-op fallback, i.e. today's color. */
      --accent-text: var(--accent);
      /* --brand-bright is the light color in this palette, so what sits on it has to be dark.
         Measured: --bg on #c7a9f0 is 9.25 against the 2.03 white was giving. */
      --on-brand-bright: var(--bg);
      /* --brand is light here too: --bg on #c3a9ec measures 9.11 against white's 2.06 (7.410.0). */
      --on-brand: var(--bg);
      /* White on these tones was 2.22 (--ok), 1.85 (--warn), 2.27 (--err) and 2.53 (--muted), all under the 3:1
         floor; --bg measures 8.42, 10.14, 8.26 and 7.40 (7.308.0). */
      --on-tone: var(--bg);
      --ok: #4fc28e; --warn: #e6b85a; --err: #ff8a8a;
      --link: #9ecbff;
      /* Measured on --panel #1d1727: 7.15 / 5.25 / 4.57 / 5.58. */
      --cal-tentative: #d99a2b; --cal-free: #4a9d6b; --cal-oof: #b866a8; --cal-elsewhere: #3aa0a0;
      --scroll: #4a3d63;
      --shadow: 0 1px 2px rgba(0,0,0,.45), 0 4px 16px rgba(0,0,0,.35);
    }

/* Derived rather than a second hex, so a per-instance brand override of --accent carries through: the
   overlay is injected after this file, and --accent-text resolves at use time. 70% accent + 30% white
   measures 6.05 on --panel, 5.46 on --panel-2 (the tightest surface it sits on) and 6.50 on --bg, while
   --accent itself is untouched so white-on-accent fills stay at 4.98. @supports rather than a bare
   declaration because a custom property accepts almost any value at parse time — an unsupported
   color-mix() would be substituted and then fail at use, taking the color with it. */
@supports (color: color-mix(in srgb, red 50%, white)) {
  html[data-theme="dark"] { --accent-text: color-mix(in srgb, var(--accent) 70%, white); }
}
