/* =============================================================================
   AEROSOPHIA DRONE DETECT  ·  "Airspace Ops" palette  ·  airspace-ops.css  v1.0
   -----------------------------------------------------------------------------
   Override layer for the platform design system. It LOADS AFTER
   aerosophia-ds.css (+ aerosophia-components.css, aerosophia-shell.css) and is
   activated with attributes on <html>:

       <html data-palette="airspace" data-theme="dark">   ← operations console
       <html data-palette="airspace" data-theme="light">  ← admin / office

   Rules of this layer
     1. Token NAMES are the platform's (--surface-*, --text-*, --border-*,
        --accent*, --sev-*, --live-*, --risk-*, --status-* …). Only VALUES change,
        so every existing component (.card, .btn, .risk-chip, .status-pill,
        .map-panel, .tool-rail, .modal, .win …) restyles without markup changes.
     2. New DOMAIN tokens are added for drone detection only:
        --canvas, --on-accent, --sev-*-ink, --pred-*, --src-*, --zone-*,
        --track-*, --trail-*, --map-*, --tl-* (DroneStars traffic light),
        --shape-* (severity shape clip-paths), --live-ink, --cov-* (sensor
        coverage: never a severity hue or lime), --aor-* (areas of
        responsibility: never a severity hue or lime, distinct from --cov-*
        and --zone-*).
     3. A short, clearly marked list of SCOPED component adjustments (§4) fixes
        places where the platform hard-codes light-theme literals (#fff on
        accent, light alert boxes …). Nothing outside :root[data-palette=
        "airspace"] is touched.
     4. Token values are literal (no chained var()), matching the platform
        convention that attribute swaps must repaint reliably.

   Comment format on every token:  [--platform-token] rationale
                                   [new]              domain token, rationale
   Keep one token per line: services/console/tests/test_design_css.py reads
   the token blocks line by line and checks them against the DTCG export.

   Palette decision code (interactive review, 2026-09-27):
       SURF:A ACC:A SEV:A PRED:A SRC:B MARK:A MAP:grey SHAPES:ON
       (MAP:grey = neutral charcoal dark / light grey basemap; chrome stays navy)
   ============================================================================= */


/* =============================== 1 · SHARED ================================ */
/* Theme-independent tokens. */
:root[data-palette="airspace"]{
  --font: "Open Sans",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif; /* [--font] unchanged — UI text */
  --font-mono: "JetBrains Mono","SF Mono",Consolas,Menlo,monospace; /* [--font-mono] unchanged — scores, coordinates, times (always tabular-nums) */

  --live-400: #A8E63A;            /* [--live-400] unchanged — rotor-blade lime, LIVE signals only */
  --live-600: #7CB518;            /* [--live-600] unchanged — live dot / ticker fill, on navy chrome */
  --live-soft: rgba(168,230,58,.12); /* [--live-soft] unchanged — live wash */

  /* Severity shapes — the redundant, colour-independent channel. Always shown. */
  --shape-low: circle(50% at 50% 50%);                                        /* [new] ● circle — low */
  --shape-medium: polygon(50% 0,100% 50%,50% 100%,0 50%);                     /* [new] ◆ diamond — medium */
  --shape-high: polygon(50% 3%,100% 94%,0 94%);                               /* [new] ▲ triangle — high */
  --shape-critical: polygon(30% 0,70% 0,100% 30%,100% 70%,70% 100%,30% 100%,0 70%,0 30%); /* [new] ⬣ octagon (stop sign) — critical */

  /* Track / zone stroke patterns (SVG stroke-dasharray values). */
  --trail-coop-dash: none;        /* [new] cooperative trail — solid */
  --trail-noncoop-dash: 6 5;      /* [new] non-cooperative trail — dashed */
  --trail-pred-dash: 2 5;         /* [new] predicted path — violet dotted */
  --zone-nfz-dash: 6 4;           /* [new] no-fly zone outline — dashed */
  --zone-protected-dash: none;    /* [new] protected zone outline — solid */
  --zone-allow-dash: 8 5;         /* [new] allow zone outline — long dash */
  --zone-monitor-dash: 1.5 4;     /* [new] monitor zone outline — dotted (round caps) */
  --zone-control-dash: 12 4 2 4 2 4; /* [new] control area outline — dash-dot-dot, unlike every zone, coverage, area and trail pattern */
  --cov-degraded-dash: 5 4;       /* [new] reduced sensor coverage outline — dashed, shorter than the zone dashes */
  --aor-dash: 10 4 2 4;           /* [new] area of responsibility outline — dash-dot, unlike every zone, coverage and trail pattern */
  --zone-ring-dash: 3 5;          /* [new] protection rings around a protected object (100, 200, 500 m) — short dash, on the 2D and the 3D map */
  --map3d-drop-dash: 2 3;         /* [new] 3D view: drop line from a drone to the ground — fine dots */
  --map3d-open-top-dash: 6 5;     /* [new] 3D view: top of an open height band (no highest altitude) — dashed; a closed band's top is solid */
  --map3d-dur-fly: 1100ms;        /* [new] 3D view: camera flight to a new target (reduced motion: a jump) */
  --map3d-dur-tween: 900ms;       /* [new] 3D view: a drone's glide to its next reported position, and the follow camera (reduced motion: a jump) */
  --live-dur-pulse: 1.6s;         /* [new] one beat of a live pulse: the LIVE dot and an alerting drone's ring (reduced motion: still) */
  --track-dur-turn: 800ms;        /* [new] 2D map: a drone's glyph and heading turning to a new course */
  --err-dur-sweep: 9s;            /* [new] error pages: one turn of the radar sweep (reduced motion: still) */
  --aor-chrome: #A5B4FC;          /* [new] area pill icon on the navy chrome (both themes) — indigo, ≥4.5:1 on the topbar */

  --track-glyph-on-fill: #04121F; /* [new] drone glyph on a filled (cooperative) marker — navy, ≥5:1 on every severity fill (validation: white failed 3:1 on low/medium/high) */
}


/* ========================= 2 · DARK (default) ============================== */
/* Operations console: 24/7 control rooms, low glare. Default whenever
   data-theme is not "light". Extends the platform's navy rail/topbar gradient
   (#0D2235 → #091828 → #050B13) into the workspace. */
:root[data-palette="airspace"]:not([data-theme="light"]){
  color-scheme: dark;

  /* ---- Surfaces ---- */
  --canvas: #050B13;              /* [new] page / map-chrome backdrop = platform --sidebar-bg-bot */
  --surface-0: #0A1726;           /* [--surface-0] cards, panels, modals */
  --surface-1: #0E1E31;           /* [--surface-1] card headers, hovered rows, section fills */
  --surface-2: #16304A;           /* [--surface-2] table headers, tracks of bars, inputs' raised state */
  --surface-sunken: #050B13;      /* [--surface-sunken] wells, code blocks */
  --surface-overlay: rgba(2,6,12,.72); /* [--surface-overlay] modal scrim */
  --surface-inverse: #E7EEF6;     /* [--surface-inverse] inverse tooltip fill */

  /* ---- Text ---- */
  --text-primary: #E7EEF6;        /* [--text-primary] platform topbar foreground */
  --text-secondary: #B8C6D6;      /* [--text-secondary] labels, secondary copy */
  --text-muted: #8FA3B9;          /* [--text-muted] captions, table headers (raised from #7E93AB for contrast) */
  --text-disabled: #5F7690;       /* [--text-disabled] disabled only (exempt from contrast) */
  --text-inverse: #050B13;        /* [--text-inverse] text on --surface-inverse */
  --text-link: #38BDF8;           /* [--text-link] = accent */
  --text-link-hover: #7DD3FC;     /* [--text-link-hover] = accent-hover */

  /* ---- Borders ---- */
  --border-subtle: #1C3550;       /* [--border-subtle] dividers, card outlines (decorative) */
  --border-default: #2A4A68;      /* [--border-default] panels, chips, table rules */
  --border-strong: #4A7196;       /* [--border-strong] form-control boundaries (≥3:1 on surface-0) */
  --border-focus: #38BDF8;        /* [--border-focus] = accent */
  --focus-ring: 0 0 0 2px var(--surface-0), 0 0 0 4px #38BDF8; /* [--focus-ring] accent ring behind a 2 px gap, the box-shadow twin of the :focus-visible outline (≥3:1 on every surface) [REMOVAL-182] 0 0 0 3px rgba(56,189,248,.38) replaced: 2.1–2.3:1 on the surfaces, too faint once it is a control's only indicator */

  /* ---- Accent: radar cyan (logo sky-blue arms) ---- */
  --accent: #38BDF8;              /* [--accent] buttons, selection, links, focus */
  --accent-hover: #7DD3FC;        /* [--accent-hover] lighter on dark (hover = more light) */
  --accent-active: #0EA5E9;       /* [--accent-active] pressed; also accent TEXT on soft fills */
  --accent-soft: rgba(56,189,248,.16);        /* [--accent-soft] selected rows, active nav */
  --accent-soft-strong: rgba(56,189,248,.24); /* [--accent-soft-strong] stronger wash */
  --on-accent: #04121F;           /* [new] text/icon on a filled accent (white fails on #38BDF8) */
  --brand-rgb: 56,189,248;        /* [--brand-rgb] accent rgb triplet, kept for platform parity; no Airspace Ops rule reads it */
  /* brand scale inverted for dark: low steps are dark tints, high steps light */
  --brand-50: #082236;            /* [--brand-50] tint bg (btn-outline hover, alert-primary) */
  --brand-100: #0B2C45;           /* [--brand-100] tint bg */
  --brand-200: #12466A;           /* [--brand-200] tint border */
  --brand-300: #1D6A97;           /* [--brand-300] secondary chart bar */
  --brand-400: #38BDF8;           /* [--brand-400] */
  --brand-500: #38BDF8;           /* [--brand-500] */
  --brand-600: #7DD3FC;           /* [--brand-600] */
  --brand-700: #BAE6FD;           /* [--brand-700] */
  --brand-800: #E0F2FE;           /* [--brand-800] text on brand-50 */
  --brand-900: #F0F9FF;           /* [--brand-900] */

  /* ---- Severity (rule alerts & threat class) — tuned for navy ---- */
  --sev-low: #22C55E;             /* [--sev-low] ● */
  --sev-medium: #F5B301;          /* [--sev-medium] ◆ */
  --sev-high: #FF7A1A;            /* [--sev-high] ▲ */
  --sev-critical: #FF3B4E;        /* [--sev-critical] ⬣ */
  --sev-info: #38BDF8;            /* [--sev-info] = accent */
  --sev-low-ink: #22C55E;        /* [new] severity ink: small text, shapes & line-work (dark: = fill) */
  --sev-medium-ink: #F5B301;     /* [new] */
  --sev-high-ink: #FF7A1A;       /* [new] */
  --sev-critical-ink: #FF3B4E;   /* [new] */

  /* risk chips = severity at 16 % / 45 % / 55 % over surface-0 (literal) */
  --risk-low-bg: #0E332F;      --risk-low-bd: #15653F;      --risk-low-fg: #7BD7A2;      /* [--risk-low-*] */
  --risk-medium-bg: #303020;   --risk-medium-bd: #745D15;   --risk-medium-fg: #EFCE6F;   /* [--risk-medium-*] */
  --risk-high-bg: #312724;     --risk-high-bd: #784421;     --risk-high-fg: #F4AE7D;     /* [--risk-high-*] */
  --risk-critical-bg: #311D2C; --risk-critical-bd: #782738; --risk-critical-fg: #F48C9A; /* [--risk-critical-*] */
  --status-ok-bg: #0E332F;     --status-ok-bd: #15653F;     --status-ok-fg: #7BD7A2;     /* [--status-ok-*] */
  --status-warn-bg: #303020;   --status-warn-bd: #745D15;   --status-warn-fg: #EFCE6F;   /* [--status-warn-*] */
  --status-error-bg: #311D2C;  --status-error-bd: #782738;  --status-error-fg: #F48C9A;  /* [--status-error-*] */

  /* ---- Status (actions) ---- */
  --success-50: #0E332F;          /* [--success-50] dark tint */
  --success-500: #15803D;         /* [--success-500] filled button (white text ≥5:1) */
  --success-600: #166534;         /* [--success-600] hover */
  --warning-50: #303020;          /* [--warning-50] dark tint */
  --warning-500: #F5B301;         /* [--warning-500] = sev-medium */
  --warning-600: #D99E00;         /* [--warning-600] */
  --danger-50: #311D2C;           /* [--danger-50] dark tint */
  --danger-500: #DC2626;          /* [--danger-500] filled Escalate/Delete button (white 4.8:1); map uses --sev-critical */
  --danger-600: #B91C1C;          /* [--danger-600] hover */
  --danger-ink: #F48C9A;          /* [new] text and icon of a destructive action (Add to red list, Escalate): danger, never a severity ink */
  --info-50: #082236;             /* [--info-50] dark tint */
  --info-500: #0369A1;            /* [--info-500] badge fill (white ≥5:1) */
  --info-600: #075985;            /* [--info-600] */

  /* ---- Live ---- */
  --live-ink: #A8E63A;            /* [new] live TEXT / dot on surfaces (dark: = --live-400) */

  /* ---- Prediction (Release 2: DEWS model output) ---- */
  --pred: #A78BFA;                /* [new] violet — "the model says"; used nowhere else */
  --pred-soft: rgba(167,139,250,.12);  /* [new] predicted box fill */
  --pred-border: rgba(167,139,250,.55);/* [new] predicted outline */

  /* ---- Sensor sources: ONE neutral tint, identity by icon + label ---- */
  --src-tint: #B8C6D6;            /* [new] chip text/icon (= text-secondary) */
  --src-bg: rgba(184,198,214,.10);/* [new] chip fill */
  --src-border: rgba(184,198,214,.28); /* [new] chip outline */
  --src-rid: #B8C6D6;             /* [new] Remote ID (kept separate so a source can diverge later) */
  --src-senhive: #B8C6D6;         /* [new] Senhive RF */
  --src-dronestars: #B8C6D6;      /* [new] DroneStars */
  --src-radar: #B8C6D6;           /* [new] Radar */
  --src-aeroscope: #B8C6D6;       /* [new] DJI Aeroscope */

  /* ---- Map (MAP:grey — neutral charcoal basemap; chrome around it stays navy) ---- */
  --map-bg: #1C1F24;              /* [new] land — neutral charcoal, no hue, so severity hues read true */
  --map-block: #23272D;           /* [new] built-up blocks */
  --map-road: #2E333A;            /* [new] roads */
  --map-water: #1A232C;           /* [new] water (faint cool cast) */
  --map-park: #1F2623;            /* [new] parks (faint green cast) */
  --map-label: #9AA0A8;           /* [new] street / place labels — ≥4.5:1 on map-bg and map-block (was #6F87A1) */
  --map-label-bg: rgba(28,31,36,.88); /* [new] pill behind zone labels (= map-bg at 88 %) */
  /* 3D view (R1-31 WP7): sky, buildings, and the lines that tie a drone to the ground; neutral greys except the protected
     building, which takes the protected-zone amber; never lime */
  --map3d-sky: #11161D;           /* [new] 3D view: sky at the zenith — near black, darker than the chrome */
  --map3d-horizon: #2B3038;       /* [new] 3D view: sky at the horizon — neutral grey, a step above map-bg */
  --map3d-fog: #1C1F24;           /* [new] 3D view: distance fog (= map-bg), so far ground fades into the basemap */
  --map3d-building: #3A3F47;      /* [new] 3D view: building — neutral grey, lighter than map-block so walls read */
  --map3d-building-protected: #8C6A12; /* [new] 3D view: building inside a protected object — dark amber, 2:1 on map3d-building, 3:1 on map-bg */
  --map3d-drop: rgba(230,236,244,.55); /* [new] 3D view: drop-line from a drone to the ground under it — ≥3:1 on map-bg */
  --map3d-shadow: rgba(0,0,0,.45);     /* [new] 3D view: a drone's shadow on the ground */
  --map3d-curtain: rgba(184,198,214,.10); /* [new] 3D view: curtain between the target's trail and the ground */
  /* 3D severity inks: the 3D window's drones and trails take these as their --sev-*-ink (= the 2D inks on dark) */
  --map3d-sev-low-ink: #22C55E;      /* [new] 3D view: low severity ink (= sev-low-ink) */
  --map3d-sev-medium-ink: #F5B301;   /* [new] 3D view: medium severity ink (= sev-medium-ink) */
  --map3d-sev-high-ink: #FF7A1A;     /* [new] 3D view: high severity ink (= sev-high-ink) */
  --map3d-sev-critical-ink: #FF3B4E; /* [new] 3D view: critical severity ink (= sev-critical-ink) */
  /* basemap treatments (CSS filter lists) of the 2D tiles; the 3D view turns the same values into its raster paint */
  --map-tiles-grey: saturate(.15) brightness(.93) contrast(.96); /* [new] grey basemap — desaturated, a little darker */
  --map-tiles-grey-invert: invert(1) hue-rotate(180deg) saturate(.15) brightness(1.25) contrast(.82); /* [new] grey basemap without dark tiles (PDOK grijs) — inverted towards map-bg */
  --map-tiles-osm: saturate(.7) brightness(.8); /* [new] OpenStreetMap — dimmed for the dark theme (owner decision 2 Oct 2026, G31: the dimming stays) */
  --map-tiles-sat: brightness(.82); /* [new] satellite — dimmed for the dark theme (owner decision 2 Oct 2026, G31: the dimming stays) */

  /* ---- Zones (rules vocabulary) ---- */
  --zone-nfz-stroke: #FF3B4E;     /* [new] no-fly: critical red, dashed */
  --zone-nfz-fill: rgba(255,59,78,.06);   /* [new] no-fly base wash */
  --zone-nfz-hatch: rgba(255,59,78,.18);  /* [new] no-fly 45° hatch at 18 % */
  --zone-protected-stroke: #F5B301; /* [new] protected: medium amber, solid outline */
  --zone-protected-fill: rgba(245,179,1,.07); /* [new] */
  --zone-allow-stroke: #22C55E;   /* [new] allow: low green, dashed, no fill */
  --zone-monitor-stroke: #38BDF8; /* [new] monitor: accent, dotted, no fill */
  /* control areas: drawn on the live map to raise events for the drones they select; magenta (the chart colour
     of controlled airspace), never a severity hue or lime: the event severity shows on the event itself */
  --zone-control-stroke: #F075F0; /* [new] control area: magenta, dash-dot-dot, ≥3:1 on map-bg, map-block and both veils */
  --zone-control-fill: rgba(240,117,240,.07); /* [new] faint magenta wash inside a control area */

  /* ---- Sensor coverage: what the sensors observe; neutral, never a severity hue or lime ---- */
  --cov-mask: rgba(5,11,19,.34);  /* [new] veil over ground no sensor covers (navy-black at 34 %) */
  --cov-hatch: rgba(184,198,214,.16); /* [new] -45° hatch lines on that veil */
  --cov-edge: #8A96A4;            /* [new] edge of covered ground — solid, ≥3:1 on map-bg, map-block and the veil */
  --cov-degraded-edge: #8A96A4;   /* [new] edge of reduced coverage (sensor degraded) — dashed */
  --cov-lost-edge: #C9D3DE;       /* [new] edge of lost coverage (sensor offline or silent) — solid, heavier */
  --cov-lost-hatch: rgba(201,211,222,.22); /* [new] 45° cross-hatch inside lost coverage */

  /* ---- Areas of responsibility: what a user may access and oversee; never a severity hue or lime ---- */
  --aor-edge: #8FA0FF;            /* [new] outline of an area — indigo dash-dot, ≥3:1 on map-bg, map-block and the dim veil */
  --aor-fill: rgba(143,160,255,.08); /* [new] faint indigo wash inside an area (admin map, legend swatch) */
  --aor-dim: rgba(8,10,28,.45);   /* [new] veil over the ground outside the user's areas (indigo-black at 45 %) */

  /* ---- Tracks ---- */
  --track-halo: #FFFFFF;          /* [new] 2px halo around cooperative markers (white on the charcoal map) */
  --track-hollow-fill: #1C1F24;   /* [new] non-cooperative marker interior (= map-bg) */
  --track-select: #38BDF8;        /* [new] selection ring (= accent) */
  --track-shadow: 0 2px 6px rgba(0,0,0,.55); /* [new] */

  /* ---- DroneStars traffic light ---- */
  --tl-green: #22C55E;            /* [new] green  → low */
  --tl-orange: #FF7A1A;           /* [new] orange → medium / high (lamp uses the high hue) */
  --tl-red: #FF3B4E;              /* [new] red    → critical */
  --tl-off: #2F4E6D;              /* [new] unlit lamp (decorative) */

  /* ---- Elevation (platform dark values) ---- */
  --elev-1: 0 1px 2px rgba(0,0,0,.4);    /* [--elev-1] */
  --elev-2: 0 2px 6px rgba(0,0,0,.5);    /* [--elev-2] */
  --elev-3: 0 6px 18px rgba(0,0,0,.55);  /* [--elev-3] */
  --elev-4: 0 18px 50px rgba(0,0,0,.65); /* [--elev-4] */
}


/* ============================ 3 · LIGHT ==================================== */
/* Admin / office. Platform light surfaces + platform "sky" accent. */
:root[data-palette="airspace"][data-theme="light"]{
  color-scheme: light;

  --canvas: #F8FAFC;              /* [new] page backdrop (= platform --surface-1) */
  --surface-0: #FFFFFF;           /* [--surface-0] platform */
  --surface-1: #F8FAFC;           /* [--surface-1] platform */
  --surface-2: #F1F5F9;           /* [--surface-2] platform */
  --surface-sunken: #F1F5F9;      /* [--surface-sunken] platform */
  --surface-overlay: rgba(15,23,42,.55); /* [--surface-overlay] platform */
  --surface-inverse: #0F172A;     /* [--surface-inverse] platform */

  --text-primary: #1F2A37;        /* [--text-primary] platform */
  --text-secondary: #334155;      /* [--text-secondary] platform */
  --text-muted: #5E6E82;          /* [--text-muted] darkened from platform #64748B (4.34:1 on surface-2 → 4.76:1) */
  --text-disabled: #94A3B8;       /* [--text-disabled] platform */
  --text-inverse: #FFFFFF;        /* [--text-inverse] platform */
  --text-link: #075985;           /* [--text-link] sky 600 */
  --text-link-hover: #0C4A6E;     /* [--text-link-hover] sky 700 */

  --border-subtle: #E4E8EE;       /* [--border-subtle] platform */
  --border-default: #CBD5E1;      /* [--border-default] platform */
  --border-strong: #7A8BA0;       /* [--border-strong] darkened from #94A3B8 so form boundaries reach 3:1 */
  --border-focus: #0369A1;        /* [--border-focus] sky 500 */
  --focus-ring: 0 0 0 2px var(--surface-0), 0 0 0 4px #0369A1; /* [--focus-ring] [REMOVAL-183] 0 0 0 3px rgba(3,105,161,.28) replaced: about 1.5:1 on the surfaces */

  --accent: #0369A1;              /* [--accent] platform "sky" palette */
  --accent-hover: #075985;        /* [--accent-hover] */
  --accent-active: #0C4A6E;       /* [--accent-active] */
  --accent-soft: rgba(3,105,161,.12);        /* [--accent-soft] */
  --accent-soft-strong: rgba(3,105,161,.18); /* [--accent-soft-strong] */
  --on-accent: #FFFFFF;           /* [new] */
  --brand-rgb: 3,105,161;         /* [--brand-rgb] */
  --brand-50: #F0F9FF;  /* [--brand-50] sky */
  --brand-100: #E0F2FE; /* [--brand-100] */
  --brand-200: #BAE6FD; /* [--brand-200] */
  --brand-300: #7DD3FC; /* [--brand-300] */
  --brand-400: #38BDF8; /* [--brand-400] */
  --brand-500: #0369A1; /* [--brand-500] */
  --brand-600: #075985; /* [--brand-600] */
  --brand-700: #0C4A6E; /* [--brand-700] */
  --brand-800: #083B5A; /* [--brand-800] */
  --brand-900: #052E47; /* [--brand-900] */

  --sev-low: #16A34A;             /* [--sev-low] platform ● */
  --sev-medium: #D97706;          /* [--sev-medium] platform warning-600 (not #F59E0B) for contrast ◆ */
  --sev-high: #EA580C;            /* [--sev-high] platform ▲ */
  --sev-critical: #DC2626;        /* [--sev-critical] platform ⬣ */
  --sev-info: #0284C7;            /* [--sev-info] */
  --sev-low-ink: #15803D;        /* [new] severity ink on light: text, shapes, trails, hollow markers */
  --sev-medium-ink: #B45309;     /* [new] */
  --sev-high-ink: #C2410C;       /* [new] */
  --sev-critical-ink: #B91C1C;   /* [new] */

  --risk-low-bg: #D1E7DD;      --risk-low-bd: #A3CFB5;      --risk-low-fg: #0A3622;      /* [--risk-low-*] platform */
  --risk-medium-bg: #FFF3CD;   --risk-medium-bd: #F6DA7A;   --risk-medium-fg: #664D03;   /* [--risk-medium-*] platform */
  --risk-high-bg: #FFD9C2;     --risk-high-bd: #FFB38A;     --risk-high-fg: #8A3500;     /* [--risk-high-*] platform */
  --risk-critical-bg: #F8D7DA; --risk-critical-bd: #F1AEB5; --risk-critical-fg: #58151C; /* [--risk-critical-*] platform */
  --status-ok-bg: #D1E7DD;     --status-ok-bd: #B5E0C2;     --status-ok-fg: #1D683A;     /* [--status-ok-*] platform */
  --status-warn-bg: #FFF5E6;   --status-warn-bd: #F6D28A;   --status-warn-fg: #8A5A00;   /* [--status-warn-*] platform */
  --status-error-bg: #FDE7E9;  --status-error-bd: #F4B9BF;  --status-error-fg: #842029;  /* [--status-error-*] platform */

  --success-50: #DCFCE7;  /* [--success-50] platform */
  --success-500: #15803D; /* [--success-500] darkened from #16A34A (white text 3.3 → 5.0:1) */
  --success-600: #166534; /* [--success-600] */
  --warning-50: #FEF3C7;  /* [--warning-50] platform */
  --warning-500: #F59E0B; /* [--warning-500] platform (badge uses dark text) */
  --warning-600: #D97706; /* [--warning-600] platform */
  --danger-50: #FEE2E2;   /* [--danger-50] platform */
  --danger-500: #DC2626;  /* [--danger-500] platform (backfill #EF4444 gave white 3.8:1) */
  --danger-600: #B91C1C;  /* [--danger-600] */
  --danger-ink: #B91C1C;  /* [new] text and icon of a destructive action (= danger-600, 6.5:1 on white) */
  --info-50: #E0F2FE;     /* [--info-50] platform */
  --info-500: #0369A1;    /* [--info-500] */
  --info-600: #075985;    /* [--info-600] */

  --live-ink: #4D7C0F;            /* [new] live text / dot on LIGHT surfaces (#7CB518 is 2.5:1 on white) */

  --pred: #7C3AED;                /* [new] violet 600 */
  --pred-soft: rgba(124,58,237,.07);   /* [new] */
  --pred-border: rgba(124,58,237,.45); /* [new] */

  --src-tint: #475569;            /* [new] neutral slate */
  --src-bg: rgba(71,85,105,.07);  /* [new] */
  --src-border: rgba(71,85,105,.26); /* [new] */
  --src-rid: #475569;       /* [new] */
  --src-senhive: #475569;   /* [new] */
  --src-dronestars: #475569;/* [new] */
  --src-radar: #475569;     /* [new] */
  --src-aeroscope: #475569; /* [new] */

  --map-bg: #E5E7EB;        /* [new] land — light neutral grey */
  --map-block: #D9DCE1;     /* [new] built-up blocks */
  --map-road: #FFFFFF;      /* [new] roads */
  --map-water: #CDD5DD;     /* [new] water */
  --map-park: #D6DDD3;      /* [new] parks */
  --map-label: #535C68;     /* [new] street / place labels — ≥4.5:1 on map-bg, map-block and map-water (was #7A8594) */
  --map-label-bg: rgba(255,255,255,.92); /* [new] */
  --map3d-sky: #C8D4E0;     /* [new] 3D view: sky at the zenith — pale slate */
  --map3d-horizon: #EEF1F4; /* [new] 3D view: sky at the horizon — near white */
  --map3d-fog: #E5E7EB;     /* [new] 3D view: distance fog (= map-bg) */
  --map3d-building: #C3C8CF; /* [new] 3D view: building — darker than map-block so walls read */
  --map3d-building-protected: #B07A1E; /* [new] 3D view: building inside a protected object — amber, 2:1 on map3d-building, 3:1 on map-bg */
  --map3d-drop: rgba(13,34,53,.6);     /* [new] 3D view: drop-line, ≥3:1 on map-bg */
  --map3d-shadow: rgba(13,34,53,.22);  /* [new] 3D view: a drone's shadow on the ground */
  --map3d-curtain: rgba(13,34,53,.08); /* [new] 3D view: curtain between the target's trail and the ground */
  --map3d-sev-low-ink: #08672E;      /* [new] 3D view: low severity ink — darker than sev-low-ink: ≥3:1 over buildings and volumes */
  --map3d-sev-medium-ink: #904607;   /* [new] 3D view: medium severity ink — ≥3:1 over buildings and volumes */
  --map3d-sev-high-ink: #AC2A12;     /* [new] 3D view: high severity ink — ≥3:1 over buildings and volumes */
  --map3d-sev-critical-ink: #970719; /* [new] 3D view: critical severity ink — ≥3:1 over buildings and volumes; the four keep their colour-blind separation */
  --map-tiles-grey: saturate(.2) brightness(.95) contrast(.94); /* [new] grey basemap */
  --map-tiles-grey-invert: saturate(.2) brightness(.95) contrast(.94); /* [new] = map-tiles-grey: the light theme draws light tiles as they are */
  --map-tiles-osm: none;     /* [new] OpenStreetMap — unchanged in light */
  --map-tiles-sat: none;     /* [new] satellite — unchanged in light */

  --zone-nfz-stroke: #B91C1C;       /* [new] darker ramp step so outline & label pass on light map */
  --zone-nfz-fill: rgba(220,38,38,.05);   /* [new] */
  --zone-nfz-hatch: rgba(220,38,38,.18);  /* [new] 18 % hatch */
  --zone-protected-stroke: #B45309; /* [new] */
  --zone-protected-fill: rgba(217,119,6,.07); /* [new] */
  --zone-allow-stroke: #15803D;     /* [new] */
  --zone-monitor-stroke: #0369A1;   /* [new] */
  --zone-control-stroke: #A21CAF;   /* [new] magenta, ≥3:1 on map-bg, map-block and both veils */
  --zone-control-fill: rgba(162,28,175,.06); /* [new] */

  --cov-mask: rgba(13,34,53,.10);   /* [new] navy veil at 10 % over uncovered ground */
  --cov-hatch: rgba(71,85,105,.22); /* [new] slate hatch lines */
  --cov-edge: #5B6573;              /* [new] ≥3:1 on map-bg, map-block and the veil */
  --cov-degraded-edge: #5B6573;     /* [new] dashed */
  --cov-lost-edge: #1E293B;         /* [new] solid, heavier */
  --cov-lost-hatch: rgba(30,41,59,.22); /* [new] cross-hatch */

  --aor-edge: #3F4DB8;              /* [new] indigo, ≥3:1 on map-bg, map-block and the dim veil */
  --aor-fill: rgba(63,77,184,.07);  /* [new] */
  --aor-dim: rgba(30,36,90,.12);    /* [new] indigo veil at 12 % outside the user's areas */

  --track-halo: #0D2235;          /* [new] navy halo on the light map (white halo is 1.2:1 against #E5E7EB); it is the marker edge, the fill never touches the map */
  --track-hollow-fill: #FFFFFF;     /* [new] white interior so the severity stroke reaches 3:1 */
  --track-select: #0369A1;          /* [new] */
  --track-shadow: 0 1px 4px rgba(13,34,53,.45); /* [new] */

  --tl-green: #16A34A;      /* [new] */
  --tl-orange: #EA580C;     /* [new] */
  --tl-red: #DC2626;        /* [new] */
  --tl-off: #CBD5E1;        /* [new] */

  --elev-1: 0 1px 2px rgba(13,34,53,.06);  /* [--elev-1] platform */
  --elev-2: 0 2px 6px rgba(13,34,53,.10);  /* [--elev-2] platform */
  --elev-3: 0 6px 18px rgba(13,34,53,.13); /* [--elev-3] platform */
  --elev-4: 0 18px 50px rgba(13,34,53,.26),0 2px 6px rgba(13,34,53,.12); /* [--elev-4] platform */
}


/* ================= 4 · SCOPED COMPONENT ADJUSTMENTS ======================== */
/* Only where aerosophia-ds.css hard-codes a light-theme literal. */
:root[data-palette="airspace"] body{background:var(--canvas);}
:root[data-palette="airspace"] .stage{background:var(--canvas);}
:where(:root[data-palette="airspace"]) :focus-visible{outline:2px solid var(--accent); outline-offset:2px; scroll-margin:6px;} /* the default ring, at the weight of :focus-visible alone (0,1,0), so any component focus rule overrides it; the scroll margin keeps a ring drawn outside the box in view when the focus scrolls a list [REMOVAL-181] :root[data-palette="airspace"] :focus-visible replaced: at 0,3,0 it outranked those rules, so rings moved outside their box or doubled a component's box-shadow */

/* #fff on accent → --on-accent (white fails 3:1 on radar cyan) */
:root[data-palette="airspace"] .btn-primary,
:root[data-palette="airspace"] .badge-primary,
:root[data-palette="airspace"] .pager button.on,
:root[data-palette="airspace"] .stepper .step.done .dot,
:root[data-palette="airspace"] .topbar__avatar,
:root[data-palette="airspace"] .rail__avatar,
:root[data-palette="airspace"] .pc-mchip,
:root[data-palette="airspace"] .pc-clip-plane .lbl{color:var(--on-accent);}
:root[data-palette="airspace"] .pc-mchip svg{stroke:var(--on-accent);}
:root[data-palette="airspace"] .switch input:checked + .track::before{background:var(--on-accent);}
:root[data-palette="airspace"] .btn-outline{color:var(--accent);}
:root[data-palette="airspace"] .btn-outline:hover:not(:disabled){background:var(--accent-soft); color:var(--accent);}

/* [REMOVAL-231] Risk-chip shape glyphs moved to §5 helpers, unscoped: severity keeps its shape inside a host page without the airspace palette (G01, theming contract §9) */

/* Severity-tinted header bars on modals and floating windows */
:root[data-palette="airspace"] .modal[data-sev] .modal__hd::before,
:root[data-palette="airspace"] .win[data-sev] .win__hd::before{background:var(--c);}
:root[data-palette="airspace"] .kpi__delta.up{color:var(--sev-low-ink);}
:root[data-palette="airspace"] .kpi__delta.down{color:var(--sev-critical-ink);}
/* live dot: --live-ink on surfaces, platform lime on the navy chrome */
:root[data-palette="airspace"] .livedot{background:var(--live-ink);}
:root[data-palette="airspace"] .topbar .livedot,
:root[data-palette="airspace"] .rail .livedot,
:root[data-palette="airspace"] .live-chip .livedot{background:var(--live-400);}

/* Lime is LIVE-ONLY in Airspace Ops: rail selection ("you are here") uses the
   accent instead of the platform's lime active marker. */
:root[data-palette="airspace"] .rail__item.is-active{background:color-mix(in srgb,var(--accent) 16%,transparent);}
:root[data-palette="airspace"] .rail__item.is-active::after{background:#38BDF8;}
:root[data-palette="airspace"] .rail--x .rail__item.is-active{
  background:linear-gradient(90deg,rgba(56,189,248,.22) 0%,rgba(56,189,248,.09) 45%,transparent 100%);
  box-shadow:inset 3px 0 0 #38BDF8;}
:root[data-palette="airspace"] .rail__inline-item.is-active::before{background:#38BDF8;}
:root[data-palette="airspace"] .form-control,
:root[data-palette="airspace"] .form-select,
:root[data-palette="airspace"] .searchbox{border-color:var(--border-strong);}

/* Dark-only: platform literals that assume a light page */
:root[data-palette="airspace"]:not([data-theme="light"]) .status-pill:not([data-status]),
:root[data-palette="airspace"]:not([data-theme="light"]) .risk-chip:not([data-risk]){background:var(--surface-2); color:var(--text-secondary);}
:root[data-palette="airspace"]:not([data-theme="light"]) .switch input:not(:checked) + .track{background:var(--border-default);}
:root[data-palette="airspace"]:not([data-theme="light"]) .map-statusbar{background:color-mix(in srgb,var(--surface-0) 90%,transparent);}
:root[data-palette="airspace"]:not([data-theme="light"]) .thin-scroll::-webkit-scrollbar-thumb{background:#2A4A68; background-clip:content-box;}
:root[data-palette="airspace"]:not([data-theme="light"]) .alert-primary{background:var(--brand-50); border-color:var(--brand-200); color:var(--brand-800);}
:root[data-palette="airspace"]:not([data-theme="light"]) .alert-success{background:var(--risk-low-bg); border-color:var(--risk-low-bd); color:var(--risk-low-fg);}
:root[data-palette="airspace"]:not([data-theme="light"]) .alert-warning{background:var(--risk-medium-bg); border-color:var(--risk-medium-bd); color:var(--risk-medium-fg);}
:root[data-palette="airspace"]:not([data-theme="light"]) .alert-danger{background:var(--risk-critical-bg); border-color:var(--risk-critical-bd); color:var(--risk-critical-fg);}
:root[data-palette="airspace"]:not([data-theme="light"]) .alert-info{background:var(--info-50); border-color:var(--brand-200); color:var(--brand-700);}
:root[data-palette="airspace"]:not([data-theme="light"]) .modal__icon.is-danger{background:var(--risk-critical-bg); color:var(--risk-critical-fg);}


/* ======================= 5 · DOMAIN HELPER CLASSES ========================= */
/* Colour rule: large FILLS use --sev-*; small marks, text and line-work use
   --sev-*-ink (identical in dark; one step darker in light so it holds 3:1 on
   the light map and 4.5:1 as text). */

/* ---- 5.1 Severity shape + text ------------------------------------------ */
/* <span class="sev-shape" data-sev="high"></span>  — use next to ANY severity colour */
.sev-shape{display:inline-block; width:.72em; height:.72em; flex:0 0 auto; background:currentColor; vertical-align:-.04em;}
.sev-shape[data-sev="low"]{clip-path:var(--shape-low); background:var(--sev-low-ink);}
.sev-shape[data-sev="medium"]{clip-path:var(--shape-medium); background:var(--sev-medium-ink);}
.sev-shape[data-sev="high"]{clip-path:var(--shape-high); background:var(--sev-high-ink); width:.8em; height:.78em;}
.sev-shape[data-sev="critical"]{clip-path:var(--shape-critical); background:var(--sev-critical-ink);}
/* Severity ALWAYS carries its shape: risk chips get a shape glyph for free, with or without the airspace palette (a widget on a host page). */
.risk-chip[data-risk]::before{content:""; display:inline-block; width:.62rem; height:.62rem; margin:0 .38rem 0 -.1rem; vertical-align:-.04rem;}
.risk-chip[data-risk="low"]::before{background:var(--sev-low-ink); clip-path:var(--shape-low);}
.risk-chip[data-risk="medium"]::before{background:var(--sev-medium-ink); clip-path:var(--shape-medium);}
.risk-chip[data-risk="high"]::before{background:var(--sev-high-ink); clip-path:var(--shape-high);}
.risk-chip[data-risk="critical"]::before{background:var(--sev-critical-ink); clip-path:var(--shape-critical);}
.sev-ink[data-sev="low"]{color:var(--sev-low-ink);}
.sev-ink[data-sev="medium"]{color:var(--sev-medium-ink);}
.sev-ink[data-sev="high"]{color:var(--sev-high-ink);}
.sev-ink[data-sev="critical"]{color:var(--sev-critical-ink);}
.sev-bar[data-sev]{box-shadow:inset 4px 0 0 var(--c);}   /* left severity edge (toasts, rows) */

/* ---- 5.2 Track markers (HTML) ------------------------------------------- */
/* <div class="trk" data-sev="high" data-coop="true"><svg class="trk__glyph">…</svg><span class="trk__badge"></span></div>
   cooperative (Remote ID / RF identity) = SOLID; non-cooperative (radar only) = HOLLOW + dashed trail */
.trk{--c:var(--sev-medium); position:relative; width:30px; height:30px; border-radius:9px; display:flex; align-items:center; justify-content:center;
  background:var(--c); border:2px solid var(--track-halo); color:var(--track-glyph-on-fill); box-shadow:var(--track-shadow);}
.trk[data-sev="low"]{--c:var(--sev-low);} .trk[data-sev="medium"]{--c:var(--sev-medium);}
.trk[data-sev="high"]{--c:var(--sev-high);} .trk[data-sev="critical"]{--c:var(--sev-critical);}
.trk{--ink:var(--sev-medium-ink);}
.trk[data-sev="low"]{--ink:var(--sev-low-ink);} .trk[data-sev="medium"]{--ink:var(--sev-medium-ink);}
.trk[data-sev="high"]{--ink:var(--sev-high-ink);} .trk[data-sev="critical"]{--ink:var(--sev-critical-ink);}
.trk[data-coop="false"]{background:var(--track-hollow-fill); border:2.5px dashed var(--ink); color:var(--ink);}
.trk__glyph{width:20px; height:20px; fill:currentColor; display:block;}
/* the badge's severity shape: 13 px (12 px circle), legible without a word beside it (DS-T06) */
.trk__badge{position:absolute; top:-9px; right:-9px; width:18px; height:18px; border-radius:var(--radius-round); background:var(--track-hollow-fill);
  display:flex; align-items:center; justify-content:center; box-shadow:0 0 0 1px rgba(0,0,0,.28);}
.trk__badge::after{content:""; width:13px; height:13px; background:var(--ink);}
.trk[data-sev="low"] .trk__badge::after{clip-path:var(--shape-low); width:12px; height:12px;}
.trk[data-sev="medium"] .trk__badge::after{clip-path:var(--shape-medium);}
.trk[data-sev="high"] .trk__badge::after{clip-path:var(--shape-high); margin-top:-1px;}
.trk[data-sev="critical"] .trk__badge::after{clip-path:var(--shape-critical);}
.trk.is-selected{outline:2px dashed var(--track-select); outline-offset:5px;}
.trk--pulse::before{content:""; position:absolute; inset:-3px; border-radius:11px; animation:aso-trk-pulse var(--live-dur-pulse) ease-out infinite; pointer-events:none;}
@keyframes aso-trk-pulse{0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--c) 55%,transparent);}70%{box-shadow:0 0 0 14px transparent;}100%{box-shadow:0 0 0 0 transparent;}}
@media (prefers-reduced-motion: reduce){ .trk--pulse::before{animation:none;} }
/* score / label chip under a marker */
.trk-chip{display:inline-flex; align-items:center; gap:6px; padding:2px 9px 2px 7px; border-radius:var(--radius-pill); white-space:nowrap;
  background:var(--surface-0); border:1px solid var(--border-default); box-shadow:var(--elev-2);
  font-family:var(--font-mono); font-size:11px; font-weight:600; color:var(--text-primary); font-variant-numeric:tabular-nums;}
.trk-chip .cls{font-family:var(--font); font-size:9.5px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--text-muted);}

/* ---- 5.3 Trails (SVG paths) --------------------------------------------- */
.trail{fill:none; stroke:var(--c,var(--sev-medium)); stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round;}
.trail[data-sev="low"]{--c:var(--sev-low-ink);} .trail[data-sev="medium"]{--c:var(--sev-medium-ink);}
.trail[data-sev="high"]{--c:var(--sev-high-ink);} .trail[data-sev="critical"]{--c:var(--sev-critical-ink);}
.trail--coop{stroke-dasharray:var(--trail-coop-dash); opacity:.85;}
.trail--noncoop{stroke-dasharray:var(--trail-noncoop-dash);}
.trail--predicted{stroke:var(--pred); stroke-dasharray:var(--trail-pred-dash); stroke-width:2;}

/* ---- 5.4 Zones (SVG shapes + legend swatches) --------------------------- */
/* NFZ hatch needs this pattern once per SVG document:
   <pattern id="aso-hatch-nfz" width="8" height="8" patternTransform="rotate(45)" patternUnits="userSpaceOnUse">
     <rect width="8" height="8" style="fill:var(--zone-nfz-fill)"/><rect width="3" height="8" style="fill:var(--zone-nfz-hatch)"/></pattern> */
.zone{stroke-width:1.8; vector-effect:non-scaling-stroke; stroke-linecap:round;}
.zone--nfz{stroke:var(--zone-nfz-stroke); stroke-dasharray:var(--zone-nfz-dash); fill:url(#aso-hatch-nfz) var(--zone-nfz-fill);}
.zone--protected{stroke:var(--zone-protected-stroke); stroke-dasharray:var(--zone-protected-dash); fill:var(--zone-protected-fill);}
.zone--allow{stroke:var(--zone-allow-stroke); stroke-dasharray:var(--zone-allow-dash); fill:none;}
.zone--monitor{stroke:var(--zone-monitor-stroke); stroke-dasharray:var(--zone-monitor-dash); fill:none; stroke-width:2;}
.zone--control{stroke:var(--zone-control-stroke); stroke-dasharray:var(--zone-control-dash); fill:var(--zone-control-fill); fill-opacity:1; stroke-width:2;}
.zone--control.is-sel{stroke-width:3.5;}
.zone-label{font-family:var(--font-mono); font-size:10px; font-weight:600; letter-spacing:.04em;}
.zone-label--nfz{fill:var(--zone-nfz-stroke);} .zone-label--protected{fill:var(--zone-protected-stroke);}
.zone-label--allow{fill:var(--zone-allow-stroke);} .zone-label--monitor{fill:var(--zone-monitor-stroke);}
.zone-label--control{fill:var(--zone-control-stroke);}
.zone-swatch{display:inline-block; width:18px; height:12px; border-radius:2px; flex:0 0 18px; vertical-align:middle;}
.zone-swatch[data-zone="nfz"]{border:1.5px dashed var(--zone-nfz-stroke);
  background:repeating-linear-gradient(45deg,var(--zone-nfz-hatch) 0 2px,var(--zone-nfz-fill) 2px 5px);}
.zone-swatch[data-zone="protected"]{border:1.5px solid var(--zone-protected-stroke); background:var(--zone-protected-fill);}
.zone-swatch[data-zone="allow"]{border:1.5px dashed var(--zone-allow-stroke);}
.zone-swatch[data-zone="monitor"]{border:2px dotted var(--zone-monitor-stroke);}
.zone-swatch[data-zone="control"]{border:2px dashed var(--zone-control-stroke); background:var(--zone-control-fill);}

/* ---- 5.5 Sensor-source chips (neutral tint, identity = icon + label) ----- */
/* <span class="src-chip" data-src="rid"><svg>…</svg>Remote ID</span> ; add .is-off when the source is not reporting */
.src-chip{display:inline-flex; align-items:center; gap:5px; height:22px; padding:0 var(--space-2) 0 6px; border-radius:6px; white-space:nowrap;
  font-size:11px; font-weight:700; color:var(--src-tint); background:var(--src-bg); border:1px solid var(--src-border);}
.src-chip svg{width:13px; height:13px; stroke:currentColor; fill:none; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; flex:0 0 13px;}
.src-chip[data-src="rid"]{color:var(--src-rid);} .src-chip[data-src="senhive"]{color:var(--src-senhive);}
.src-chip[data-src="dronestars"]{color:var(--src-dronestars);} .src-chip[data-src="radar"]{color:var(--src-radar);}
.src-chip[data-src="aeroscope"]{color:var(--src-aeroscope);}
.src-chip.is-off{color:var(--text-muted); background:transparent; border-style:dashed;}
.src-chip--icon{width:22px; padding:0; justify-content:center;}

/* ---- 5.6 Prediction (never without its source label) --------------------- */
/* <span class="pred-tag">Predicted 0.91<span class="pred-tag__src">DEWS model v2</span></span> */
.pred-tag{display:inline-flex; align-items:center; gap:6px; height:20px; padding:0 var(--space-2); border-radius:var(--radius-pill); white-space:nowrap;
  font-size:10px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--pred); border:1px solid var(--pred-border); background:var(--pred-soft);}
.pred-tag::before{content:""; width:7px; height:7px; background:currentColor; clip-path:var(--shape-medium); transform:scale(1.1);}
.pred-tag__src{font-weight:600; letter-spacing:.02em; text-transform:none; color:var(--text-secondary); padding-left:6px; border-left:1px solid var(--pred-border);}
.pred-tag:not(:has(.pred-tag__src))::after{content:"⚠ source missing"; color:var(--sev-critical-ink); text-transform:none;} /* dev-time lint */
.pred-box{border:1px solid var(--pred-border); background:var(--pred-soft); border-radius:var(--radius-md); padding:10px var(--space-3);}

/* ---- 5.7 DroneStars traffic light --------------------------------------- */
/* <span class="tl" data-tl="orange"><i></i><i></i><i></i>Orange</span>  green→low · orange→medium/high · red→critical */
.tl{display:inline-flex; align-items:center; gap:3px; padding:3px 9px 3px 5px; border-radius:var(--radius-pill);
  background:var(--surface-2); border:1px solid var(--border-default); font-size:11px; font-weight:700; color:var(--text-secondary); white-space:nowrap;}
.tl i{display:inline-block; width:10px; height:10px; background:var(--tl-off); flex:0 0 10px;}
.tl i:nth-child(1){clip-path:var(--shape-critical);} .tl i:nth-child(2){clip-path:var(--shape-high);} .tl i:nth-child(3){clip-path:var(--shape-low); margin-right:var(--space-1);}
.tl[data-tl="red"] i:nth-child(1){background:var(--tl-red);}
.tl[data-tl="orange"] i:nth-child(2){background:var(--tl-orange);}
.tl[data-tl="green"] i:nth-child(3){background:var(--tl-green);}
.tl--compact{padding:3px 3px 3px 5px;}

/* ---- 5.8 Live ------------------------------------------------------------ */
.live-ink{color:var(--live-ink); font-family:var(--font-mono); font-variant-numeric:tabular-nums;}

/* ---- 5.9 Sensor coverage (SVG shapes + legend swatches) ----------------- */
/* What the sensors can observe. It never triggers events and never grants access, so it keeps its own
   neutral family: never a severity hue, never lime. The hatches need these patterns once per SVG document:
   <pattern id="aso-hatch-cov" width="10" height="10" patternTransform="rotate(-45)" patternUnits="userSpaceOnUse">
     <rect width="10" height="10" class="…fill (--cov-mask)"/><rect width="1.5" height="10" class="…line (--cov-hatch)"/></pattern>
   <pattern id="aso-hatch-cov-lost" width="7" height="7" patternTransform="rotate(45)" patternUnits="userSpaceOnUse">
     <rect width="1.5" height="7" class="…line (--cov-lost-hatch)"/></pattern>
   The mask is one path: a world ring with the covered ground cut out (fill-rule evenodd). */
.cov{vector-effect:non-scaling-stroke; stroke-linecap:round; stroke-linejoin:round;}
.cov--mask{stroke:none; fill:url(#aso-hatch-cov) var(--cov-mask); fill-opacity:1; fill-rule:evenodd;}
.cov--covering{stroke:var(--cov-edge); stroke-width:1.25; fill:none;}
.cov--degraded{stroke:var(--cov-degraded-edge); stroke-width:1.5; stroke-dasharray:var(--cov-degraded-dash); fill:none;}
.cov--lost{stroke:var(--cov-lost-edge); stroke-width:2; fill:url(#aso-hatch-cov-lost) transparent; fill-opacity:1;}
.cov-swatch{display:inline-block; width:18px; height:12px; border-radius:2px; flex:0 0 18px; vertical-align:middle;}
.cov-swatch[data-cov="outside"]{border:1.25px solid var(--cov-edge);
  background:repeating-linear-gradient(-45deg,var(--cov-hatch) 0 1.5px,var(--cov-mask) 1.5px 5px);}
.cov-swatch[data-cov="degraded"]{border:1.5px dashed var(--cov-degraded-edge);}
.cov-swatch[data-cov="lost"]{border:2px solid var(--cov-lost-edge);
  background:repeating-linear-gradient(45deg,var(--cov-lost-hatch) 0 1.5px,transparent 1.5px 4px),
    repeating-linear-gradient(-45deg,var(--cov-hatch) 0 1.5px,var(--cov-mask) 1.5px 5px);}

/* ---- 5.10 Areas of responsibility (SVG shapes + legend swatches) -------- */
/* What a user may access and oversee. An area never triggers events (zones do) and is not what the sensors
   observe (coverage), so it keeps its own family: never a severity hue, never lime. The dim is one path: a
   world ring with the user's areas cut out (fill-rule evenodd). Legend swatches are 18 × 12 SVGs:
   <svg class="aor-swatch" viewBox="0 0 18 12"><rect class="aor aor--fill" x="1" y="1" width="16" height="10"/></svg>
   <svg class="aor-swatch" viewBox="0 0 18 12"><rect class="aor-swatch__ground" width="18" height="12"/>
     <rect class="aor aor--dim" width="11" height="12"/><path class="aor aor--edge" d="M11 0V12"/></svg> */
.aor{vector-effect:non-scaling-stroke; stroke-linecap:round; stroke-linejoin:round;}
.aor--edge{stroke:var(--aor-edge); stroke-width:2; stroke-dasharray:var(--aor-dash); fill:none;}
.aor--fill{stroke:var(--aor-edge); stroke-width:2; stroke-dasharray:var(--aor-dash); fill:var(--aor-fill); fill-opacity:1;}
.aor--fill.is-sel{stroke-width:3.5;}
.aor--off{opacity:.55;}
.aor--dim{stroke:none; fill:var(--aor-dim); fill-opacity:1; fill-rule:evenodd;}
.aor-swatch{display:inline-block; width:18px; height:12px; flex:0 0 18px; vertical-align:middle; overflow:visible;}
.aor-swatch__ground{fill:var(--map-bg);}
