/* ═══════════════════════════════════════════════════════════════════════════
   CELESTE DESIGN TOKENS — prototype-tokens.css approved values
   Source: prototype-tokens.css (single source of truth) + UI_SPEC.md

   Rules:
   - Use semantic tokens ONLY in components. Zero raw hex.
   - Dark theme is default (:root and [data-theme="dark"])
   - Light theme via [data-theme="light"] on html/body
   - Short names (--txt, --surface, --mark) are CANONICAL
   - Long names (--text-primary, --surface-primary) are backward-compat aliases
   ═══════════════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════
   DARK THEME (default)
   Warm blacks from prototype-tokens.css
   ═══════════════════════════════════════════════════════ */
:root, [data-theme="dark"] {
  color-scheme: dark;

  /* ── Surfaces ── */
  --surface-base: #0c0b0a;
  --surface:      #181614;
  --surface-el:   #1e1b18;
  --surface-hover:#242424;

  /* ── Borders ── */
  --border-sub:    rgba(255,255,255,0.09);
  --border-top:    rgba(255,255,255,0.13);
  --border-side:   rgba(255,255,255,0.07);
  --border-bottom: rgba(255,255,255,0.03);
  --border-faint:  rgba(255,255,255,0.05);
  --border-chrome: rgba(255,255,255,0.10);
  /* Form-control outlines only (WCAG 1.4.11, >= 3:1). Hairlines stay quiet. */
  --border-control: rgba(255,255,255,0.36);
  --border-strong:  rgba(255,255,255,0.16);  /* table header rule */

  /* ── Shadows ── */
  --shadow-panel: 0 0 0 1px rgba(0,0,0,0.60), 0 28px 80px rgba(0,0,0,0.80);
  --shadow-side-panel: -12px 0 40px rgba(0,0,0,0.45);   /* CEL-51 docked record panel */
  --shadow-drop:  0 8px 24px rgba(0,0,0,0.50);
  --shadow-tip:   0 4px 12px rgba(0,0,0,0.40);

  /* ── Overlay ── */
  --overlay-bg:     rgba(0,0,0,0.50);
  --search-overlay-bg: rgba(0,0,0,0.94); /* search backdrop: 0.50 let page text show through the idle-state pointers on phone */
  --overlay-medium: rgba(0,0,0,0.70);
  --overlay-heavy:  rgba(0,0,0,0.85);
  --overlay-w:      90vw;
  --overlay-h:      90vh;
  --surface-tile-max-h: 340px;  /* Vessel Surface tile internal scroll cap (P5) */

  /* CEO 2026-05-14 (certificate_issues.md theme #1): all backdrops must
     respect light/dark mode. Pre-fix the popup backdrops (L1-L5) and the
     EntityDetailOverlay bg-black/90 were hardcoded rgba(0,0,0,*) — near-
     black in both themes, unreadable contrast in light. Tokens below
     have light-theme overrides in the [data-theme="light"] block so the
     same class names render appropriately per theme. */
  --overlay-backdrop-read:   rgba(0,0,0,0.25);  /* read-mode popup */
  --overlay-backdrop-l1:     rgba(0,0,0,0.35);  /* signature L1 */
  --overlay-backdrop-l2:     rgba(0,0,0,0.45);  /* signature L2 */
  --overlay-backdrop-l4:     rgba(0,0,0,0.60);  /* signature L4 (wet sig) */
  --overlay-backdrop-l5:     rgba(0,0,0,0.60);  /* signature L5 (chain) */
  --overlay-backdrop-entity: rgba(0,0,0,0.45);  /* entity card detail overlay — light dim, blur does the work */

  /* ── Glass / Split ── */
  --glass-bg:       rgba(16,14,12,0.65);
  --glass-border:   1px solid rgba(255,255,255,0.07);
  --glass-blur:     blur(12px);
  --split-bg:       rgba(255,255,255,0.06);
  --split-bg-hover: rgba(255,255,255,0.10);

  /* ── Text ── */
  --txt:       rgba(255,255,255,0.92);
  /* M6 readability (CEL-44, render 04-readability-before-after.html):
     --txt2 (secondary: descriptions, context lines, nav labels) sits ABOVE
     --txt3 (labels & metadata) so labels never outshine the content they
     label. Ghost is decoration / disabled only — readable text that used
     to sit on it uses --txt-meta. WCAG AA guarded in
     __tests__/token-contrast-wcag.test.ts:
       --txt2 .70 (9.7:1) · --txt3 .55 (6.3:1) · ghost .40 decoration */
  --txt2:      rgba(255,255,255,0.70);
  --txt3:      rgba(255,255,255,0.55);
  --txt-ghost: rgba(255,255,255,0.40);
  /* Semantic text roles (CEL-45). Declared once here on :root and resolved
     against the active theme's greys; the light block does not redeclare
     them.
       --txt-meta          readable text that sat on the ghost grey (labels,
                           counts, hints, placeholders, close buttons, empty
                           states) → the label grey
       --txt-pill-neutral  neutral (resting) pill text → --status-neutral
       --fill-disabled     disabled control fills / disabled button text →
                           the ghost grey */
  --txt-meta:         var(--txt3);
  --txt-pill-neutral: var(--status-neutral);
  --fill-disabled:    var(--txt-ghost);
  --text-inverse: #0c0b0a;

  /* ── Brand ── */
  --mark:           #5AABCC;
  --teal:           #3A7C9D;
  --teal-light:     #5AABCC;
  --teal-bg:        rgba(58,124,157,0.12);
  --mark-hover:     rgba(58,124,157,0.22);
  --mark-underline: rgba(90,171,204,0.3);
  --mark-thumb:     rgba(90,171,204,0.25);
  /* ALE-836 — global keyboard focus-visible ring (form fields, buttons,
     table rows). Matches brand teal, per-theme like --mark. */
  --focus-ring:     var(--mark);
  --on-status:      #0c0b0a;   /* dark label on status fills (white was 3.0-3.7:1 on amber/green) */
  --on-solid:       #fff;      /* label on flat teal solid button */

  /* Brand CTA teal — per colour-system.md "CTA buttons" row.
     Used by .btn-teal-solid / .btn-teal-hollow. Distinct from --mark
     (the general interactive-affordance teal). #2B8FB3 dark / #2B7BA3 light. */
  --btn-color:          #2B8FB3;
  --btn-color-hover:    #239AB8;
  --btn-color-bg:       rgba(43,143,179,0.10);
  --btn-color-bg-hover: rgba(43,143,179,0.18);
  --btn-color-border:   rgba(43,143,179,0.32);

  /* Solid button: FLAT teal (brand: no gradient in product UI), white label
     >= 4.5:1. top/bottom kept equal so existing consumers still resolve. */
  --btn-solid-top:        #277FA1;
  --btn-solid-bottom:     #277FA1;
  --btn-solid-edge:       #1B6683;
  --btn-solid-top-hover:  #24708F;
  --btn-solid-bot-hover:  #24708F;
  --btn-solid-edge-hover: #1E6E8C;
  --btn-solid-inner-light:transparent;
  --btn-solid-drop:       0 1px 1px rgba(0,0,0,0.30);
  --btn-solid-press:      inset 0 1px 2px rgba(0,0,0,0.20);

  /* ── Signal colours ── */
  --red:          #CD7462;
  --red-bg:       rgba(192,80,58,0.10);
  --red-border:   rgba(192,80,58,0.22);
  --amber:        #C4893B;
  --amber-bg:     rgba(196,137,59,0.10);
  --amber-border: rgba(196,137,59,0.22);
  --green:        #5BA177;
  --green-bg:     rgba(76,175,129,0.10);
  --green-border: rgba(76,175,129,0.22);
  --blue:         #5B8DEF;
  --blue-bg:      rgba(91,141,239,0.10);
  --blue-border:  rgba(91,141,239,0.22);

  /* High severity — one warmer step down from critical --red. The calm
     pill (render-shapes SEVERITY_TONE.high) used to carry the #B45A3D /
     rgba(180,90,61,*) literals inline; tokenised here so both themes
     resolve through var() and zero raw hex lives in the component. */
  --severity-high:        #C27962;
  --severity-high-bg:     rgba(180,90,61,0.10);
  --severity-high-border: rgba(180,90,61,0.22);

  /* ── Compact-pill TEXT (ALE-310 calm pill) ──
     Lightened signal shades chosen for legibility on the .10 dark tint.
     The full-saturation --red/--amber/etc. stay reserved for the dot +
     border; the LABEL reads on these softer shades so a critical pill is
     calm, not a boxed alarm. Light theme overrides below to the readable
     signal colour. Mirrors p8-calm-colour.html. */
  --pill-red-txt:    #d97a64;
  --pill-amber-txt:  #d6a45c;
  --pill-green-txt:  #7fc49a;
  --pill-blue-txt:   #83a8f2;

  /* ── Status (neutral — theme-dependent) ── */
  --status-neutral:    var(--txt2);
  --status-neutral-bg: rgba(255,255,255,0.05);
  --neutral-bg:        var(--status-neutral-bg);

  /* ── Backward compat — existing components use these names ── */
  --surface-primary:      var(--surface);
  --surface-elevated:     var(--surface-el);
  --surface-active:       var(--surface-hover);
  --surface-border:       var(--border-sub);
  --surface-border-subtle:var(--border-faint);
  --text-primary:         var(--txt);
  --text-secondary:       var(--txt2);
  --text-tertiary:        var(--txt3);
  --text-disabled:        var(--txt-ghost);

  /* ── Brand aliases ── */
  --brand-ambient:     var(--teal);
  --brand-interactive: var(--mark);
  --brand-hover:       var(--mark-hover);
  --brand-muted:       var(--teal-bg);

  /* ── Status → Signal mapping ── */
  --status-critical:    var(--red);
  --status-critical-bg: var(--red-bg);
  --status-warning:     var(--amber);
  --status-warning-bg:  var(--amber-bg);
  --status-success:     var(--green);
  --status-success-bg:  var(--green-bg);

  /* ── Button tokens ── */
  /* CEO 2026-05-14 (certificate_issues.md item 3): brand primary CTA is
     teal, not inverted-monochrome. Aligns .btn-primary across the codebase
     (CreateCertificateButton, NotesSection Save, every PrimaryButton
     consumer) with the Subbar teal cluster. Hex literals replaced with
     brand var() refs so both themes resolve to teal automatically. */
  --btn-primary-bg:         var(--teal-bg);
  --btn-primary-text:       var(--mark);
  --btn-primary-border:     var(--mark-hover);
  --btn-ghost-hover-bg:     #323232;
  --btn-secondary-border:   #404040;
  --btn-secondary-hover-bg: #323232;
  --btn-danger-bg:          #C0503A;  /* decoupled from the lighter text --red; white label >= 4.5:1 */
  --btn-danger-hover-bg:    #9B3F2E;
  --btn-danger-text:        #ffffff;

  /* ── Shadow aliases (old names) ── */
  --shadow-sm: var(--shadow-tip);
  --shadow-md: var(--shadow-drop);
  --shadow-lg: var(--shadow-panel);
  /* CARDS05 2026-05-14 (PR-0): --shadow-card was referenced at 9 sites
     (work-orders/page.tsx, LinkedEntityActions undo-toast + confirm-dialog,
     WorkOrderContent, WOModals, EditChecklistModal, CreateWorkOrderModal)
     but never defined — every consumer rendered boxShadow:undefined.
     Aliased to --shadow-drop (popover/card elevation). Per-site intent
     tuning (panel vs drop vs tip) deferred. */
  --shadow-card: var(--shadow-drop);

  /* ── Homepage: Topbar ── */
  --topbar-bg:          rgba(12,11,10,0.70);
  --topbar-brand-color: #4A9EC0;
  --topbar-vessel-em:   rgba(74,158,192,0.80);
  --topbar-role-bg:     var(--surface-el);

  /* ── Homepage: Search panel glass ── */
  --search-glass-bg:       rgba(14,12,10,0.72);
  --search-glass-blur:     28px;
  --search-glass-border-t: rgba(255,255,255,0.13);
  --search-glass-border-s: rgba(255,255,255,0.06);
  --search-glass-border-b: rgba(255,255,255,0.03);
  --search-glass-shadow:   0 20px 80px rgba(0,0,0,0.60), 0 4px 20px rgba(0,0,0,0.40), inset 0 1px 0 rgba(255,255,255,0.05);

  /* ── Homepage: Footer / kbd ── */
  --search-footer-bg:   rgba(0,0,0,0.18);
  --search-icon-strip-bg: rgba(0,0,0,0.10);
  --search-icon-strip-border: rgba(255,255,255,0.04);
  --kbd-bg:              var(--surface-el);
  --kbd-color:           var(--txt3);
  --kbd-border:          transparent;

  /* Pill-strip tokens — used by LensPillStrip in the spotlight overlay
     (28px clickable filter pill with hover + shadow). Distinct from
     --pill-compact-* below, which power the static 18px status/severity
     badges in tabulated list views. Two different components; do not
     consolidate. */
  --pill-strip-bg:        var(--surface);
  --pill-strip-color:     var(--txt2);
  --pill-strip-border-t:  rgba(255,255,255,0.11);
  --pill-strip-border-s:  rgba(255,255,255,0.07);
  --pill-strip-border-b:  rgba(255,255,255,0.04);
  --pill-strip-hover-bg:  rgba(58,124,157,0.10);
  --pill-strip-hover-color: var(--mark);
  --pill-strip-hover-border: rgba(90,171,204,0.30);
  --pill-strip-shadow:    none;

  /* ── Settings modal ── */
  --settings-modal-bg:       var(--surface-el);
  --settings-modal-border-t: rgba(255,255,255,0.13);
  --settings-modal-border-s: rgba(255,255,255,0.06);
  --settings-modal-border-b: rgba(255,255,255,0.03);
  --settings-modal-shadow:   0 0 0 1px rgba(0,0,0,0.60), 0 28px 80px rgba(0,0,0,0.80), 0 8px 24px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.05);
  --settings-header-bg:      rgba(16,14,12,0.65);
  --settings-backdrop:       rgba(0,0,0,0.35);

  /* ── Shell structural dimensions ──────────────────────────────────────────
     Single source of truth for AppShell grid layout.
     Any component measuring against the shell (e.g. fixed-position overlays,
     calc-based offsets) must use these tokens — never hardcode 48/46/192.
     These are dimension tokens (not theme tokens) so they live in :root and
     do NOT change between dark/light themes.
  ── */
  --shell-topbar-h:          48px;   /* Topbar row height                      */
  --shell-subbar-h:          46px;   /* Subbar row height (hidden on surface/HoR) */
  --shell-sidebar-w:         192px;  /* Full sidebar width (desktop)            */
  --shell-sidebar-compact-w: 48px;   /* Compact sidebar width (tablet)          */
  --filter-panel-w:          280px;  /* FilterPanel sidebar width (list pages)  */
  --icon-size-inline:        13px;   /* Brand canon — inline within text         */
  --icon-size-row:           16px;   /* Brand canon — row entity type             */
  --icon-size-button:        18px;   /* Brand canon — icon-only button            */

  /* FilterStrip · header filter band (G-1, CEO 2026-05-15) */
  --filter-strip-h:          52px;   /* Strip vertical band height               */
  --filter-btn-h:            28px;   /* .btn.filter trigger height (SM)          */
  --filter-btn-pad-x:        10px;   /* .btn.filter horizontal padding           */

  /* ── Hours-of-Rest additive tokens (dark) ── */
  --surface-card:        rgba(255,255,255,0.03);
  --surface-subtle:      rgba(255,255,255,0.05);
  --red-border-strong:   rgba(192,80,58,0.35);
  --green-strong:        rgba(76,175,129,0.9);
  --red-strong:          rgba(192,80,58,0.9);
  --mark-strong:         rgba(90,171,204,0.8);
  --mark-border:         rgba(90,171,204,0.30);
  --compliance-good:     var(--green-strong);
  --compliance-warn:     rgba(196,137,59,0.9);
  --compliance-crit:     var(--red-strong);
  --overlay-subtle:      rgba(0,0,0,0.15);

  /* ── Drift aliases ─────────────────────────────────────────────
     Non-canonical token names that consumers still reference, mapped
     to the canonical token via `var()` indirection so per-theme
     overrides resolve correctly. Each entry exists ONLY to make the
     consumer compile + render correctly until that consumer is
     renamed to the canonical token. Do NOT extend this block — fix
     the consumer instead. Caught + ratified by the project-wide
     token-resolution guard at __tests__/tokens-resolve-globally.test.ts.
     Cleanup tracked per family in Linear (ALE-NEW backlog).
     ─────────────────────────────────────────────────────────────── */
  --bg:                   var(--surface);                /* IdentityStrip, WO/AddChecklistItemModal — panel bg intent */
  --font-body:            var(--font-sans);              /* MyTimeView/* fontFamily intent (NOT font-size) */
  --font-size-small:      var(--font-size-caption);      /* FieldAttachment — caption-tier (12px) */
  --txt-secondary:        var(--txt2);                   /* ActionPopup/FieldEntitySearch — canonical is --txt2 */
  --txt-primary:          var(--txt);                    /* same — canonical is --txt */
  --txt1:                 var(--txt);                    /* PurchaseOrderContent etc — typo of --txt. CEL-45: call sites moved to the canonical tokens; these 4 text aliases are kept only so a stray reference still resolves */
  --text-xs:              var(--font-size-caption);      /* IdentityStrip — caption tier (12px; M6 readability floor) */
  --text-sm:              var(--font-size-label);        /* same — 13px tier */
  --text-md:              var(--font-size-body);         /* WO/EditChecklistModal — 14px tier */
  --text-sub:             var(--txt2);                   /* Subbar — sub-text intent */
  --color-status-critical:var(--status-critical);        /* AttachmentUploadModal — canonical is --status-critical */
  --color-error:          var(--status-critical);        /* ChecklistSection — same intent */
  --danger:               var(--red);                    /* PurchaseOrderContent — canonical is --red per colour-system §5 */
  --danger-bg:            var(--red-bg);                 /* same */
  --danger-border:        var(--red-border);             /* same */
  --surface-raised:       var(--surface-hover);          /* Subbar/PO — confirmed via fallback `var(--surface-raised, var(--surface-hover))` in shopping-list/new */
  --surface-glass:        var(--glass-bg);               /* DrawerHeader — canonical is --glass-bg */
  --on-mark:              var(--text-inverse);           /* lens.module.css/WO — text colour on top of --mark background */
  --radius-xs:            var(--radius-sm);              /* LinkedEntityActions — smallest defined radius (2px) */
  --mark-bg:              var(--teal-bg);                /* ReceivingLabelPrint — mark-coloured background */
  --border-t:             var(--border-top);             /* SmartPointers — canonical is --border-top */
  --border-s:             var(--border-side);            /* same */
  --border-b:             var(--border-bottom);          /* same */
}

/* ═══════════════════════════════════════════════════════
   LIGHT THEME
   Clean whites from prototype-tokens.css
   ═══════════════════════════════════════════════════════ */
[data-theme="light"] {
  color-scheme: light;

  /* ── Surfaces ── */
  --surface-base: #FFFFFF;
  --surface:      #F5F5F3;
  --surface-el:   #FFFFFF;
  --surface-hover:#EBEBE8;

  /* ── Borders ── */
  /* Light edges are symmetric: the dark theme's "top light" trick leaves the
     bottom/side edge invisible on white. ~1.3:1 on both --surface-base and --surface. */
  --border-sub:    rgba(0,0,0,0.14);
  --border-top:    rgba(0,0,0,0.14);
  --border-side:   rgba(0,0,0,0.14);
  --border-bottom: rgba(0,0,0,0.14);
  --border-faint:  rgba(0,0,0,0.09);
  --border-chrome: rgba(0,0,0,0.14);
  --border-strong: rgba(0,0,0,0.22);  /* table header rule */
  --border-control: rgba(0,0,0,0.44);

  /* ── Shadows ── */
  --shadow-panel: 0 0 0 1px rgba(0,0,0,0.08), 0 28px 80px rgba(0,0,0,0.15);
  --shadow-side-panel: -12px 0 40px rgba(0,0,0,0.12);   /* CEL-51 docked record panel */
  --shadow-drop:  0 8px 24px rgba(0,0,0,0.12);
  --shadow-tip:   0 4px 12px rgba(0,0,0,0.08);

  /* ── Overlay ── */
  --overlay-bg:     rgba(0,0,0,0.30);
  --search-overlay-bg: rgba(0,0,0,0.30); /* light unchanged (founder ruling) */
  --overlay-medium: rgba(0,0,0,0.50);
  --overlay-heavy:  rgba(0,0,0,0.72);
  --overlay-w:      90vw;
  --overlay-h:      90vh;
  --surface-tile-max-h: 340px;  /* Vessel Surface tile internal scroll cap (P5) */

  /* Light-theme backdrops — see :root note above. Scaled down vs dark so
     content stays legible behind the modal. Tuned to dim the background
     enough that the modal is visually elevated without crushing the
     underlying lens text into illegible contrast. */
  --overlay-backdrop-read:   rgba(15,23,42,0.10);
  --overlay-backdrop-l1:     rgba(15,23,42,0.15);
  --overlay-backdrop-l2:     rgba(15,23,42,0.22);
  --overlay-backdrop-l3:     rgba(15,23,42,0.28);
  --overlay-backdrop-l4:     rgba(15,23,42,0.35);
  --overlay-backdrop-l5:     rgba(15,23,42,0.35);
  --overlay-backdrop-entity: rgba(15,23,42,0.45);

  /* ── Glass / Split ── */
  --glass-bg:       rgba(248,248,248,0.85);
  --glass-border:   1px solid rgba(0,0,0,0.08);
  --glass-blur:     blur(12px);
  --split-bg:       rgba(0,0,0,0.04);
  --split-bg-hover: rgba(0,0,0,0.08);

  /* ── Text ── */
  --txt:       rgba(0,0,0,0.87);
  /* M6 readability (CEL-44): --txt2 above --txt3, as in the dark block.
     --txt3 .58 keeps the ALE-1217 AA floor (it was .46 = 3.4:1); the
     ALE-1217 "txt3 above txt2" ordering was reversed by the founder
     2026-10-12 (render 04-readability-before-after.html):
       --txt2 .65 (7.0:1) · --txt3 .58 (5.3:1) · ghost .45 decoration */
  --txt2:      rgba(0,0,0,0.65);
  --txt3:      rgba(0,0,0,0.58);
  --txt-ghost: rgba(0,0,0,0.45);
  --text-inverse: #FFFFFF;

  /* ── Brand (light-mode tints) ── */
  --mark:           #276F94;
  --teal-light:     #276F94;
  --teal:           #276F94;   /* was inheriting dark #3A7C9D */
  --teal-bg:        rgba(43,127,163,0.08);
  --mark-hover:     rgba(43,127,163,0.16);
  --mark-underline: rgba(43,127,163,0.3);
  --mark-thumb:     rgba(43,127,163,0.20);
  /* ALE-836 — global keyboard focus-visible ring (form fields, buttons,
     table rows). Matches brand teal, per-theme like --mark. */
  --focus-ring:     var(--mark);

  /* Brand CTA teal — light theme override. */
  --btn-color:          #276F94;
  --btn-color-hover:    #1E5F82;
  --btn-color-bg:       rgba(43,123,163,0.08);
  --btn-color-bg-hover: rgba(43,123,163,0.16);
  --btn-color-border:   rgba(43,123,163,0.32);

  /* Solid button depth — light theme override. */
  --btn-solid-top:        #2B7CA5;
  --btn-solid-bottom:     #2B7CA5;
  --btn-solid-edge:       #1A5F88;
  --btn-solid-top-hover:  #2E7CA3;
  --btn-solid-bot-hover:  #2E7CA3;
  --btn-solid-edge-hover: #1f6792;
  --btn-solid-inner-light:transparent;
  --btn-solid-drop:       0 1px 1px rgba(0,0,0,0.12);
  --btn-solid-press:      inset 0 1px 2px rgba(0,0,0,0.10);
  --on-status:      #fff;

  /* ── Signal colours (light-mode tints) ── */
  --red:          #AF4935;
  --red-bg:       rgba(192,80,58,0.06);
  --red-border:   rgba(192,80,58,0.15);
  --amber:        #8E5F24;
  --amber-bg:     rgba(196,137,59,0.06);
  --amber-border: rgba(196,137,59,0.15);
  --green:        #317554;
  --green-bg:     rgba(76,175,129,0.06);
  --green-border: rgba(76,175,129,0.15);
  --blue:         #3E66B7;
  --blue-bg:      rgba(74,122,217,0.06);
  --blue-border:  rgba(74,122,217,0.15);

  /* High severity — light-theme tints (scaled to .06/.15 like the other
     signal families above so the calm pill stays legible on white). */
  --severity-high:        #A35137;
  --severity-high-bg:     rgba(180,90,61,0.06);
  --severity-high-border: rgba(180,90,61,0.15);

  /* ── Compact-pill TEXT (ALE-310 calm pill, light) ──
     The dark-tuned lightened shades are too pale on white; use the
     readable signal colour directly (matches p8-calm-colour.html light). */
  --pill-red-txt:    var(--red);
  --pill-amber-txt:  var(--amber);
  --pill-green-txt:  var(--green);
  --pill-blue-txt:   var(--blue);

  /* ── Status (neutral — light theme) ── */
  --status-neutral:    var(--txt2);
  --status-neutral-bg: rgba(0,0,0,0.04);
  --neutral-bg:        var(--status-neutral-bg);

  /* ── Backward compat — same aliases as dark (cascade override) ── */
  --surface-primary:      var(--surface);
  --surface-elevated:     var(--surface-el);
  --surface-active:       var(--surface-hover);
  --surface-border:       var(--border-sub);
  --surface-border-subtle:var(--border-faint);
  --text-primary:         var(--txt);
  --text-secondary:       var(--txt2);
  --text-tertiary:        var(--txt3);
  --text-disabled:        var(--txt-ghost);

  /* ── Brand aliases ── */
  --brand-ambient:     var(--teal);
  --brand-interactive: var(--mark);
  --brand-hover:       var(--mark-hover);
  --brand-muted:       var(--teal-bg);

  /* ── Status → Signal mapping ── */
  --status-critical:    var(--red);
  --status-critical-bg: var(--red-bg);
  --status-warning:     var(--amber);
  --status-warning-bg:  var(--amber-bg);
  --status-success:     var(--green);
  --status-success-bg:  var(--green-bg);

  /* ── Button tokens (light overrides) ── */
  /* See CEO 2026-05-14 note in :root above — same brand-teal references
     here; --teal-bg / --mark / --mark-hover already resolve to the light
     palette in this block, so .btn-primary picks up the light-mode teal. */
  --btn-primary-bg:         var(--teal-bg);
  --btn-primary-text:       var(--mark);
  --btn-primary-border:     var(--mark-hover);
  --btn-ghost-hover-bg:     #eeeeee;
  --btn-secondary-border:   #e7e7e7;
  --btn-secondary-hover-bg: #eeeeee;
  --btn-danger-bg:          var(--red);
  --btn-danger-hover-bg:    #9B3F2E;
  --btn-danger-text:        #ffffff;

  /* ── Shadow aliases (old names) ── */
  --shadow-sm: var(--shadow-tip);
  --shadow-md: var(--shadow-drop);
  --shadow-lg: var(--shadow-panel);
  /* CARDS05 2026-05-14 (PR-0): see dark-block comment for context. */
  --shadow-card: var(--shadow-drop);

  /* ── Homepage: Topbar ── */
  --topbar-bg:          rgba(242,240,236,0.88);
  --topbar-brand-color: var(--mark);
  --topbar-vessel-em:   rgba(26,107,150,0.85);
  --topbar-role-bg:     rgba(0,0,0,0.05);

  /* ── Homepage: Search panel glass ── */
  --search-glass-bg:       rgba(255,255,255,0.92);
  --search-glass-blur:     20px;
  --search-glass-border-t: rgba(0,0,0,0.12);
  --search-glass-border-s: rgba(0,0,0,0.06);
  --search-glass-border-b: rgba(0,0,0,0.04);
  --search-glass-shadow:   0 8px 40px rgba(0,0,0,0.10), 0 2px 8px rgba(0,0,0,0.07), inset 0 1px 0 rgba(255,255,255,0.90);

  /* ── Homepage: Footer / kbd ── */
  --search-footer-bg:   rgba(0,0,0,0.02);
  --search-icon-strip-bg: rgba(0,0,0,0.02);
  --search-icon-strip-border: rgba(0,0,0,0.06);
  --kbd-bg:              var(--surface-hover);
  --kbd-color:           var(--txt3);
  --kbd-border:          var(--border-sub);

  /* Pill-strip tokens — light-theme values. See dark-theme block above
     for component scope. Distinct from --pill-compact-* status badges. */
  --pill-strip-bg:        var(--surface);
  --pill-strip-color:     var(--txt2);
  --pill-strip-border-t:  var(--border-top);
  --pill-strip-border-s:  var(--border-sub);
  --pill-strip-border-b:  var(--border-faint);
  --pill-strip-hover-bg:  rgba(26,107,150,0.07);
  --pill-strip-hover-color: var(--mark);
  --pill-strip-hover-border: rgba(26,107,150,0.28);
  --pill-strip-shadow:    0 1px 3px rgba(0,0,0,0.05);

  /* ── Settings modal ── */
  --settings-modal-bg:       var(--surface-el);
  --settings-modal-border-t: rgba(0,0,0,0.12);
  --settings-modal-border-s: rgba(0,0,0,0.06);
  --settings-modal-border-b: rgba(0,0,0,0.04);
  --settings-modal-shadow:   0 0 0 1px rgba(0,0,0,0.05), 0 28px 80px rgba(0,0,0,0.13), 0 8px 24px rgba(0,0,0,0.08), inset 0 1px 0 #fff;
  --settings-header-bg:      rgba(242,240,236,0.88);
  --settings-backdrop:       rgba(0,0,0,0.25);

  /* ── Hours-of-Rest additive tokens (light) ── */
  --surface-card:        rgba(0,0,0,0.03);
  --surface-subtle:      rgba(0,0,0,0.05);
  --red-border-strong:   rgba(192,80,58,0.30);
  --green-strong:        rgba(61,146,104,0.9);
  --red-strong:          rgba(192,80,58,0.9);
  --mark-strong:         rgba(43,123,163,0.85);
  --mark-border:         rgba(43,123,163,0.28);
  --compliance-good:     var(--green-strong);
  --compliance-warn:     rgba(184,122,46,0.9);
  --compliance-crit:     var(--red-strong);
  --overlay-subtle:      rgba(0,0,0,0.08);
}

/* READABILITY (M6 · CEL-9) is the base: the greys (R1) and the
   --txt-meta / --txt-pill-neutral / --fill-disabled roles (R2) live in the
   theme blocks above, the type scale (R3) in TYPOGRAPHY SCALE /
   --pill-compact-* below, statusTone (R4) in lib/statusTone.ts. Type roles:
   overline 11 (uppercase only) · caption 12 · label 13 · body 14 ·
   heading 18 · title 24 — floor 11px uppercase / 12px everything else;
   no weight 700 (→ 600). Render: 04-readability-before-after.html. */

/* ═══════════════════════════════════════════════════════
   SHARED TOKENS (same in both themes)
   ═══════════════════════════════════════════════════════ */
:root {
  /* List row background: default here so it always resolves; EntityTableRow.module.css
     overrides it per row state (selected / hover) and the pinned cells read it. */
  --row-bg: var(--surface-base);

  /* Typography - System Font Stack (no web font loading required) */
  --font-sans: -apple-system, BlinkMacSystemFont, system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-family: var(--font-sans);
  --font-mono: 'SF Mono', ui-monospace, 'Fira Code', monospace;

  /* Spacing (4px base) */
  --space-1: 4px;   --space-2: 8px;   --space-3: 12px;
  --space-4: 16px;  --space-5: 20px;  --space-6: 24px;
  --space-8: 32px;  --space-10: 40px; --space-12: 48px;
  --space-16: 64px; --space-20: 80px;

  /* Radius - ULTRA scale per CEO 2026-05-15 ratification.
     Spec: popup-preview-2026-05-15-buttons.html (Button System v1).
     "Instrument-grade — radius is information, not decoration." */
  --radius-pill: 1px;      /* Pills, tags */
  --radius-sm:   2px;      /* Close buttons, toggle groups */
  --radius-md:   2px;      /* Buttons, inputs, selects, nav items */
  --radius-lg:   3px;      /* Modals */
  --radius-xl:   4px;      /* Large containers */
  --radius-full: 9999px;   /* Status dots, avatars (always pill) */

  /* Transitions */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-hover:  60ms;   /* Background hover (brand spec — allowed) */
  --duration-fast:  120ms;
  --duration-normal: 200ms;
  --duration-slow:   300ms;

  /* Z-index — TWO parallel scales:
     - Logical (10-60) — components that compose via z-index relative
       to their parent stacking context. Used by sidebar, header,
       modal in non-overlay contexts.
     - Overlay (1100-1500) — the lens/drawer/modal/toast overlay system
       that needs absolute global ordering. These override anything
       below. Toast sits ABOVE modal because the trust-journey
       acknowledgment is epistemically higher-priority than the modal
       that triggered it (CEO 2026-05-28 trust-journey discipline). */
  --z-sticky: 10;
  --z-header: 20;
  --z-sidebar: 30;
  --z-modal: 40;
  --z-search: 50;
  --z-toast: 60;

  /* Modal sizing — CEO 2026-05-28 popup uniformity contract.
     Consumed by <Modal /> primitive at components/modal/Modal.tsx.
     4 sizes only; if a consumer needs something else, the answer is
     'no — change the layout, not the size'. */
  --modal-w-sm: 480px;  /* Confirms / brief prompts */
  --modal-w-md: 560px;  /* Default — Add to Handover, simple forms */
  --modal-w-lg: 720px;  /* Multi-field create flows */
  --modal-w-xl: 920px;  /* Document-grade content (rare) */

  /* Backdrop dim levels — used by Modal + Drawer overlays */
  --overlay-backdrop-l3: rgba(0, 0, 0, 0.55);  /* signature L3 (single dark definition) */

  /* Side-panel tier (CEL-51). The docked, NON-modal record panel sits:
       above the Subbar (90) — it covers the list's right side, subbar included;
       below the Topbar (100) — so the user / vessel / notification menus and
       the Ledger / Handover panels (100) open over it;
       below search (200 / 500), drawers (900 / 1100), modals (1200+) and
       toasts — so Log Fault (DrawerShell), the ClaimPackDrawer etc. opened
       while it is up are never hidden behind it.
     While a modal opened FROM the panel is up (and always for the <900px
     full-screen sheet) the panel is raised to the modal tier, exactly where
     the centre overlay sat, so that modal is not tucked under the Topbar. */
  --z-side-panel:            95;
  --z-side-panel-raised:     var(--z-overlay-modal);
  --z-drawer-backdrop:       900;   /* DrawerShell scrim */
  --z-drawer:                901;   /* DrawerShell panel */

  /* Overlay scale */
  --z-overlay-drawer:        1100;
  --z-overlay-modal-backdrop: 1200;
  --z-overlay-modal:         1250;
  --z-overlay-toast:         2000;  /* above every modal, confirm (1500) and image viewer */
  --z-overlay-confirm:       1500;  /* reserved for destructive confirms */

  /* ═══════════════════════════════════════════════════════
     TYPOGRAPHY SCALE — UI_SPEC.md exact specification
     Weight creates hierarchy, not size.
     ═══════════════════════════════════════════════════════ */

  /* Display — 28px / 600 / 1.15 / -0.02em (Lens title on mobile) */
  --font-size-display: 28px;
  --font-weight-display: 600;   /* M6: no weight 700 */
  --line-height-display: 1.15;
  --letter-spacing-display: -0.02em;

  /* Title — 24px / 600 / 1.2 / -0.01em (Entity name / lens title) */
  --font-size-title: 24px;
  --font-weight-title: 600;
  --line-height-title: 1.2;
  --letter-spacing-title: -0.01em;

  /* h2 — page-title alias on the Title rung (used by app/crew page <h1>, weight
     600 — the lens-title role). The semantic scale has no separate h-ramp; h2
     maps to the existing Title rung rather than introducing an off-scale value. */
  --font-size-h2: var(--font-size-title);

  /* Heading — 18px / 600 / 1.3 / 0 (Major section breaks) */
  --font-size-heading: 18px;
  --font-weight-heading: 600;
  --line-height-heading: 1.3;
  --letter-spacing-heading: 0;

  /* Section — 14px / 600 / 1.4 / 0 (Sticky section headers) */
  --font-size-section: 14px;
  --font-weight-section: 600;
  --line-height-section: 1.4;
  --letter-spacing-section: 0;

  /* Body — 14px / 400 / 1.6 / 0 (Note content, descriptions) */
  --font-size-body: 14px;
  --font-weight-body: 400;
  --line-height-body: 1.6;
  --letter-spacing-body: 0;

  /* Body Strong — 14px / 500 / 1.6 / 0 (Emphasis within body) */
  --font-weight-body-strong: 500;

  /* Label — 13px / 500 / 1.4 / 0 (Vital sign labels, form labels) */
  --font-size-label: 13px;
  --font-weight-label: 500;
  --line-height-label: 1.4;
  --letter-spacing-label: 0;

  /* Caption — 12px / 400 / 1.4 / 0 (Timestamps, file sizes) */
  --font-size-caption: 12px;
  --font-weight-caption: 400;
  --line-height-caption: 1.4;
  --letter-spacing-caption: 0;

  /* Overline — 11px / 500 / 1.2 / 0.08em / uppercase (Entity type label) */
  --font-size-overline: 11px;
  --font-weight-overline: 500;
  --line-height-overline: 1.2;
  --letter-spacing-overline: 0.08em;

  /* Action — 13px / 500 / 1 / 0 (Ghost button text, inline links) */
  --font-size-action: 13px;
  --font-weight-action: 500;
  --line-height-action: 1;
  --letter-spacing-action: 0;

  /* ═══════════════════════════════════════════════════════
     LAYOUT PROPORTIONS — UI_SPEC.md exact specification
     ═══════════════════════════════════════════════════════ */

  /* Lens */
  --lens-max-width: 800px;
  --lens-hdr-h: 56px;  /* lens glass header (.lensHdr); the CEL-51 panel-mode Related layer sits under it */
  --lens-padding-desktop: 40px;
  --lens-padding-tablet: 24px;
  --lens-padding-mobile: 16px;
  --lens-body-max-line: 680px;

  /* Lens — wide variant for lenses that embed a rendered document
     (certificate lens, document lens). Use .lens-container-wide (defined in
     lens.css) or apply inline via style={{ maxWidth: 'var(--lens-max-width-wide)' }}.
     The viewer height adapts to viewport via clamp(min, preferred, max). */
  --lens-max-width-wide: 720px; /* prototype: ONE 720px record card for every lens (lens-base.css .lens-panel); name kept for its consumers */

  /* Record side panel geometry (CEL-51/52/65). The inputs live here once; the
     panel width formulas built from them are declared once, in the
     `:root, [data-shell-nav]` block below. TS twins: features/panel-stack/
     panelGeometry.ts (kept equal by panelGeometry.test.ts).
     --lens-card-w / -wide — the record card widths (lens.module.css .panel /
     --lens-max-width-wide), so at full width the record renders at exactly
     its page width.
     --list-keep-w — list kept visible beside one record.
     --list-keep-split-w — list kept beside a dragged panel.
     --filter-rail-w — the list's filter panel (FilterPanel.module.css .panel).
     --filter-rail-folded-w — the same panel folded to a strip beside an open
       record (CEL-65 item 6, FilterPanel.module.css .folded). */
  --lens-card-w:        720px;
  --lens-card-w-wide:   var(--lens-max-width-wide);
  --list-keep-w:        320px;
  --list-keep-split-w:  120px;
  --filter-rail-w:      268px;
  --filter-rail-folded-w: 44px;
  --lens-doc-viewer-h: clamp(480px, 70vh, 760px);
  --lens-doc-viewer-h-compact: clamp(280px, 42vh, 460px); /* viewer above a tab strip: keeps the tabs on screen */

  /* Sidebar */
  --sidebar-width: 420px;

  /* Search bar */
  --search-max-width: 720px;
  --search-height: 48px;

  /* Modal - SPEC: exact shadow value */
  --modal-max-width: 480px;
  --modal-padding: 32px;
  --modal-shadow: 0 25px 50px -12px rgba(0,0,0,0.4);

  /* Picker dialog — entity search modals (FaultPicker, PartPicker, EquipmentPicker) */
  --picker-max-w:        560px;  /* wider than standard modal to fit subtitle text */
  --picker-list-h:       440px;  /* results area ≈10 rows at 44px each */
  --picker-close-offset: -6px;   /* nudge header × to visual edge */
  --picker-qty-input-w:  72px;   /* qty number input in PartPicker footer */

  /* Settings modal — bespoke (not the shared <Modal/> primitive's 4-size
     scale), pixel-matched to settings-v4.html. ALE-892: values unchanged
     from the prior hardcoded literals, just token-ized. */
  --settings-modal-w:        547px;
  --settings-modal-min-h:    483px;  /* was a fixed height; now a floor — content can grow/scroll past it, never clipped below it */
  --settings-modal-header-h: 42px;
  --settings-modal-sidebar-w: 168px;

  /* Navigation header */
  --header-height: 56px;

  /* ═══════════════════════════════════════════════════════
     COMPONENT DIMENSIONS — UI_SPEC.md exact specification
     Touch targets: 44px minimum (Apple standard)
     ═══════════════════════════════════════════════════════ */

  /* Touch targets */
  --touch-target-min: 44px;
  --touch-target-mobile: 48px;

  /* Buttons */
  --button-height-ghost: 36px;
  --button-height-primary: 36px;
  --button-padding-ghost-x: 12px;
  --button-padding-ghost-y: 8px;
  --button-padding-primary-x: 24px;
  --button-padding-primary-y: 12px;
  --button-icon-only-size: 32px;

  /* Status pill */
  --pill-height: 24px;
  --pill-padding-x: 12px;
  --pill-padding-y: 4px;
  --pill-dot-size: 6px;

  /* Compact status/severity pill metrics — used by the shared Pill
     component at features/entity-list/lib/pill.tsx for tabulated lens
     column cells (work-orders, faults, equipment, and — post-PR-C —
     purchasing, receiving, certificates). Distinct from the larger
     nav-style --pill-* tokens above (24px / 6px radius). These are
     dimension tokens (not theme tokens), so they share the :root block
     and have identical values across dark/light. */
  --pill-compact-height:         20px;
  --pill-compact-padding-x:      7px;
  --pill-compact-padding-y:      0;
  --pill-compact-radius:         3px;
  --pill-compact-font-size:      var(--font-size-overline);   /* M6: 9.5/600 at 18px → 11/500 at 20px */
  --pill-compact-font-weight:    500;
  --pill-compact-letter-spacing: 0.04em;

  /* Inputs */
  --input-height: 36px;
  --input-padding-x: 12px;
  --input-padding-y: 10px;
  /* Textarea min-height — CEO 2026-05-28 popup-uniformity sweep consolidated the
     drifted 70–100px inline textareas to one shared token (~3 lines at the
     line-height:1.5 used by FormTextarea + input padding). Consumed by
     FormTextarea.module.css. */
  --textarea-min-height: 88px;

  /* Section header */
  --section-header-height: 44px;

  /* List row */
  --list-row-min-height: 44px;
  --list-row-padding-y: 12px;
  --list-row-padding-x: 20px;

  /* Vital signs row */
  --vital-signs-height: 40px;

  /* Cards */
  --card-padding-x: 20px;
  --card-padding-y: 16px;

  /* File preview card */
  --file-preview-height: 48px;

  /* Media preview */
  --media-preview-max-height: 240px;

  /* Toast */
  --toast-max-width: 400px;
  --toast-padding: 16px;

  /* Gaps */
  --gap-sections: 24px;
  --gap-title-vitals: 12px;
  --gap-overline-title: 4px;
  --gap-section-content: 12px;
  --gap-vital-items: 16px;

}

/* Record side panel widths (CEL-51/52/65), declared ONCE. A var() inside a
   custom property resolves where it is declared, so the rule also matches the
   shell root: CEL-52's shell root sets its own nav width (236px under
   sidebar_v2, or the user's dragged width) and marks itself data-shell-nav,
   and the widths there follow THAT nav width, not :root's 192px.
   --lens-panel-w / -wide — one record; on narrower screens the panel gives way
   so --list-keep-w of the list stays visible.
   Side by side and Full width have no token: they span nav edge to screen
   edge with the list behind (PanelStackHost panelStyle, CEL-65). A
   user-dragged width replaces both (capped so --list-keep-split-w stays).
   --list-rail-w — the list's filter panel (CEL-53, when shown) sits between the
   nav and the list, so the room kept for the list starts after it: without
   that a wide record (certificate, document) left the table a 52px strip at
   1600px — only the row checkboxes showed and no second row could be opened.
   It is unset (0px) unless the rules below apply; browsers without :has()
   keep 0px. While a record is open and the full panel would leave the list
   under --list-keep-w, the panel folds to a strip (CEL-65 item 6,
   useFilterRailFold), and the record keeps its card width. */
:root, [data-shell-nav] {
  --lens-panel-w:       min(var(--lens-card-w), calc(100vw - var(--shell-sidebar-w) - var(--list-rail-w, 0px) - var(--list-keep-w)));
  --lens-panel-w-wide:  min(var(--lens-card-w-wide), calc(100vw - var(--shell-sidebar-w) - var(--list-rail-w, 0px) - var(--list-keep-w)));
}
[data-shell-nav]:has([data-list-rail]) {
  --list-rail-w:        var(--filter-rail-w);
}
[data-shell-nav]:has([data-list-rail="folded"]) {
  --list-rail-w:        var(--filter-rail-folded-w);
}

/* ═══════════════════════════════════════════════════════
   ANIMATIONS
   Component-level keyframes for UI elements
   ═══════════════════════════════════════════════════════ */

/* Toast slide up + fade in animation */
@keyframes toast-in {
  0% {
    opacity: 0;
    transform: translateX(-50%) translateY(12px);
  }
  100% {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
  }
}

.animate-toast-in {
  animation: toast-in 200ms var(--ease-out) forwards;
}

/* ═══════════════════════════════════════════════════════════════════════════
   TYPOGRAPHY UTILITY CLASSES — UI_SPEC.md exact specification
   Usage: class="text-display", class="text-title", etc.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Display — Lens title on mobile when space is tight */
.text-display {
  font-size: var(--font-size-display);
  font-weight: var(--font-weight-display);
  line-height: var(--line-height-display);
  letter-spacing: var(--letter-spacing-display);
  color: var(--text-primary);
}

/* Title — Entity name / lens title (largest text on screen) */
.text-title {
  font-size: var(--font-size-title);
  font-weight: var(--font-weight-title);
  line-height: var(--line-height-title);
  letter-spacing: var(--letter-spacing-title);
  color: var(--text-primary);
}

/* Heading — Major section breaks if needed. .page-title = the one list-page <h1> role (lens entity titles use .text-title). */
.text-heading,
.page-title {
  font-size: var(--font-size-heading);
  font-weight: var(--font-weight-heading);
  line-height: var(--line-height-heading);
  letter-spacing: var(--letter-spacing-heading);
  color: var(--text-primary);
}

/* Section — Sticky section headers (Notes, Parts, History) */
.text-section {
  font-size: var(--font-size-section);
  font-weight: var(--font-weight-section);
  line-height: var(--line-height-section);
  letter-spacing: var(--letter-spacing-section);
  color: var(--text-secondary);
}

/* Body — Note content, descriptions, general text */
.text-body {
  font-size: var(--font-size-body);
  font-weight: var(--font-weight-body);
  line-height: var(--line-height-body);
  letter-spacing: var(--letter-spacing-body);
  color: var(--text-primary);
}

/* Body Strong — Emphasis within body text (use sparingly) */
.text-body-strong {
  font-size: var(--font-size-body);
  font-weight: var(--font-weight-body-strong);
  line-height: var(--line-height-body);
  letter-spacing: var(--letter-spacing-body);
  color: var(--text-primary);
}

/* Label — Vital sign labels, form labels, metadata labels */
.text-label {
  font-size: var(--font-size-label);
  font-weight: var(--font-weight-label);
  line-height: var(--line-height-label);
  letter-spacing: var(--letter-spacing-label);
  color: var(--text-secondary);
}

/* Caption — Timestamps, file sizes, secondary metadata */
.text-caption {
  font-size: var(--font-size-caption);
  font-weight: var(--font-weight-caption);
  line-height: var(--line-height-caption);
  letter-spacing: var(--letter-spacing-caption);
  color: var(--text-tertiary);
}

/* Overline — Entity type label (WORK ORDER, FAULT, CERTIFICATE) */
.text-overline {
  font-size: var(--font-size-overline);
  font-weight: var(--font-weight-overline);
  line-height: var(--line-height-overline);
  letter-spacing: var(--letter-spacing-overline);
  text-transform: uppercase;
  color: var(--text-tertiary);
}

/* Action — Ghost button text, inline action links */
.text-action {
  font-size: var(--font-size-action);
  font-weight: var(--font-weight-action);
  line-height: var(--line-height-action);
  letter-spacing: var(--letter-spacing-action);
  color: var(--brand-interactive);
}

/* ═══════════════════════════════════════════════════════════════════════════
   BUTTON COMPONENT CLASSES — UI_SPEC.md exact specification
   ═══════════════════════════════════════════════════════════════════════════ */

/* Ghost Button - uses secondary style per spec (no tertiary buttons) */
.btn-ghost {
  background: transparent;
  color: var(--text-primary);
  font-size: var(--font-size-action);
  font-weight: 500;
  padding: 0 12px;
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  height: 36px;
  min-height: 36px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: background var(--duration-fast) var(--ease-out);
}

.btn-ghost:hover {
  background: var(--btn-ghost-hover-bg);
}

.btn-ghost:active {
  opacity: 0.9;
}

.btn-ghost:disabled {
  color: var(--text-disabled);
  cursor: not-allowed;
  background: transparent;
}

/* Primary Button - SPEC: 36px height, 10px radius, 500 weight */
.btn-primary {
  background: var(--btn-primary-bg);
  color: var(--btn-primary-text);
  font-size: var(--font-size-body);
  font-weight: 500;
  padding: 0 12px;
  border-radius: var(--radius-md);
  border: 1px solid var(--btn-primary-border);
  height: 36px;
  min-height: 36px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: opacity var(--duration-fast) var(--ease-out);
}

.btn-primary:hover {
  opacity: 0.9;
}

.btn-primary:active {
  opacity: 0.85;
}

.btn-primary:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Secondary Button - SPEC: transparent bg, border-default, hover bg-highlight */
.btn-secondary {
  background: transparent;
  color: var(--text-primary);
  font-size: var(--font-size-body);
  font-weight: 500;
  padding: 0 12px;
  border-radius: var(--radius-md);
  border: 1px solid var(--btn-secondary-border);
  height: 36px;
  min-height: 36px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: background var(--duration-fast) var(--ease-out);
}

.btn-secondary:hover {
  background: var(--btn-secondary-hover-bg);
}

/* Danger Button */
.btn-danger {
  background: var(--btn-danger-bg);
  color: var(--btn-danger-text);
  font-size: var(--font-size-action);
  font-weight: 500;
  padding: 0 12px;
  border: 1px solid var(--btn-danger-bg);
  border-radius: var(--radius-md);
  height: 36px;
  min-height: 36px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: background var(--duration-fast) var(--ease-out);
}

.btn-danger:hover {
  background: var(--btn-danger-hover-bg);
  border-color: var(--btn-danger-hover-bg);
}

/* Danger confirmation state */
.btn-danger-confirm {
  background: var(--btn-danger-bg);
  color: var(--btn-danger-text);
  border-color: var(--btn-danger-bg);
}

/* ───────────────────────────────────────────────────────────────────────
   Three-tier brand button system (CEO 2026-05-15 design pass).
   Every popup gets ONE solid teal commit, optional hollow teal secondary
   (Save Draft / Save & Close / Select File), and ghost/quiet for exits.
   "Radius and overlay weight scale with gravity — radius is information,
   not decoration." See docs/popup-visual-discipline-2026-05-15.md.
   ─────────────────────────────────────────────────────────────────────── */

/* SOLID teal — the single commit per popup. THE ONLY VARIANT WITH DEPTH.
   Spec: popup-preview-2026-05-15-buttons.html §03 Solid.
   Machined-metal feel: micro vertical gradient (~3% top/bottom shift) +
   1px inner top highlight + hairline darker edge + 1px drop shadow.
   The depth is felt, not seen. Catches imaginary overhead light like
   a polished metal button on a yacht bridge. */
.btn-teal-solid {
  background: var(--btn-solid-top);
  color: var(--on-solid, #fff);
  font-size: var(--font-size-action);
  font-weight: var(--font-weight-body-strong);
  padding: 0 var(--space-4);
  border: 1px solid var(--btn-solid-edge);
  border-radius: var(--radius-md);
  height: 36px;
  min-height: 36px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  white-space: nowrap;
  transition:
    background var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out);
}
.btn-teal-solid:hover {
  background: var(--btn-solid-top-hover);
  border-color: var(--btn-solid-edge-hover);
}
.btn-teal-solid:active {
  background: var(--btn-solid-bottom);
  box-shadow: var(--btn-solid-press);
  transform: translateY(0.5px);
}
.btn-teal-solid:disabled {
  background: var(--surface-raised, var(--surface-hover));
  color: var(--text-disabled);
  border-color: var(--border-sub);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.04);
  cursor: not-allowed;
}

/* HOLLOW teal — secondary-but-positive (Save Draft, Save & Close,
   Select File). Brand identity in the action without competing with
   the primary commit. Background stays transparent until hover. */
.btn-teal-hollow {
  background: transparent;
  color: var(--btn-color);
  font-size: var(--font-size-action);
  font-weight: var(--font-weight-body-strong);
  padding: 0 var(--space-4);
  border: 1px solid var(--btn-color-border);
  border-radius: var(--radius-md);
  height: 36px;
  min-height: 36px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  white-space: nowrap;
  transition:
    background var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out);
}
.btn-teal-hollow:hover {
  background: var(--btn-color-bg);
  border-color: var(--btn-color);
}
.btn-teal-hollow:active   { background: var(--btn-color-bg-hover); }
.btn-teal-hollow:disabled {
  color: var(--text-disabled);
  border-color: var(--border-sub);
  background: transparent;
  cursor: not-allowed;
}

/* Quiet ghost — cancel / discard / keep-editing. No border tint, just
   secondary text. Replaces the colourless btn-outline pattern that
   made "save my work" and "cancel" feel like the same neutral gesture. */
.btn-quiet {
  background: transparent;
  color: var(--txt3);
  font-size: var(--font-size-action);
  font-weight: var(--font-weight-body);
  padding: 0 var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  height: 36px;
  min-height: 36px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: color var(--duration-fast) var(--ease-out);
}
.btn-quiet:hover    { color: var(--txt); }
.btn-quiet:disabled { opacity: 0.5; cursor: not-allowed; }

/* HOLLOW red — the one place red appears as affordance (ConfirmDialog
   danger variant only). Brand value Calm Under Stress: critical signal
   without alarm SaaS. Status colours never become solid fills. */
.btn-danger-hollow {
  background: transparent;
  color: var(--red);
  font-size: var(--font-size-action);
  font-weight: var(--font-weight-body-strong);
  padding: 0 var(--space-4);
  border: 1px solid var(--red-border);
  border-radius: var(--radius-md);
  height: 36px;
  min-height: 36px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: background var(--duration-fast) var(--ease-out);
}
.btn-danger-hollow:hover    { background: var(--red-bg); }
.btn-danger-hollow:disabled { opacity: 0.5; cursor: not-allowed; }

/* Icon-Only Button (close, back, forward, settings) */
.btn-icon {
  width: var(--button-icon-only-size);
  height: var(--button-icon-only-size);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out);
}

.btn-icon:hover {
  background: var(--surface-hover);
  color: var(--text-primary);
}

.btn-icon svg {
  width: 18px;
  height: 18px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   STATUS PILL CLASSES — UI_SPEC.md exact specification
   ═══════════════════════════════════════════════════════════════════════════ */

.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: var(--pill-padding-y) var(--pill-padding-x);
  border-radius: var(--radius-pill);
  font-size: var(--font-size-caption);
  font-weight: var(--font-weight-action);
  height: var(--pill-height);
}

.status-pill-neutral {
  background: var(--status-neutral-bg);
  color: var(--status-neutral);
}

.status-pill-warning {
  background: var(--status-warning-bg);
  color: var(--status-warning);
}

.status-pill-success {
  background: var(--status-success-bg);
  color: var(--status-success);
}

.status-pill-critical {
  background: var(--status-critical-bg);
  color: var(--status-critical);
}

/* Status dot (prefix for pills) */
.status-dot {
  width: var(--pill-dot-size);
  height: var(--pill-dot-size);
  border-radius: 50%;
  flex-shrink: 0;
}

.status-dot-neutral {
  background: var(--status-neutral);
}

.status-dot-warning {
  background: var(--status-warning);
}

.status-dot-success {
  background: var(--status-success);
}

.status-dot-critical {
  background: var(--status-critical);
}

/* ═══════════════════════════════════════════════════════════════════════════
   INPUT CLASSES — UI_SPEC.md exact specification
   ═══════════════════════════════════════════════════════════════════════════ */

.input-field {
  height: 36px;                    /* SPEC: 36px (h-9), shared with buttons */
  min-height: 36px;
  padding: 0 12px;
  font-size: var(--font-size-body);
  font-weight: var(--font-weight-body);
  color: var(--text-primary);
  background: var(--surface-base);
  border: 1px solid var(--border-control);
  border-radius: var(--radius-md);
  width: 100%;
  transition: border-color var(--duration-fast) var(--ease-out),
              box-shadow var(--duration-fast) var(--ease-out);
}

.input-field::placeholder {
  color: var(--txt-meta);
}

.input-field:focus {
  border-color: var(--brand-interactive);
  outline: none;
  box-shadow: 0 0 0 3px var(--brand-muted);
}

.input-field-error {
  border-color: var(--status-critical);
  box-shadow: 0 0 0 3px var(--status-critical-bg);
}

.input-field:disabled {
  background: var(--surface-hover);
  color: var(--text-disabled);
  cursor: not-allowed;
}

/* Textarea */
.textarea-field {
  min-height: 100px;
  padding: var(--input-padding-y) var(--input-padding-x);
  font-size: var(--font-size-body);
  font-weight: var(--font-weight-body);
  line-height: var(--line-height-body);
  color: var(--text-primary);
  background: var(--surface-base);
  border: 1px solid var(--border-control);
  border-radius: var(--radius-md);
  width: 100%;
  resize: vertical;
  transition: border-color var(--duration-fast) var(--ease-out),
              box-shadow var(--duration-fast) var(--ease-out);
}

.textarea-field:focus {
  border-color: var(--brand-interactive);
  outline: none;
  box-shadow: 0 0 0 3px var(--brand-muted);
}

/* ═══════════════════════════════════════════════════════════════════════════
   CARD CLASSES — UI_SPEC.md exact specification
   ═══════════════════════════════════════════════════════════════════════════ */

/* Section Container (building block of every lens) */
.section-container {
  background: var(--surface-primary);
  border-radius: var(--radius-md);
  overflow: hidden;
  margin-bottom: var(--gap-sections);
}

/* Entity Card (in lists: parts, equipment, search results) */
.entity-card {
  background: var(--surface-primary);
  border-radius: var(--radius-md);
  padding: var(--card-padding-y) var(--card-padding-x);
  min-height: var(--touch-target-min);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out);
}

.entity-card:hover {
  background: var(--surface-hover);
}

/* File Preview Card (documents, not media) */
.file-preview-card {
  background: var(--surface-primary);
  border-radius: var(--radius-md);
  padding: 12px 16px;
  height: var(--file-preview-height);
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out);
}

.file-preview-card:hover {
  background: var(--surface-hover);
}

.file-preview-card .file-icon {
  width: 20px;
  height: 20px;
  color: var(--text-tertiary);
  flex-shrink: 0;
}

.file-preview-card .file-name {
  font-size: var(--font-size-body);
  font-weight: var(--font-weight-action);
  color: var(--text-primary);
}

.file-preview-card .file-size {
  font-size: var(--font-size-caption);
  font-weight: var(--font-weight-caption);
  color: var(--text-tertiary);
}

/* ═══════════════════════════════════════════════════════════════════════════
   LAYOUT UTILITY CLASSES — UI_SPEC.md exact specification
   ═══════════════════════════════════════════════════════════════════════════ */

/* Lens container */
.lens-container {
  max-width: var(--lens-max-width);
  margin: 0 auto;
  padding-left: var(--lens-padding-desktop);
  padding-right: var(--lens-padding-desktop);
}

@media (max-width: 1024px) {
  .lens-container {
    padding-left: var(--lens-padding-tablet);
    padding-right: var(--lens-padding-tablet);
  }
}

@media (max-width: 768px) {
  .lens-container {
    padding-left: var(--lens-padding-mobile);
    padding-right: var(--lens-padding-mobile);
  }
}

/* Body text max width (readability: ~75 chars) */
.text-readable {
  max-width: var(--lens-body-max-line);
}

/* Touch target enforcement */
.touch-target {
  min-height: var(--touch-target-min);
}

@media (max-width: 768px) {
  .touch-target {
    min-height: var(--touch-target-mobile);
  }
}

/* Section spacing */
.section-gap {
  margin-bottom: var(--gap-sections);
}

/* List row base */
.list-row {
  min-height: var(--list-row-min-height);
  padding: var(--list-row-padding-y) var(--list-row-padding-x);
}

/* Vital signs row */
.vital-signs {
  height: var(--vital-signs-height);
  display: flex;
  align-items: center;
  gap: var(--gap-vital-items);
}

/* ═══════════════════════════════════════════════════════════════════════════
   SKELETON LOADING — UI_SPEC.md specification
   Use everywhere instead of spinners
   ═══════════════════════════════════════════════════════════════════════════ */

.skeleton {
  background: var(--surface-hover);
  border-radius: var(--radius-sm);
  animation: shimmer 1.5s ease-in-out infinite;
}

@keyframes shimmer {
  0% { opacity: 0.5; }
  50% { opacity: 0.8; }
  100% { opacity: 0.5; }
}

/* Skeleton shapes per UI_SPEC */
.skeleton-title {
  width: 60%;
  height: 24px;
}

.skeleton-body-line {
  width: 100%;
  height: 14px;
}

.skeleton-vital-signs {
  width: 80%;
  height: 20px;
}

.skeleton-section-header {
  width: 40%;
  height: 14px;
}

.skeleton-entity-card {
  width: 100%;
  height: 56px;
}

.skeleton-media-preview {
  width: 100%;
  height: 160px;
}

.skeleton-status-pill {
  width: 64px;
  height: var(--pill-height);
  border-radius: var(--radius-pill);
}

/* ═══════════════════════════════════════════════════════════════════════════
   SPOTLIGHT TOKENS — Raycast-inspired panel (additive, zero overrides)
   ═══════════════════════════════════════════════════════════════════════════ */

:root, [data-theme="dark"] {
  /* Panel elevation — deeper than modal-shadow to float off dark backgrounds */
  --spotlight-shadow: 0 16px 70px rgba(0, 0, 0, 0.55), 0 4px 16px rgba(0, 0, 0, 0.35);
  /* Shine sweep — visible only in dark mode */
  --spotlight-shine-opacity: 1;
  --spotlight-shine-duration: 2s;
  /* Loader sweep color — brand teal */
  --spotlight-loader-color: var(--brand-interactive);
  /* Footer bar */
  --spotlight-footer-height: 40px;
  --spotlight-footer-bg: var(--surface-elevated);
  --spotlight-footer-border: var(--surface-border);
  /* kbd badge */
  --spotlight-kbd-bg: var(--surface-active);
  --spotlight-kbd-color: var(--text-secondary);
  --spotlight-kbd-radius: 4px;
}

[data-theme="light"] {
  /* Lighter shadow in light mode (Apple barely-there) */
  --spotlight-shadow: 0 16px 70px rgba(0, 0, 0, 0.12), 0 4px 16px rgba(0, 0, 0, 0.06);
  /* No shine in light mode */
  --spotlight-shine-opacity: 0;
  --spotlight-shine-duration: 0s;
  --spotlight-footer-bg: var(--surface-elevated);
  --spotlight-footer-border: var(--surface-border);
  --spotlight-kbd-bg: var(--surface-hover);
  --spotlight-kbd-color: var(--text-tertiary);
}

/* ─── Spotlight keyframes ─── */

@keyframes spotlight-shine {
  0%   { background-position: -200% center; opacity: var(--spotlight-shine-opacity); }
  60%  { opacity: var(--spotlight-shine-opacity); }
  100% { background-position: 200% center;  opacity: 0; }
}

@keyframes spotlight-loader {
  0%   { opacity: 0; transform: translateX(-100%); }
  40%  { opacity: 1; }
  60%  { opacity: 1; }
  100% { opacity: 0; transform: translateX(200%); }
}

@keyframes spotlight-in {
  0%   { opacity: 0; transform: translateY(-4px) scale(0.99); }
  100% { opacity: 1; transform: translateY(0)    scale(1);    }
}
