/* ==========================================================================
   AlienView design system — "control-room at night" — TOKENS
   Portal redesign phase 1A + UX overhaul U1. Single source of design tokens.

   STYLESHEET SPLIT (U1)
   ---------------------
   The system now ships as three stylesheets, loaded in this order from
   dashboard/_base.html so the cascade + var resolution stay predictable:
     1. theme.css       — this file: tokens (:root vars), theming, data-status
                          indirection, and the reduced-motion global.
     2. components.css  — the concrete component classes (card, pill, stat,
                          check, button, tab bar, sheet, …) + the `.ui-app`
                          scope and the phone-nav global.
     3. patterns.css    — the U1 instrumentation kit (notice, page/kpi headers,
                          sparkline, meter, timeline, stages, age, queue row,
                          segmented, icon).
   It was split when the single file passed ~500 lines; each `{% static %}`
   include is version-stamped for cache-busting and covered by the
   static-resolution tripwire test (dashboard/tests/test_static_assets.py).

   NAMESPACING
   -----------
   Every token and class is prefixed `--ui-*` / `.ui-*`, with exactly TWO
   deliberate unprefixed globals (documented so the namespacing claim stays
   honest):

     1. `header nav { display: none }` at <=720px — the IA change itself: the
        phone tab bar REPLACES the 20-link header nav, so the legacy selector
        must be reached. Lives in components.css (with the tab bar it enables).
        Known side effect: communications/notifications.js injects its
        unread-count bell pill into that header nav, so the badge is hidden on
        phones for now (documented follow-up for the reskin sweep).
     2. The `prefers-reduced-motion` universal freeze at the bottom of THIS
        file — it intentionally spans the whole page, so it also stops legacy
        animations (the live page's heartbeat pip, the alarm-tile pulse):
        exactly what a reduced-motion user asked for. State is still conveyed
        by colour/text/icon, never by motion alone.

   Otherwise, the legacy templates each still carry their own `<style>` block
   keyed on the old unprefixed `:root` tokens (`--bg`, `--surface`, `--accent`,
   …) defined in dashboard/_base.html. Namespacing lets these load globally
   WITHOUT restyling those pages — the app-wide reskin sweep (U3) that retires
   the legacy tokens is a deliberate follow-up. New surfaces opt in by using
   `.ui-*` classes inside a `.ui-app` / `[data-ui]` scope.

   THEME
   -----
   Dark-first (night shifts). Tokens resolve to dark by default at `:root`.
   A light theme is available two ways, both at token level:
     * explicit  — `<html data-theme="light">`
     * automatic — `prefers-color-scheme: light` when no explicit `data-theme`
   The automatic branch is deliberate: the brief's dark-first mandate is about
   the DEFAULT (no preference expressed -> dark, inverting the usual
   light-default web), not about overriding a user's explicit OS-level light
   preference. A deployment that wants operator surfaces locked dark regardless
   of OS setting pins `<html data-theme="dark">`.
   Status hues (crit/high/med/low/ok) map 1:1 to the alarm severities and are
   never used decoratively.
   ========================================================================== */

:root {
  /* --- Surfaces & text (dark-first) --- */
  --ui-bg: #0f1420;
  --ui-surface: #1a2130;
  --ui-surface-2: #232b3d;
  --ui-border: #2e3850;
  --ui-text: #e8ecf4;
  --ui-muted: #8b95ab;
  --ui-accent: #4f8ef7;
  --ui-accent-ink: #ffffff; /* text on an accent fill */

  /* Accent-tinted surface — the "needs YOUR action" wash (queue rows, notices).
     Derived from the accent + surface so it re-tints per theme automatically.
     Kept subtle enough that --ui-text still clears 4.5:1 on top. */
  --ui-tint: color-mix(in srgb, var(--ui-accent) 14%, var(--ui-surface));
  /* Muted text that clears AA (4.5:1) for 13px meta ON the --ui-tint wash.
     Plain --ui-muted (#8b95ab) only reaches 4.39:1 on the dark tint, so queue
     meta uses this brighter step in dark (measured 4.84:1); light keeps its
     regular muted, which already clears 4.9:1 on the light tint. */
  --ui-tint-muted: #939db2;

  /* --- Status (1:1 with alarm severities crit/high/med/low + ok) --- */
  --ui-crit: #f87171;
  --ui-high: #fb923c;
  --ui-med: #fbbf24;
  --ui-low: #38bdf8;
  --ui-ok: #4ade80;
  /* ink used on top of a solid status fill (dark text reads on these hues) */
  --ui-status-ink: #0f1420;

  /* --- Type scale (px): micro 11, meta 13, body 15, title 17, section 22, gauge 34 --- */
  --ui-fs-micro: 11px; /* count badges, tick labels, stage captions */
  --ui-fs-meta: 13px;
  --ui-fs-body: 15px;
  --ui-fs-title: 17px;
  --ui-fs-section: 22px;
  --ui-fs-gauge: 34px;
  --ui-lh: 1.45;

  /* --- 4px spacing grid --- */
  --ui-sp-1: 4px;
  --ui-sp-2: 8px;
  --ui-sp-3: 12px;
  --ui-sp-4: 16px;
  --ui-sp-5: 24px;
  --ui-sp-6: 32px;

  /* --- Geometry --- */
  --ui-radius: 12px;
  --ui-radius-sm: 8px;
  --ui-touch: 48px; /* minimum glove-friendly hit target */
  --ui-edge: 4px;   /* card status left-edge width */
  --ui-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
  --ui-font: ui-sans-serif, -apple-system, system-ui, "Segoe UI", Roboto, sans-serif;

  /* --- Stacking order (one scale so overlays never fight ad-hoc z-indexes) --- */
  --ui-z-base: 1;
  --ui-z-nav: 40;     /* fixed bottom tab bar */
  --ui-z-overlay: 44; /* sheet backdrop */
  --ui-z-sheet: 45;   /* bottom sheet panel */
  --ui-z-toast: 60;   /* transient status, above everything */

  /* --- Motion (only on state change; overridden by reduced-motion) --- */
  --ui-motion: 160ms ease;
}

/* Light theme — explicit opt-in. Brand-continuous with the legacy light UI.
   `--ui-muted` is bumped darker than the legacy #6b7280 (~4.5:1 on white, on
   the edge) to a comfortable ~5.3:1 so meta text stays AA on light surfaces. */
:root[data-theme="light"] {
  --ui-bg: #f7f8fa;
  --ui-surface: #ffffff;
  --ui-surface-2: #f2f4f8;
  --ui-border: #dfe3ea;
  --ui-text: #1a1f2e;
  --ui-muted: #5b6470;
  --ui-accent: #2563eb;
  --ui-accent-ink: #ffffff;
  --ui-tint-muted: #5b6470;
  --ui-crit: #b91c1c;
  --ui-high: #b45309;
  --ui-med: #92670a;
  --ui-low: #0369a1;
  --ui-ok: #15803d;
  --ui-status-ink: #ffffff;
  --ui-shadow: 0 4px 14px rgba(16, 24, 40, 0.08);
}

/* Light theme — automatic, only when the user hasn't pinned a theme. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --ui-bg: #f7f8fa;
    --ui-surface: #ffffff;
    --ui-surface-2: #f2f4f8;
    --ui-border: #dfe3ea;
    --ui-text: #1a1f2e;
    --ui-muted: #5b6470;
    --ui-accent: #2563eb;
    --ui-accent-ink: #ffffff;
    --ui-tint-muted: #5b6470;
    --ui-crit: #b91c1c;
    --ui-high: #b45309;
    --ui-med: #92670a;
    --ui-low: #0369a1;
    --ui-ok: #15803d;
    --ui-status-ink: #ffffff;
    --ui-shadow: 0 4px 14px rgba(16, 24, 40, 0.08);
  }
}

/* Map a `data-status` token to a single `--_s` colour used by cards/pills/tiles
   so a status only needs stating once per element. */
[data-status="crit"] { --_s: var(--ui-crit); }
[data-status="high"] { --_s: var(--ui-high); }
[data-status="med"]  { --_s: var(--ui-med); }
[data-status="low"]  { --_s: var(--ui-low); }
[data-status="ok"]   { --_s: var(--ui-ok); }
[data-status="none"] { --_s: var(--ui-border); }

/* ==========================================================================
   Motion: only on state change, and never for reduced-motion users. This is
   one of the two deliberate unprefixed globals (see the header note).
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
