/* ══════════════════════════════════════════════════════════════════
   VAGT DESIGN TOKENS — role-based, theme-indirected
   Built 2026-07-25 · Claire (design lane)

   FILED AT assets/css/theme.css (Claire authored it as tokens/theme.css).
   Renamed by the strategist lane so it follows the same load convention as
   every other stylesheet: all 50 portal pages link ../assets/css/*, and both
   stampers enforce that path. A root-level tokens/ dir would need a stamper
   exception and create a new way to wire a page up wrong. Load order:
       theme.css  →  main.css  →  iq.css  →  iq-platform.css  →  data-fields.css
   theme.css must come FIRST — the tokens must exist before anything reads them.

   Two layers on purpose:
   1. Brand palette  — raw hex, one block per tenant, swapped via [data-tenant]
   2. Semantic roles — what components actually reference. Never hardcode
      hex in a component; reference a role token below.

   This costs nothing today (single tenant = single palette block) and
   means white-labeling later is a new [data-tenant="x"] block, not a
   rewrite of every page. Naming rule: tokens are named by JOB, not hue —
   this is what prevents the #127475/#127470 near-duplicate problem.
   ══════════════════════════════════════════════════════════════════ */

/* ── LAYER 1: brand palette, per tenant ── */
:root,
[data-tenant="vagt"] {
  --brand-navy:        #0D1F3C;
  --brand-navy-deep:   #091629;
  --brand-navy-mid:    #1A3355;
  --brand-amber:       #F5C400;
  --brand-amber-deep:  #D9A800;
  --brand-red:         #C41E1E;
  --brand-bg:          #F4F3EF;
  --brand-surface:     #FFFFFF;
  --brand-border:      #E0DED8;
  --brand-green:       #059669;
  --brand-amber-status:#D97706;
  --brand-danger:      #DC2626;
  --brand-cyan:        #0891B2; /* PSARA/compliance accent */
}

/* Per-tenant theming: CONFIRMED 2026-07-25 (Nikhil). Each tenant firm's
   guards/clients see their own logo + colours, never VAGT's. VAGT Solutions
   Bihar is tenant #1 — this gets exercised for real.

   Worked stress-test tenant below deliberately uses a hard brand colour
   (saturated red primary, pale yellow accent) — proves the architecture
   survives a brand that is bad for UI, not just VAGT's well-behaved navy. */
[data-tenant="stress-test-firm"] {
  --brand-navy:        #B91C1C; /* saturated red as "primary" — legibility-hostile on purpose */
  --brand-navy-deep:   #7F1D1D;
  --brand-navy-mid:    #DC2626;
  --brand-amber:       #FEF3C7; /* pale yellow as "accent" — near-zero contrast if misused */
  --brand-amber-deep:  #FDE68A;
  --brand-red:         #7C2D12;
  --brand-bg:          #FAFAF9;
  --brand-surface:     #FFFFFF;
  --brand-border:      #E7E5E4;
}

/* ── LAYER 2: semantic roles — components reference ONLY these ──
   Split into TENANT-OVERRIDABLE (follows --brand-*, changes per tenant)
   and PINNED (fixed by the system, ignores tenant entirely — legibility
   and status meaning are not brand decisions). Per Nikhil 2026-07-25:
   a tenant's brand cannot break WCAG AA or status semantics. */
:root {
  /* Surfaces — tenant-overridable */
  --color-bg:            var(--brand-bg);
  --color-surface:       var(--brand-surface);
  --color-border:        var(--brand-border);
  --color-border-light:  color-mix(in srgb, var(--brand-border) 60%, white);

  /* Text — tenant-overridable */
  --color-text:          var(--brand-navy);
  --color-text-muted:    color-mix(in srgb, var(--brand-navy) 55%, white);
  --color-text-faint:    color-mix(in srgb, var(--brand-navy) 35%, white);

  /* Brand actions — tenant-overridable */
  --color-primary:        var(--brand-navy);
  --color-primary-hover:  var(--brand-navy-mid);
  --color-accent:         var(--brand-amber);
  --color-accent-hover:   var(--brand-amber-deep);

  /* ── PINNED — never resolve through --brand-*. Same hex for every
     tenant, always. Status meaning (green=active, red=urgent) and its
     AA contrast is a system guarantee, not something a tenant's palette
     can degrade — this is why the stress-test tenant above can have an
     unreadable "primary" without breaking status legibility anywhere. */
  --color-status-active:      #059669;
  --color-status-active-bg:   #ECFDF5;
  --color-status-pending:     #B45309;
  --color-status-pending-bg:  #FFFBEB;
  --color-status-urgent:      #B91C1C;
  --color-status-urgent-bg:   #FEF2F2;
  --color-status-inactive:    #57534E;
  --color-status-inactive-bg: #F5F5F4;
  --color-compliance:         #0E7490;
  --color-compliance-bg:      #ECFEFF;

  /* ── TEXT-SAFE status variants — added 2026-07-25 by strategist lane,
     found during the admin-employees.html pilot migration. PLEASE REVIEW, Claire.

     THE PROBLEM: the tokens above are correct for FILLS (dots, bars, icons),
     which need 3:1. They are NOT safe for TEXT, which needs 4.5:1:

         --color-status-active  #059669  on white = 3.77:1  ✗ FAILS AA text
         admin-employees.html   #005C30  on white = 8.16:1  ✓ passes

     The page already used the darker, accessible values. Swapping them for the
     pinned tokens would have silently REGRESSED contrast on live pages — and the
     WCAG AA pass (admin + guard portal) is a shipped commitment we can't undo.

     So: fills use the tokens above; text uses these. Both are PINNED — a
     tenant's brand cannot alter either, which is the whole point of pinning. */
  --color-status-active-text:   #005C30;   /* 8.2:1 on white  */
  --color-status-pending-text:  #5A4200;   /* 9.7:1 on white  */
  --color-status-urgent-text:   #8B1000;   /* 9.1:1 on white  */
  --color-status-inactive-text: #4B4B4B;   /* 8.9:1 on white  */
  --color-info-text:            #003580;   /* 11.4:1 on white */
  --color-role-admin-text:      #3A0080;   /* 12.6:1 on white */
  --color-status-pending-strong:#3A2800;   /* emphasis inside amber banners */

  /* ── Type ────────────────────────────────────────────────────────────────
     --mono was previously defined ONLY inside admin-invoices.html's page-local
     :root, so it existed on exactly one page. Every other page that wanted
     monospace hardcoded its own stack, and assets/css/data-fields.css
     referenced var(--mono, …) which silently fell back everywhere else.
     Defined here so it's real platform-wide. Found 2026-07-25. */
  --mono: 'DM Mono', 'SF Mono', 'Roboto Mono', 'Courier New', ui-monospace, monospace;

  /* Sidebar (dark surface — separate scale, not derived from --color-* above) */
  --sidebar-bg:        var(--brand-navy);
  --sidebar-text:      rgba(255,255,255,0.58);
  --sidebar-text-dim:  rgba(255,255,255,0.32);
  --sidebar-hover:     rgba(255,255,255,0.06);
  --sidebar-active-bg: rgba(245,196,0,0.12);
  --sidebar-active-fg: var(--brand-amber);
  --sidebar-border:    rgba(255,255,255,0.07);
}

/* ── client-dashboard.html migration, 2026-08-02 ──────────────────────
   This page's inline <style> used a Tailwind-slate/gray palette that is
   NOT a shade of the VAGT brand palette above — it's a genuinely separate
   set of roles (worst hex offender in pages/, 119 raw hex). Values below
   are the EXACT hex the page already rendered; none were snapped to an
   existing near-but-not-identical token (e.g. #0b1120 was kept distinct
   from --brand-navy #0D1F3C rather than merged) so the migration is a
   pure refactor with zero visual change. Flagged for Claire: several of
   these (--color-heading-strong vs --brand-navy; --color-accent-hover-strong
   vs --brand-amber-deep) look like the same near-duplicate pattern the
   2026-07-25 audit called out and may be worth deliberately converging
   later — that's a design decision, not something to guess at here. */
:root {
  --color-heading-strong:      #0b1120; /* dashboard "navy" — sidebar bg, headline/value text, avatar bg */
  --color-heading:             #111827; /* card/section headline text */
  --color-body-strong:         #1f2937; /* strong body text (contract values, titles) */
  --color-text-body:           #4b5563; /* regular body text (table cells, contact info) */
  --color-text-label:          #374151; /* uppercase tile-title labels */
  --color-text-secondary:      #6b7280; /* muted labels, captions, secondary text */
  --color-text-tertiary:       #9ca3af; /* faintest text — timestamps, codes, empty placeholders */
  --color-border-card:         #e5e7eb; /* standard card/table border */
  --color-border-strong:       #d1d5db; /* hover/emphasis border */
  --color-divider-subtle:      #f3f4f6; /* subtle dividers, table-row borders, progress track */
  --color-surface-tint:        #f9fafb; /* faint tinted background fill (page bg, hover rows) */

  --color-badge-warning-bg:    #fef3c7;
  --color-badge-warning-text:  #92400e;
  --color-badge-success-bg:    #dcfce7;
  --color-badge-success-text:  #166534;
  --color-pill-success-bg:     #d1fae5; /* welfare "tracked digitally" pill */
  --color-pill-success-text:   #065f46;

  --color-info-bg:             #eff6ff; /* info tag + info banner fill */
  --color-info-border:         #bfdbfe;
  --color-info-text-strong:    #1e40af; /* info banner body text */
  --color-tag-info-text:       #1d4ed8; /* "Veteran" tag text */
  --color-tag-positive-bg:     #f0fdf4;
  --color-tag-positive-text:   #15803d; /* "Reliable" tag */
  --color-tag-highlight-bg:    #f5f3ff;
  --color-tag-highlight-text:  #6d28d9; /* "New" tag */

  --color-progress-good:       #10b981;
  --color-progress-medium:     #f59e0b;
  --color-progress-low:        #ef4444;

  --color-accent-hover-strong: #f0bc00; /* download-btn hover — darker amber than --brand-amber-deep */
  --color-avatar-veteran-bg:   #1e3a5f;
}

/* ── admin-incidents.html migration, 2026-08-02 ───────────────────────
   Incident model (CLAUDE.md "Incident severity model"): guard-reported
   `severity` (low/medium/high/critical) drives the status-workflow badge;
   `priority` (P1-P5, computePriority() server-side) drives the separate
   pri-* pill AND the stat-strip / card accent colours. Two distinct scales
   sharing a red→green ramp, so kept as two token groups rather than forced
   into one. Values below are the EXACT hex the page already rendered.

   Snapped to existing PINNED tokens where the hex was an exact match:
     #005c30 → --color-status-active-text   (green stat value)
     #5a4200 → --color-status-pending-text  (amber stat value)
     #003080 → --color-info-text            (blue stat value / MTTA/MTTR)
     #B91C1C → --color-status-urgent        (badge-critical text)
     #c41e1e → --brand-red                  (exact match, brand layer)
   Everything else is a genuinely new role (workflow-status badges,
   priority pills, severity badges) with no existing token to reuse. */
:root {
  /* Incident stat-strip / card accents (P1/P2 priority, not workflow status) */
  --color-incident-critical:     var(--brand-red); /* #c41e1e — P1 accent, red stat value, close-section title/button */
  --color-incident-critical-bg:  #fff8f8; /* close-section panel bg */
  --color-incident-high:         #e65100; /* P2 accent — is-p2 card border */

  /* Workflow-status badges (submitted/acknowledged/in_progress/resolved/closed) */
  --color-wf-submitted-bg:      rgba(220,38,38,0.11);
  --color-wf-submitted-text:    #991B1B;
  --color-wf-submitted-border:  #DC2626;
  --color-wf-acknowledged-bg:      rgba(217,119,6,0.13);
  --color-wf-acknowledged-text:    #78350F;
  --color-wf-acknowledged-border:  #D97706;
  --color-wf-inprogress-bg:      rgba(37,99,235,0.11);
  --color-wf-inprogress-text:    #1E40AF;
  --color-wf-inprogress-border:  #2563EB;
  --color-wf-resolved-bg:      rgba(0,150,80,0.11);
  --color-wf-resolved-text:    #065F46;
  --color-wf-resolved-border:  #009650;
  --color-wf-closed-bg:      rgba(0,0,0,0.07);
  --color-wf-closed-text:    #374151;
  --color-wf-closed-border:  #6B7280;

  /* Severity badges (guard-reported low/medium/high/critical) */
  --color-sev-low-bg:      rgba(37,99,235,0.10);
  --color-sev-low-text:    #1E40AF;
  --color-sev-low-border:  #2563EB;
  --color-sev-medium-bg:      rgba(217,119,6,0.12);
  --color-sev-medium-text:    #92400E;
  --color-sev-medium-border:  #D97706;
  --color-sev-high-bg:      rgba(234,88,12,0.12);
  --color-sev-high-text:    #C2410C;
  --color-sev-high-border:  #EA580C;
  --color-sev-critical-bg:      rgba(220,38,38,0.13);
  --color-sev-critical-text:    var(--color-status-urgent); /* #B91C1C, exact match */
  --color-sev-critical-border:  #DC2626;

  /* Priority pills (P1-P5, pale fill + saturated text) */
  --color-pri-p1-bg:    #fce4ec;
  --color-pri-p1-text:  #b71c1c;
  --color-pri-p2-bg:    #fff3e0;
  --color-pri-p2-text:  #c05621;
  --color-pri-p3-bg:    #e8f5e9;
  --color-pri-p3-text:  #2e7d32;
  --color-pri-p4-bg:    #f5f5f5;
  --color-pri-p4-text:  #5E6473;
  --color-pri-p5-bg:    var(--color-pri-p4-bg);
  --color-pri-p5-text:  var(--color-pri-p4-text);

  /* P2 sub-band preview accents (employee-incidents.html live priority preview —
     P2_SEV1..SEV4 share the pri-p2 pale fills but need distinct text/bg per band).
     e65100 snaps exactly to --color-incident-high; b45309 snaps exactly to
     --color-status-pending. c62828 and fff8e1 are genuinely new roles. */
  --color-pri-p2-sev1-text: #c62828; /* P2_SEV1 preview accent */
  --color-pri-p2-sev34-bg:  #fff8e1; /* P2_SEV3/SEV4 preview + pill bg */

  /* SO-only callout (client-summary field, supervisor-tier only) */
  --color-callout-warning-bg: #fffbf0;

  /* Neutral panel + navy-hover reused elsewhere on this page */
  --color-closed-panel-bg:  #f5f5f5;
  --color-navy-hover:       #1a2f5a; /* view-btn / drawer-save button hover */
  --color-amber-hover-alt:  #e8a800; /* ack-btn hover */
}

/* ── Migration note for Mike ──────────────────────────────────────────
   Do NOT bulk-replace hex with these yet. Migrate file-by-file:
   grep a page for its hex values, map each to the closest role above,
   log any hex that has no clean role match here for Claire to review —
   don't force a fit. 216 hex → 36 old tokens is the current count;
   target is these ~26 role tokens covering all of them.

   Per-tenant theming is CONFIRMED (2026-07-25) — recorded in CLAUDE.md
   under DESIGN HOLDS. Practical effect on migration: any component CSS
   that references --brand-* directly instead of a --color-* role is a
   bug, not a style choice — it will silently ignore tenant theming.
   ─────────────────────────────────────────────────────────────────── */

/* ── verify.html migration, 2026-08-02 ─────────────────────────────────
   Public, standalone employee-verification page (no shared header/sidebar,
   loaded via QR code) — previously had zero stylesheet links at all, just
   an inline <style> block. Reused every exact hex match already defined
   above (--color-heading-strong #0b1120, --brand-amber #f5c400,
   --color-text-secondary #6b7280, --color-pill-success-bg/-text #d1fae5/
   #065f46, --color-heading #111827, --color-divider-subtle #f3f4f6,
   --color-border-card #e5e7eb, --color-badge-warning-text #92400e,
   --color-text-tertiary #9ca3af). The remaining hex had no existing role
   match — added below rather than forced onto a near-but-different shade
   (e.g. #fee2e2 is not the same red as --color-status-urgent-bg #FEF2F2). */
:root {
  --color-bg-page-standalone:   #f0f4f8; /* body background — standalone public page */
  --color-text-on-dark-subtle:  #94a3b8; /* logo sub-label on dark navy header */
  --color-spinner-track:        #e2e8f0; /* loading-spinner ring track */
  --color-badge-success-border: #6ee7b7; /* "Identity Verified" badge strip border */
  --color-text-success-secondary:#047857; /* badge strip secondary line ("registered with…") */
  --color-badge-danger-bg:      #fee2e2; /* Inactive status pill background */
  --color-badge-danger-text:    #991b1b; /* Inactive status pill text */
  --color-note-warning-bg:      #fffbeb; /* footer disclosure note background */
  --color-note-warning-border:  #fde68a; /* footer disclosure note border */
}

/* ── admin-setup.html migration, 2026-08-02 ────────────────────────────
   First-time-admin-creation page, standalone (no shared sidebar), locked
   after first admin exists. Values below are the EXACT hex the page
   already rendered — pure refactor, zero visual change. Exact matches to
   existing tokens were reused (see substitutions in the page itself);
   the tokens below are the genuinely new roles with no existing match:
     #e63946 (8x) is NOT the same red as --brand-red (#C41E1E) or
     --color-status-urgent (#B91C1C) — close enough to be the exact
     near-duplicate pattern the 2026-07-25 audit warned about, but
     snapping it would change the rendered colour, so it's kept distinct
     and flagged for Claire to consider converging later. */
:root {
  --color-setup-accent:        #e63946; /* page's primary danger/alert red — badge, border, spinner, focus ring, primary button, active step-dot */
  --color-setup-accent-hover:  #c0392b; /* primary button hover */
  --color-setup-header-bg:     #0b0e18; /* setup card header dark background */
  --color-success-icon:        #16a34a; /* configured/success check icon stroke, done step-dot */
  --color-setup-warning-bg:    #fff7ed; /* inline warning-note background */
  --color-auth-wrap-bg:        #f0f0ec; /* .portal-login-wrap background on auth pages */
  --color-surface-soft:        #f6f6f6; /* readonly-field background (portal.html return-visit email) */
  --color-info-banner-bg:      #eef2ff; /* return-visit welcome banner background */
  --color-info-banner-border:  #c7d4f0; /* return-visit welcome banner border */
  --color-shift-night-text:    #333; /* .shift-night badge text (admin-schedule.html) */
  --color-bg-soft-hover:       #f6f7f9; /* .exc-cta hover background (admin-schedule.html) */
  --color-badge-danger-border: #fecaca; /* .vp-error border (visitor-preapproval.html) */
  --color-report-dot-red:      #E05555; /* security-audit.html report-dot red */
  --color-report-dot-orange:   #E08A30; /* security-audit.html report-dot orange */
  --color-toast-success-text:  #5fcea0; /* security-audit.html form-toast success text */
  --color-toast-error-text:    #e07070; /* security-audit.html form-toast error text */
  --color-sla-bar-green:       #00965f; /* admin-reports.html SLA bar-fill green */
  --color-invoice-overdue-text: #7a0000; /* .badge-overdue text (client-invoices.html, admin-leaves.html) — distinct from --color-status-urgent-text */
  --color-delta-good-text:     #006b2b; /* admin-portal.html .delta-good text */
  --color-btn-approve-hover:   #1a3a6e; /* admin-portal.html .btn-approve:hover background */
  --color-supervisor-chip-text: #7a5900; /* employee-profile-setup.html .ps-desig-chip.supervisor text */
  --color-setup-warning-border:#fed7aa; /* inline warning-note border */
  --color-setup-warning-text:  #9a3412; /* inline warning-note text */
  --color-text-inverse:        #ffffff; /* white text on dark/accent surfaces (header h1, primary button label) */
}

/* ── admin-invoices.html migration, 2026-08-02 ─────────────────────────
   Invoice/GST/deduction workflow page. Exact-hex matches were reused
   against existing tokens (see substitutions in the page itself):
     #78350F → --color-wf-acknowledged-text · #B45309 → --color-status-pending
     #F59E0B → --color-progress-medium · #92400E/#92400e → --color-badge-warning-text
     #FEF3C7 → --color-badge-warning-bg · #c0392b → --color-setup-accent-hover
     #b91c1c → --color-status-urgent · #991b1b → --color-badge-danger-text
     #1e40af → --color-info-text-strong · #fff → --color-text-inverse
   The var(--navy, #0D1F3C) / var(--text, #333) / var(--border, #ccc)
   fallback literals were dropped, not tokenized — --navy/--text/--border
   are real custom properties defined in main.css (loaded after theme.css,
   before this inline block), so the fallback never actually fires; it was
   dead hex, not a missing token. Genuinely new roles below: */
:root {
  --color-invoice-error-text:  #7f1d1d; /* error-banner body text (result-banner.error) */
  --color-input-disabled-bg:   #f8f9fc; /* read-only period-display input fill */
  --color-toast-success-bg:    #1a7f3c; /* vagtToast success background */
}

/* ── employee-so-leaves.html migration, 2026-08-02 ─────────────────────
   SO/FM leave-approval page (guard/supervisor tier, per CLAUDE.md AUTH
   MODEL — SOs fully approve casual/sick leave for their team). Status
   colours here are a distinct scale from the incident workflow/severity
   tokens above (different domain: leave-request state, not incident
   state) — kept separate per prior migration's guidance not to force
   different domains onto one token family.

   Exact-hex matches reused against existing tokens:
     #b71c1c → --color-pri-p1-text · #fce4ec → --color-pri-p1-bg
     #e8f5e9 → --color-pri-p3-bg   · #2e7d32 → --color-pri-p3-text
     #fff8e1 → --color-pri-p2-sev34-bg
     #fff    → --color-text-inverse
     #c0392b → --color-setup-accent-hover
     #1a7f3c → --color-toast-success-bg
   Genuinely new roles below (leave-status badges + actions, no existing
   match — checked against --color-status-*, --color-wf-*, --color-sev-*,
   --color-pri-* families first per Nikhil's uniformity rule): */
:root {
  --color-leave-pending-text:        #f57f17; /* lsb-pending badge text (awaiting SO) */
  --color-leave-pendingso-bg:        #e3f2fd; /* lsb-pending-so badge + sanction action bg */
  --color-leave-pendingso-text:      #1565c0;
  --color-leave-pendingso-hover-bg:  #bbdefb; /* sanction action hover */
  --color-leave-pendingso-border:    #64b5f6; /* sanction action border */
  --color-leave-pendingadmin-bg:     #f3e5f5; /* lsb-pending-admin badge bg */
  --color-leave-pendingadmin-text:   #6a1b9a;
  --color-leave-approved-hover-bg:   #c8e6c9; /* approve action hover */
  --color-leave-approved-border:     #81c784; /* approve action border */
  --color-leave-rejected-bg:         #ffebee; /* reject-reason note, reject action, error box */
  --color-leave-rejected-hover-bg:   #ffcdd2; /* reject action hover */
  --color-leave-rejected-border:     #ef9a9a; /* reject action border */
  --color-panel-neutral-bg:          #fafafa; /* reject-form panel background */
}

/* ── sentinel-ai.html migration, 2026-08-02 ────────────────────────────
   Sentinel Engine detection-UI page (CLAUDE.md "SENTINEL NAMING" — this
   is the detection layer: tripwire/line-crossing, tracking, anomaly,
   alert policy; a real, actively-referenced page, not held/deprecated).
   Standalone, no shared header/sidebar. Its inline <style> already
   defined page-local custom properties (--navy, --amber, --green, --red,
   --amber2, --ink, --muted, etc.) referenced throughout the CSS — those
   names are kept (component code doesn't change), but their VALUES now
   resolve through role tokens instead of raw hex, so a re-theme still
   flows through here.

   Exact-hex matches reused against existing tokens:
     #0D1F3C → --brand-navy · #F5C400 → --brand-amber
     #10b981 → --color-progress-good · #ef4444 → --color-progress-low
     #f59e0b → --color-progress-medium · #fff/#ffffff → --color-text-inverse
   Also used directly in <script> canvas drawing code (fillStyle/
   strokeStyle) — not CSS, so tokens are read there via
   getComputedStyle(document.documentElement) into JS constants at the
   top of the detection-loop script, rather than duplicating hex.

   Genuinely new roles below (no existing match — checked against
   --color-status-*, --color-progress-*, --brand-* families first):
     #1A3461 is NOT the same navy-mid as --brand-navy-mid (#1A3355) —
     kept distinct, flagged for Claire, same near-duplicate pattern as
     prior migrations' notes.
     #E8B400 is NOT the same amber as --brand-amber-deep (#D9A800) —
     kept distinct for the same reason. */
:root {
  --color-sentinel-navy-gradient:   #1A3461; /* header gradient 2nd stop */
  --color-sentinel-amber-btn-hover: #E8B400; /* btn-amber gradient end */
  --color-sentinel-ink:             #e8edf6; /* primary light text on dark navy */
  --color-sentinel-muted:           #9fb0cc; /* muted text/dot/labels, OUT wire label, non-threat detection box */
  --color-sentinel-blue:            #3b82f6; /* animal/non-threat detection marker + info chip icon tone */
  --color-sentinel-switch-track:    #2b3b57; /* toggle off-state track */
  --color-sentinel-chip-threat-text:#fca5a5; /* threat-count chip text */
  --color-sentinel-chip-info-text:  #93c5fd; /* info-count chip text */
  --color-sentinel-tracking-box:    #14b8a6; /* confirmed-track ID badge + bbox teal */
  --color-sentinel-anomaly:         #a78bfa; /* anomaly-region dashed outline */
  --color-sentinel-stage-bg:        #000000; /* video/canvas stage background */
}

/* ── Strategist-lane addendum, 2026-07-25 ─────────────────────────────
   TWO OPEN ITEMS, neither blocking, both worth resolving before the
   migration starts in volume:

   1. --sidebar-active-bg and --sidebar-active-fg are hardcoded to VAGT's
      amber (rgba(245,196,0,…) / --brand-amber). Under per-tenant theming
      the sidebar is the most brand-visible surface in the product, so the
      active-state colour arguably should follow the tenant. But the
      stress-test tenant's #FEF3C7 accent on a dark sidebar is near-
      invisible — which is exactly the failure the pinned/overridable
      split exists to prevent. Suggest: pin a minimum-contrast active
      treatment, let the hue follow the tenant. Claire's call.

   2. color-mix() is used for --color-text-muted/-faint and
      --color-border-light. Well supported in current browsers, but the
      guard portal runs on low-end Android WebViews in the field. If any
      device renders these as transparent, muted text disappears against
      white. Worth one on-device check during the mobile smoke test that
      is already owed — cheap to verify, ugly to discover in production.
   ─────────────────────────────────────────────────────────────────── */

/* ── employee-patrol.html migration, 2026-08-02 ────────────────────────
   NFC beat-patrol page (guard-facing; this page is the earlier data-i18n
   reference page — this pass is CSS-color-only, i18n markup untouched).

   Exact-hex matches reused against existing tokens:
     #f59e0b → --color-progress-medium · #b45309 → --color-status-pending
     #1565c0 → --color-leave-pendingso-text · #fffbf0 → --color-callout-warning-bg
     #c0392b → --color-setup-accent-hover · #1a7f3c → --color-toast-success-bg
     #fff3e0 → --color-pri-p2-bg · #000 → --color-sentinel-stage-bg

   Genuinely new roles below (scan-method badges + scan-result panel
   backgrounds + generic subtle surfaces — no existing match, checked
   against --color-status-*, --color-badge-*, --color-pri-* families
   first per Nikhil's uniformity rule):
     #e6f4ea and #e8f4fd are pale badge backgrounds distinct from
     --color-pri-p3-bg (#e8f5e9) and --color-leave-pendingso-bg (#e3f2fd)
     respectively — close but not exact, so not snapped.
     #145f2e is the pressed/active state of the toast-success green —
     not the same value as --color-toast-success-bg, kept distinct. */
:root {
  --color-badge-nfc-bg:        #e6f4ea; /* NFC scan-mode badge + method-tag background */
  --color-badge-qr-bg:         #e8f4fd; /* QR scan-mode badge + method-tag background */
  --color-scan-success-bg:     #f0faf4; /* scan-result.success panel background */
  --color-scan-error-bg:       #fff5f5; /* scan-result.error panel background */
  --color-success-active:      #145f2e; /* cp-mark-btn pressed/active state */
  --color-panel-subtle-bg:     #f7f9fb; /* scan-mode-bar background */
}

/* ── employee-training.html migration, 2026-08-02 ──────────────────────
   PSARA training module (guard-facing; CLAUDE.md "employee-training.html
   — PSARA training, 5 modules x 10 MCQs, learning panels, certificate
   overlay"). Module-icon accent colours read directly via JS
   getComputedStyle() into per-module constants at script init, same
   pattern as sentinel-ai.html's canvas-drawing colours and
   employee-patrol.html's scan-result colours (getComputedStyle(document.
   documentElement) at the top of the script, not raw hex in JS).

   Exact-hex matches reused against existing tokens:
     #0D1F3C → --brand-navy (module-icon "PSARA Act" accent + certificate
       border, both places the page already used VAGT navy)
     #0891B2 → --brand-cyan (module-icon "Guard Duties & Conduct" accent —
       --brand-cyan is documented as the "PSARA/compliance accent", an
       exact semantic fit)
     #DC2626 → --brand-danger (module-icon "Emergency Response" accent)
     #005c30 → --color-status-active-text (status-passed badge text)

   Genuinely new roles below — checked against --color-status-*,
   --color-badge-*, --color-pri-*, --color-leave-* families first per
   Nikhil's uniformity rule. Quiz pass/fail is its own domain (correct/
   incorrect answer + module pass/fail state), same pattern as the
   --color-leave-* family being kept separate from incident/workflow
   status scales — it reads as a status colour but means something
   different here (assessment result, not a workflow stage):
     #1a7f3c is the SAME value as --color-toast-success-bg, but reused
     here under a new --color-quiz-* name rather than aliased, because
     "toast background" and "quiz pass" are unrelated UI roles that
     happen to share a value today — tying them together would make a
     future toast-colour change silently repaint the quiz UI too.
     #c0392b is likewise the same value as --color-setup-accent-hover,
     same reasoning — kept as its own --color-quiz-fail role.
     #7C3AED has no existing match — new module-icon accent
     ("Client Communication").
     #1a3a6e is NOT the same navy as --brand-navy-mid (#1A3355) or
     --brand-navy-deep (#091629) — it's the compliance-banner gradient's
     2nd stop, close to navy-mid but not identical, so kept distinct
     rather than silently darkening the banner.
     #F0F7FF / #0D6EFD are the learn-panel's pale-blue "callout" box —
     not exact matches for --color-info-bg (#eff6ff) / --color-info-
     border (#bfdbfe) / --color-info-text-strong (#1e40af), so not
     snapped.
     #FAFAF8 is the learn-panel's start-bar background — not an exact
     match for --brand-bg (#F4F3EF) or --color-surface-tint (#f9fafb). */
:root {
  --color-quiz-pass:                  #1a7f3c; /* module-card.passed border, module-score, option-label.correct border, result-icon.pass bg, result-verdict.pass, cert-score — also reused for the "Physical Fitness Standards" module-icon accent (same green) */
  --color-quiz-fail:                  #c0392b; /* module-card.failed border, status-failed text, module-score.fail, option-label.wrong border/text, result-icon.fail bg, result-verdict.fail */
  --color-training-accent-communication: #7C3AED; /* "Client Communication" module-icon accent */
  --color-training-banner-gradient-end:  #1a3a6e; /* compliance-banner gradient 2nd stop */
  --color-training-callout-bg:           #F0F7FF; /* learn-panel info callout background */
  --color-training-callout-border:       #0D6EFD; /* learn-panel info callout left border */
  --color-training-start-bar-bg:         #FAFAF8; /* learn-panel "start quiz" footer bar background */
}
   ─────────────────────────────────────────────────────────────────── */

/* ── admin-complaints.html migration, 2026-08-02 ───────────────────────
   Client complaint-ticket page. Status/priority badges reuse the SAME
   role tokens as the admin-incidents.html workflow-status + severity
   badge families (in_progress↔wf-inprogress, resolved↔wf-resolved,
   low/medium/high priority↔sev-low/medium/high) — same visual language,
   different domain object (complaint vs incident), same exact hex.

   Exact-hex matches reused against existing tokens:
     #c41e1e → --brand-red · #DC2626 → --brand-danger
     #005c30 → --color-status-active-text · #5a4200 → --color-status-pending-text
     #991B1B → --color-badge-danger-text (verify.html)
     #1E40AF → --color-wf-inprogress-text (badge-in_progress) /
       --color-sev-low-text (badge-low) — same hex, both already exist
     #2563EB → --color-wf-inprogress-border / --color-sev-low-border
     #065F46 → --color-wf-resolved-text · #009650 → --color-wf-resolved-border
     #92400E → --color-sev-medium-text · #D97706 → --color-sev-medium-border
     #C2410C → --color-sev-high-text · #EA580C → --color-sev-high-border
     #B91C1C → --color-status-urgent

   Genuinely new roles below — checked against --color-status-*, --color-wf-*,
   --color-sev-*, --color-badge-* families first per Nikhil's uniformity rule:
     #003080 is NOT the same blue as --color-info-text (#003580) — close but
     not identical, kept distinct rather than silently shifting the site-chip
     colour, same near-duplicate caution as prior migrations' notes.
     #7a0000 is NOT the same red as --color-status-urgent-text (#8B1000) —
     kept distinct for the same reason. */
:root {
  --color-complaint-site-text:        #003080; /* site-annotation chip text */
  --color-complaint-sla-breach-text:  #7a0000; /* SLA-breach chip text + red stat value */
}

/* ── admin-payroll.html migration, 2026-08-02 ───────────────────────────
   Batch-first payroll page (CLAUDE.md flags this as high-traffic/business-
   critical — batch payslip generation, client_uid batch-run payload. This
   pass is strictly CSS-token substitution; zero JS/logic touched.

   Exact-hex matches reused against existing tokens:
     #005c30 → --color-status-active-text (pill-ready/pill-generated text,
       result-banner.success text)
     #7f1d1d → --color-invoice-error-text (pill-error text, result-banner.
       error text — same role this token was already named for)
     #1e40af → --color-info-text-strong (pill-exists text)
     #374151 → --color-text-label (pill-skipped text)
     #92400e → --color-badge-warning-text (runPayrollHint banner text)
     #fffbeb → --color-status-pending-bg (runPayrollHint banner background)
     #f8f9fc → --color-input-disabled-bg (batch-bulk-row background)
     #c0392b → --color-setup-accent-hover (payStructError text)

   Genuinely new roles below — checked against --color-status-*, --color-
   badge-*, --color-info-* families first per Nikhil's uniformity rule:
     #854d0e is NOT the same amber-brown as --color-badge-warning-text
     (#92400e) or --color-status-pending-text (#5A4200) — close but not
     identical (pill-nostr text is a distinct shade), kept distinct rather
     than silently shifting it, same near-duplicate caution as prior
     migrations' notes.
     #fcd34d has no existing border-role match (closest bg is --color-
     status-pending-bg #FFFBEB, a different value) — new border token for
     the runPayrollHint banner.
     #1e3a8a is NOT the same blue as --color-info-text-strong (#1e40af) —
     kept distinct (info-note body text).
     #0a1e52 is a darker navy hover state with no existing match (not
     --brand-navy-mid #1A3355 or --brand-navy-deep #091629) — btn-run
     hover background.
     #1a7f3c is the SAME value as --color-toast-success-bg / --color-quiz-
     pass, but reused here under its own --color-stat-* role per the
     employee-training.html precedent — unrelated UI roles that happen to
     share a value today shouldn't be tied together. */
:root {
  --color-status-nostructure-text: #854d0e; /* pill-nostr text (needs pay structure) */
  --color-status-pending-border:   #fcd34d; /* runPayrollHint banner border */
  --color-info-text-deep:          #1e3a8a; /* info-note body text (set-pay-structure modal) */
  --color-primary-hover-deep:      #0a1e52; /* btn-run hover background */
  --color-stat-positive-text:      #1a7f3c; /* stat-value.green (Net Payable) */
}

/* ── pages/node-device.html (VAGT Node hardware detail page — Sentinel product
   line, see CLAUDE.md "SENTINEL NAMING") ────────────────────────────────────
   Page-local --navy/--amber/--red/--white/--text/--text-mid/--text-muted now
   resolve to the matching brand/core tokens below (exact hex match, confirmed
   before mapping) instead of duplicating the literal.

   Genuinely new roles (no existing exact match — checked against --brand-*,
   --color-status-*, --color-sev-* families first):
     #162D4B / #2B4C77 — device page's own navy-scale steps, distinct from
       --brand-navy-deep (#091629) / --brand-navy-mid (#1A3355).
     #009650 is the SAME value as --color-wf-resolved-border, but kept as its
       own role here (device online status vs. workflow border) — unrelated
       UI roles that happen to share a value today shouldn't be tied together,
       same precedent as employee-training.html / admin-payroll.html.
     #D9AE00 is NOT the same amber-dark as --brand-amber-deep (#D9A800) —
       kept distinct, same near-duplicate pattern as sentinel-ai.html's
       #E8B400 vs #D9A800 note above.
     #EA580C is the SAME value as --color-sev-high-border, kept as its own
       role for the same reason as #009650 above (device tamper alert vs.
       incident-severity workflow). */
:root {
  --color-node-navy-deep:    #162D4B; /* portal-navy-deep — card/panel gradient step */
  --color-node-navy-soft:    #2B4C77; /* portal-navy-soft — card/panel gradient step */
  --color-node-status-online:#009650; /* device online/heartbeat-ok status green */
  --color-node-amber-dark:   #D9AE00; /* battery/signal gauge — amber-dark shade */
  --color-node-status-tamper:#EA580C; /* tamper/motion alert accent */
}

/* ── pages/admin-guests.html migration, 2026-08-02 ──────────────────────
   Visitor log admin view — KPI danger stat, exception dots, guard-deploy
   status dot, visitor-type tags, and visit-status pills.

   Exact-hex matches reused against existing tokens:
     #c0392b → --color-setup-accent-hover (kpi-value.danger, exc-dot —
       same "danger/urgent accent" role as its other reuses)
     #d97706 → --brand-amber-status (exc-dot.amber)
     #1a7f3c → --color-toast-success-bg (deploy-dot.active, type-tradesman
       text, vstatus-active text — general "success/positive" green)
     #fff3e0 → --color-pri-p2-bg (type-vendor bg, vstatus-expired bg)
     #b45309 → --color-status-pending (type-vendor text, vstatus-expired
       text)
     #e8f4fd → --color-badge-qr-bg (type-delivery bg)
     #1565c0 → --color-leave-pendingso-text (type-delivery text)
     #e6f4ea → --color-badge-nfc-bg (type-tradesman bg, vstatus-active bg)

   Genuinely new roles below (checked against --color-badge-*, --color-
   status-* families first per Nikhil's uniformity rule):
     #f3e8ff / #6b21a8 are the "guest" visitor-type tag's purple —
       no existing badge family uses this hue.
     #f0f0f0 / #555 are the "exited" visit-status pill's neutral grey —
       not exact matches for --color-status-inactive-bg (#F5F5F4) /
       --color-status-inactive-text (#4B4B4B), so not snapped. */
:root {
  --color-badge-guest-bg:      #f3e8ff; /* type-guest tag background */
  --color-badge-guest-text:    #6b21a8; /* type-guest tag text */
  --color-badge-neutral-bg:    #f0f0f0; /* vstatus-exited pill background */
  --color-badge-neutral-text:  #555;    /* vstatus-exited pill text */
}

/* ── pages/client-scorecards.html (client guard performance, A-D grade
   bands — see CLAUDE.md "UI Design Rules" client section) ─────────────────
   Establishes the CANONICAL --color-grade-* token family: platform-wide,
   reusable by role (grade A/B/C/D), not page-scoped. pages/admin-scorecards.html
   is the admin-side equivalent of this page, not yet migrated — it should
   reuse this family rather than invent its own when that migration happens.

   Checked against existing families first — no exact-match reuse found:
     #006b2b / #7a4f00 are close to but distinct from
       --color-status-active-text (#005C30) / --color-status-pending-text (#5A4200)
       — kept as their own "grade" role rather than aliased, since a KPI-tile
       green/amber and a guard-grade green/amber are different UI concepts
       that happen to sit in the same part of the ramp (same precedent as
       node-device.html's #009650 note above).
     #005c30 / #5a4200 ARE the exact same values as --color-status-active-text /
       --color-status-pending-text but are kept as page-local grade-badge
       tokens rather than aliased to those — this page renders TWO distinct
       green/amber shades side by side (KPI value vs. badge text) and forcing
       them onto one shared token would silently change one of the two once
       either token's value is later revisited. Exact-value overlap today,
       deliberately not unified — same caution as node-device.html's #009650.
     #d97706 / #dc2626 are the SAME values as --color-wf-acknowledged-border
       and --color-wf-submitted-border, kept distinct for the same reason.
     #f5f7fc / #f0f4ff are new near-white tint roles (table hover / detail
       drawer bg) — no existing tint token was a close enough match. */
:root {
  /* Grade band text/value colours (KPI tiles, stat rows, detail-drawer values) */
  --color-grade-a-text:   #006b2b; /* grade A value colour — KPI tile / stat-row / detail-drawer, score >= 85 */
  --color-grade-b-text:   var(--brand-navy); /* grade B — good, score 70-84 (shares navy, no new role needed) */
  --color-grade-c-text:   #7a4f00; /* grade C value colour — KPI tile / stat-row / detail-drawer, score 50-69 */
  --color-grade-d-text:   var(--brand-red); /* grade D — needs support, score < 50 (shares brand red) */

  /* Grade badge fill + text (the round A/B/C/D badge — distinct shade pairing from the -text tokens above) */
  --color-grade-a-bg:          rgba(0,150,80,0.12);
  --color-grade-a-badge-text:  #005c30;
  --color-grade-b-bg:          rgba(13,31,60,0.08);
  --color-grade-c-bg:          rgba(245,196,0,0.18);
  --color-grade-c-badge-text:  #5a4200;
  --color-grade-d-bg:          rgba(192,57,43,0.12);
  --color-grade-d-badge-text:  #8b1a10;

  /* Score-bar fill (solid, slightly brighter than the -text shade for contrast on white) */
  --color-grade-a-fill:   #008c3c;
  --color-grade-b-fill:   var(--brand-navy);
  --color-grade-c-fill:   #d97706;
  --color-grade-d-fill:   #dc2626;

  /* Near-white tints local to the scorecard table/detail view */
  --color-scorecard-row-hover-bg: #f5f7fc; /* leaderboard table row hover fill */
  --color-scorecard-detail-bg:    #f0f4ff; /* detail-drawer panel background */
}

/* ── pages/admin-add-employee.html migration, 2026-08-02 ────────────────
   Employee onboarding wizard — multi-step form, progress indicator,
   submit/success state, plus a print-only summary sheet (JS-built via
   innerHTML, injected as inline style="" attributes on the printed table)
   used for the physical fingerprint file copy.

   Exact-hex matches reused against existing tokens:
     #fff/#ffffff → --color-text-inverse
     #5a4200      → --color-status-pending-text (PSARA reminder banner text
       inside the success screen — same "pending/amber" role already pinned)

   Genuinely new roles below — checked against --color-status-*, --color-
   toast-*, --color-quiz-* (green "success" family) first per Nikhil's
   uniformity rule:
     #0a8a4a is NOT the same green as --color-toast-success-bg /
     --color-quiz-pass (#1a7f3c) or --color-success-icon (#16a34a) — kept
     distinct rather than silently shifting the wizard's step-done/submit/
     success-icon green, same near-duplicate caution as prior migrations.
     #067a3e is that green's hover/pressed shade, no existing match.

   The print-sheet greys (#333/#000/#555/#999) are plain black-on-white
   print-only inline styles for a physical paper form (fingerprint file
   copy) — deliberately NOT the branded on-screen palette. Tokenized
   anyway (CSS custom properties resolve fine on inline style="" once the
   string is inserted into the live DOM) so the hex count still reaches 0;
   given new print-scoped roles rather than forced onto on-screen text
   tokens like --color-text-label (#374151), which are a different shade. */
:root {
  --color-onboarding-success:       #0a8a4a; /* wizard step-done indicator, submit button, success icon */
  --color-onboarding-success-hover: #067a3e; /* submit button hover */

  --color-print-label:  #333; /* print sheet — row label text */
  --color-print-value:  #000; /* print sheet — row value text */
  --color-print-meta:   #555; /* print sheet — "Employee ID / Printed on" meta line */
  --color-print-border: #999; /* print sheet — fingerprint box border */
}

/* ── pages/admin-live-map.html migration, 2026-08-02 ─────────────────────
   Leaflet live map — site-list KPI stats, coverage badges, geofence
   marker fills (full/partial/none/unknown status ramp).

   Exact-hex matches reused/aliased against existing tokens:
     #006b2b / #7a4f00 → --color-grade-a-text / --color-grade-c-text
       (KPI stat green/amber — same "value in a status ramp" role as
       the scorecard grade system)
     #005c30 / #5a4200 / #8b1a10 → --color-status-active-text /
       --color-status-pending-text / --color-grade-d-badge-text
       (site coverage badge text)
     #f5f7fc → --color-scorecard-row-hover-bg (site-list row hover —
       same near-white hover tint already established for table rows)
     #008c3c / #d97706 / #dc2626 / #6b7280 → aliased below as
       --color-marker-* — exact same hex as the scorecard grade-fill
       ramp (a/c/d) and --color-text-secondary respectively; the map
       marker and the scorecard grade bar are a different UI object
       but the same good/warm/bad/neutral status semantic, so aliased
       rather than duplicated as raw hex.

   Genuinely new role:
     #edf1ff is the site-list "selected" row background — distinct
     from the #f5f7fc hover tint (a different, cooler near-white),
     no existing tint token was a close enough match. */
:root {
  --color-sitelist-selected-bg: #edf1ff; /* site-list selected row background */

  --color-marker-full:    var(--color-grade-a-fill);    /* #008c3c — geofence marker, full coverage */
  --color-marker-partial: var(--color-grade-c-fill);    /* #d97706 — geofence marker, partial coverage */
  --color-marker-none:    var(--color-grade-d-fill);    /* #dc2626 — geofence marker, no coverage */
  --color-marker-unknown: var(--color-text-secondary);  /* #6b7280 — geofence marker, unknown status */
}

/* ── pages/client-complaints.html migration, 2026-08-02 ───────────────────
   Client complaint form message + status/severity badges. Google-Material
   badge-color convention (open/in_progress/resolved status, high/medium/low
   severity) — a distinct domain from the incident workflow-status /
   priority-P1-5 token families, even where hex values coincide, so given
   their own --color-complaint-* names rather than aliased across domains.

   Exact-hex matches aliased where the SAME literal value already exists
   elsewhere in the system (kept as their own complaint-scoped name per the
   "role, not hue" rule — a complaint's "open" badge and an incident's P2
   preview pill are different UI concepts that happen to share a shade):
     #fff3e0 → --color-pri-p2-bg          (badge-open bg)
     #e8f5e9 / #2e7d32 → --color-pri-p3-bg / --color-pri-p3-text (badge-low)
     #fff8e1 → --color-pri-p2-sev34-bg    (badge-medium bg)
     #e6f4ea → --color-badge-nfc-bg       (badge-resolved bg)

   Genuinely new roles (no existing match): #b00/#007a3d (form message
   error/success), #b45000/#1a56db/#137333/#c5221f/#b06000 (badge text
   colours — status/severity ramp not covered by any prior migration). */
:root {
  --color-complaint-error-text:   #b00;
  --color-complaint-success-text: #007a3d;

  --color-complaint-open-bg:        var(--color-pri-p2-bg);       /* #fff3e0 */
  --color-complaint-open-text:      #b45000;
  --color-complaint-inprogress-bg:  #e8f0fe;
  --color-complaint-inprogress-text:#1a56db;
  --color-complaint-resolved-bg:    var(--color-badge-nfc-bg);    /* #e6f4ea */
  --color-complaint-resolved-text:  #137333;

  --color-complaint-high-bg:    #fce8e6;
  --color-complaint-high-text:  #c5221f;
  --color-complaint-medium-bg:  var(--color-pri-p2-sev34-bg);     /* #fff8e1 */
  --color-complaint-medium-text:#b06000;
  --color-complaint-low-bg:     var(--color-pri-p3-bg);           /* #e8f5e9 */
  --color-complaint-low-text:   var(--color-pri-p3-text);         /* #2e7d32 */
}

/* ── pages/employee-guests.html migration, 2026-08-02 ──────────────────────
   Guard-facing visitor log. Type/status tags reuse the badge family
   established in admin/client-guests.html (PR #95/#103) directly — same
   component, same hex, exact matches.

   Genuinely new roles:
     #666 is NOT the same grey as --color-badge-neutral-text (#555) — the
       "exited" pill text on this page uses a visibly lighter grey than the
       admin/client guest-log equivalent, kept distinct rather than snapped.
     #7a5f00 (overstay-amber pill text) has no existing match.
     #25D366 / #1ebe5b are WhatsApp's own brand green (send-notification
       button + hover) — a third-party brand colour, not a VAGT palette
       colour, but still tokenized per "every colour resolves through a
       token" — named by what it IS (a fixed external brand mark), not
       given a VAGT status/role name it doesn't have. */
:root {
  --color-guest-pill-exited-text:      #666;
  --color-guest-overstay-amber-text:   #7a5f00;

  --color-whatsapp-brand:       #25D366;
  --color-whatsapp-brand-hover: #1ebe5b;
}

/* ── pages/client-incidents.html migration, 2026-08-02 ──────────────────────
   Client-facing incident thread. This page has its OWN workflow-status
   badge shade family (submitted/acknowledged/in_progress/resolved/closed)
   distinct from admin-incidents.html's --color-wf-* family (e.g. #7a0000
   here vs #991B1B for wf-submitted-text) — same status concept, different
   shade already in production use. Reused whichever EXISTING token already
   carried the exact value from other migrations (complaint/status-pending/
   status-active/text-label families) rather than aliasing onto the
   differently-shaded --color-wf-* set or minting page-local duplicates.
   Exact-match reuse: #7a0000 → --color-complaint-sla-breach-text ·
   #5a4200 → --color-status-pending-text · #003080 → --color-complaint-site-text
   · #005c30 → --color-status-active-text · #374151 → --color-text-label ·
   #e8f5e9/#2e7d32 → --color-pri-p3-bg/-text · #c8e6c9 → --color-leave-approved-hover-bg
   · #1a2f5a → --color-navy-hover · #f5f5f5 → --color-closed-panel-bg.
   Genuinely new: #e05000 (sev-high border, distinct orange) and #5a0000
   (critical badge text, darker than any existing red token). */
:root {
  --color-incident-sev-high-border:    #e05000;
  --color-incident-critical-badge-text:#5a0000;
}

/* ── pages/intelligent-solutions.html migration, 2026-08-02 ────────────────
   Marketing/public page. "Coming soon" feature-card tag ramp (live/soon/
   future) — live and soon reuse existing status tokens exactly; "future"
   (a muted slate tint) has no existing match. */
:root {
  --color-intel-future-tag-bg:   #f1f5f9;
  --color-intel-future-tag-text: #64748b;
}

/* ── pages/employee-so-rota.html migration, 2026-08-03 ──────────────────────
   Leave-approval status pill ramp (draft/pending/approved/rejected).
   #dbeafe (approved-status light blue) has no existing match. */
:root {
  --color-so-rota-approved-bg: #dbeafe;
}

/* ── pages/admin-devices.html migration, 2026-08-03 ─────────────────────────
   VAGT Node security-events feed. panic/tamper (#7b241c), door_open
   (#1D3D6B), lights_out (#334155), and the events-timestamp meta grey
   (#8a8a8a) have no existing match -- power_loss/battery_low (#5a4200)
   and power_restored (#005c30) reuse --color-status-pending-text /
   --color-status-active-text exactly, read via getComputedStyle since
   this is a JS event-color map, not CSS. */
:root {
  --color-device-event-panic: #7b241c;
  --color-device-event-door:  #1D3D6B;
  --color-device-event-lights:#334155;
  --color-device-events-meta: #8a8a8a;
}

/* ── pages/admin-onboarding-wizard.html migration, 2026-08-03 ──────────────
   #007a41 (submit-button hover green) has no existing match -- distinct
   shade from --color-toast-success-bg (#1a7f3c). */
:root {
  --color-onboarding-submit-hover: #007a41;
}

/* ── pages/admin-policies.html migration, 2026-08-03 ────────────────────────
   #555 (draft-status pill grey) has no existing match. */
:root {
  --color-policy-draft-text: #555;
}
