/* SAIP design system — Phase 67E (liquid glass).
 *
 * Scoped to .lp-root: only the public landing page applies these tokens
 * so the existing authenticated app surfaces are untouched in 67E.
 * Phase 67F will widen the scope after the inner-app polish pass.
 *
 * No third-party CSS · no preprocessor · native CSS custom properties.
 */

:root {
  /* Brand palette */
  --saip-navy-900: #08152B;
  --saip-navy-800: #0B1A33;
  --saip-navy-700: #13294D;
  --saip-slate-600: #3F5C8A;
  --saip-slate-400: #6F88B0;
  --saip-ice-100: #F4F7FB;
  --saip-ice-50: #FBFCFE;
  --saip-ice-0: #FFFFFF;
  --saip-teal-500: #1FA8AB;
  --saip-teal-600: #147A7C;
  --saip-teal-50: #E5F6F6;
  --saip-amber-500: #D88E2F;
  --saip-amber-50: #FBEFD8;
  --saip-rose-500: #C45163;
  --saip-rose-50: #F8DDE2;
  --saip-green-500: #2BA46E;
  --saip-green-50: #DEF4E8;
  --saip-grey-700: #2B3441;
  --saip-grey-500: #5A6477;
  --saip-grey-400: #5E6B82; /* muted text — DARKENED for WCAG AA (was #76839A ≈ 3.4-3.8:1; now ≈ 4.5:1 on ice-100). W0 a11y floor G1. */
  --saip-grey-300: #C8CFDA;
  --saip-grey-200: #E2E7EE;
  --saip-grey-100: #EEF0F2;  /* light fill / hairline surface */
  --saip-grey-50:  #F8FAFC;  /* lightest surface tint */
  --saip-grey-600: #57606A;  /* muted text, one step darker than 500 (AA ≈ 6.5:1 on white) */
  --saip-white:    #FFFFFF;  /* alias of ice-0 for legacy call sites */
  --saip-navy-50:  var(--saip-grey-100);  /* lightest navy tint — alias to grey-100 (matches prior fallback) */

  /* W0 token-integrity (2026-06-28, Design Council audit) — these names were
     referenced by ~306 call sites as var(--token,#hex) fallbacks but were never
     DEFINED, so the system silently rendered the hardcoded hex (the "assembled,
     not engineered" root cause). Defining them makes the token file the actual
     single source of truth. Values match the dominant prior fallback so the
     appearance is preserved (except grey-400, darkened above for AA). */
  --saip-green-100: #E6F6EC;  /* success wash */
  --saip-green-700: #1D7A3F;  /* success text (AA ≈ 4.8:1 on white) */
  --saip-red-500:   var(--saip-rose-500);  /* semantic alias */
  --saip-red-100:   #FDE6E6;  /* danger wash */
  --saip-red-700:   #A11D1D;  /* danger text (AA ≈ 6.4:1 on white) */
  --saip-amber-600: #9A6700;  /* warning text (AA ≈ 4.9:1 on white) — W4 residual: was referenced undefined in standards_kb.css */
  --saip-amber-700: #9A6700;  /* warning text (AA ≈ 4.9:1 on white) */
  --saip-blue-100:  #E6EFFB;  /* info wash */
  --saip-blue-700:  #1C52A8;  /* info text (AA ≈ 6.9:1 on white, ≈ 6.3:1 on blue-100) */
  --saip-navy-200:  #C6DAFC;  /* light info border/fill */
  --saip-navy-300:  #A8C7FA;  /* light info border (decorative, non-text) */
  --saip-navy-400:  var(--saip-slate-600);  /* real palette navy (removes the stray #4a7fd0 blue) */
  --saip-mono:      var(--saip-font-mono);  /* alias for font-family call sites */

  /* W4B token-system closure (2026-06-29) — the safe, bounded --saip-* slice.
     Each name below was referenced as var(--token,#hex) with no :root entry,
     so the system rendered the hardcoded fallback. Defining them makes the
     token file the source of truth. Values match the dominant prior fallback
     unless an AA-safe shift is noted. */
  --saip-grey-800:  #24292F;  /* darkest grey text (AA ≈ 13:1 on white) */
  --saip-slate-700: #2F3B4C;  /* deep slate body text (AA ≈ 9.7:1 on white) */
  --saip-green-600: #1A7F37;  /* success text/fill, one step darker than 500 (AA ≈ 4.8:1 on white) */
  --saip-amber-100: #FDF0D5;  /* warning wash (between amber-50 and amber-500) */
  --saip-color-warn: var(--saip-amber-500);  /* semantic warn alias (was undefined #b66; amber is the system warn hue) */
  --saip-danger-600: var(--saip-red-700);    /* semantic danger-text alias (canonical AA red text) */
  --saip-red-600:    var(--saip-red-700);    /* semantic danger-text alias (canonical AA red text) */
  --saip-font-sans:  var(--saip-font-ui);    /* alias for legacy font-family call site */
  --saip-glass-light: rgba(255, 255, 255, 0.65);
  --saip-glass-dark: rgba(11, 26, 51, 0.55);
  --saip-glass-border: rgba(255, 255, 255, 0.18);

  /* Gradients */
  --saip-gradient-hero: radial-gradient(circle at 18% 12%, #16315e 0%, #0b1a33 38%, #08152b 100%);
  --saip-gradient-card-light: linear-gradient(135deg, rgba(255, 255, 255, 0.85) 0%, rgba(244, 247, 251, 0.55) 100%);
  --saip-gradient-card-dark: linear-gradient(135deg, rgba(31, 168, 171, 0.18) 0%, rgba(11, 26, 51, 0.55) 100%);
  --saip-gradient-cta-primary: linear-gradient(135deg, #1FA8AB 0%, #147A7C 100%);
  --saip-gradient-cta-navy: linear-gradient(135deg, #13294D 0%, #08152B 100%);

  /* Spacing scale */
  --saip-spacing-1: 4px;
  --saip-spacing-2: 8px;
  --saip-spacing-3: 12px;
  --saip-spacing-4: 16px;
  --saip-spacing-5: 24px;
  --saip-spacing-6: 32px;
  --saip-spacing-7: 48px;
  --saip-spacing-8: 64px;
  --saip-spacing-9: 96px;

  /* Layout */
  --saip-container-max: 1180px;
  --saip-gutter: 24px;

  /* Radii */
  --saip-radius-sm: 8px;
  --saip-radius-md: 10px;  /* step between sm (8px) and base (12px) — was undefined */
  --saip-radius: 12px;
  --saip-radius-lg: 16px;
  --saip-radius-xl: 24px;

  /* Elevation */
  --saip-shadow-sm: 0 2px 8px rgba(11, 26, 51, 0.06);
  --saip-shadow-md: 0 8px 32px rgba(11, 26, 51, 0.08);
  --saip-shadow-lg: 0 16px 48px rgba(11, 26, 51, 0.14);
  /* Enterprise redesign (HANDOFF §2.2) — soft card shadow + row-hover tint */
  --saip-shadow-card: 0 1px 4px rgba(11, 26, 51, 0.05);
  --saip-row-hover: rgba(31, 168, 171, 0.045);

  /* Surface blur */
  --saip-blur-card: blur(18px);
  --saip-blur-modal: blur(28px);

  /* Typography fallback (Inter / Source Serif Pro shipped in 67F when self-hosted woff2
   * land; for 67E we use the OS sans-serif stack with a Source Serif Pro hint that
   * falls back gracefully). */
  --saip-font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Helvetica, Arial, system-ui, sans-serif;
  --saip-font-serif: "Source Serif Pro", "Source Serif 4", Georgia, "Times New Roman", serif;
  --saip-font-mono: "JetBrains Mono", Menlo, Consolas, monospace;

  /* W5 typography consistency (Sponsor 2026-06-18) — single canonical type
   * scale. Every text size site-wide snaps to one of these steps so the same
   * semantic element renders at one size across pages/sections. The values
   * are the charter sizes already in use; the scale just NAMES them so future
   * work references a token instead of inventing a raw px (the root cause of
   * the 8/9/10/10.5/11/11.5/12/12.5/13/14/16/20 spread the Sponsor saw). */
  --saip-text-2xs: 10px;   /* micro labels, count pills, field labels */
  --saip-text-xs: 11px;    /* small uppercase labels, muted captions, pills */
  --saip-text-sm: 12px;    /* secondary text, meta, breadcrumbs, helper text */
  --saip-text-base: 13px;  /* table cells, dense body, nav, buttons */
  --saip-text-md: 14px;    /* default body text (.app-root base) */
  --saip-text-lg: 15px;    /* section/card titles (.app-sec-title) */
  --saip-text-h3: 16px;    /* h3 */
  --saip-text-h2: 18px;    /* h2 */
  --saip-text-h1: 24px;    /* h1 (page title in chrome) */
  --saip-text-xl: 26px;    /* large numeric / progress percent */
  --saip-text-2xl: 34px;   /* hero stat value */
  --saip-text-3xl: 40px;   /* display hero lockup (e.g. /clause console title) */
  /* Mono / value sizes — code, hex, monospaced values only. */
  --saip-text-mono: 12.5px;
  --saip-text-mono-sm: 11px;

  /* M22-BRAND-02-R1 — brand logo sizing tokens (folded in from the former
   * second :root block so the design system has ONE token root). */
  --ps-logo-app-header: 44px;   /* enlarged brand lockup — prominent navy header mark */
  --ps-logo-app-header-mobile: 34px;
  --clause-mark-panel: 30px;    /* embedded Clause panel header */
  --clause-mark-console: 40px;  /* /clause page lead */

  /* ============================================================
     Wave-0 SEMANTIC token layer (--ps-*) — the theme-swappable tier.
     The primitives above are the raw palette; the names below name
     colours by ROLE, so every surface consumes ONE source of truth and
     dark mode (Wave 2) is just a SECOND mapping of the SAME names via
     [data-theme]. Brand chrome (navy/teal on header/nav/hero) keeps the
     primitives directly. Light values here match the current appearance
     (brief 02 · field-test 2026-07-01 · Design Council: visual-design-lead).
     ============================================================ */
  /* Surface & text */
  --ps-bg-canvas:        var(--saip-ice-100);
  --ps-bg-surface:       var(--saip-ice-0);
  --ps-bg-surface-muted: var(--saip-ice-50);
  --ps-bg-inset:         var(--saip-ice-50);
  --ps-bg-table-head:    var(--saip-ice-50);
  --ps-text-primary:     var(--saip-slate-700);
  --ps-text-heading:     var(--saip-navy-900);
  --ps-text-secondary:   var(--saip-grey-600);
  --ps-text-muted:       var(--saip-grey-400);
  --ps-border-hairline:  var(--saip-grey-200);
  --ps-border-strong:    var(--saip-grey-300);
  /* Composer / primary-input border — the page's most important control needs
     a NON-text border >= 3:1 vs the surface (WCAG 1.4.11). --ps-border-strong
     (grey-300 ~1.57:1 on white) fails; slate-400 (#6F88B0) is ~3.66:1 on white
     / surface-muted. Dark maps onto --psd-border-input (below). Guarded by
     tests/web/test_ps_token_contrast_aa.py (test_input_border_token_visible). */
  --ps-border-input:     var(--saip-slate-400);
  /* FT-W2-DARK-SWEEP-01 — three role tokens the pillar stylesheets consumed as
     RAW primitives (recessed neutral fill · brand-navy heading/label/mono-id ·
     slate secondary text). Light values are BYTE-identical to the primitives
     they replace (grey-100 · navy-700 · slate-600) so no light-mode colour
     shifts; the dark map (below) repaints all three. Dark pairings are
     WCAG-AA computed + guarded (tests/web/test_ps_token_contrast_aa.py). */
  --ps-bg-fill:            var(--saip-grey-100);
  --ps-text-heading-brand: var(--saip-navy-700);
  --ps-text-slate:         var(--saip-slate-600);
  --ps-link:             var(--saip-teal-600);
  --ps-accent:           var(--saip-teal-500);
  --ps-shadow-card:      var(--saip-shadow-card);
  --ps-focus-ring:       var(--saip-teal-600); /* FT-DC-PILL-CONTRAST-AA-01: teal-500 ≈2.90:1 vs white failed 1.4.11 (≥3:1); teal-600 ≈5.12:1 */
  /* Severity — ONE canonical set (HANDOFF §2.7). fg · bg · bd
     FT-DC-PILL-CONTRAST-AA-01 (Design Council T9 a11y M6): the fg darks below
     are the WCAG-AA text ramp for 11px bold uppercase pill text (needs 4.5:1
     on the wash). Values reuse the ramp the product already shipped in the
     PE workspace badges (.pe-badge-*), which now CONSUME these tokens.
     Computed ratios (guarded by tests/web/test_ps_token_contrast_aa.py):
       critical on rose-50   ≈ 6.21:1 (was rose-500  ≈ 3.49:1)
       major    on amber-50  ≈ 5.09:1 (was amber-500 ≈ 2.36:1)
       minor    on amber-50  ≈ 4.94:1 (was old olive ≈ 2.52:1)
       pass     on green-50  ≈ 6.26:1 (was green-500 ≈ 2.74:1)
       info     teal-600 on teal-50  ≈ 4.59:1 (verified — kept)
       neutral  grey-500 on grey-200 ≈ 4.80:1 (verified — kept) */
  --ps-sev-critical-fg: #9E1C23;               --ps-sev-critical-bg: var(--saip-rose-50);  --ps-sev-critical-bd: #f0a8a0;
  --ps-sev-critical-solid-bg: #B03A4C;         /* solid pill bg — white text ≈ 5.91:1 (was rose-500 ≈ 4.46:1, borderline) */
  --ps-sev-major-fg:    #92580A;               --ps-sev-major-bg:    var(--saip-amber-50); --ps-sev-major-bd:    #f0c987;
  --ps-sev-minor-fg:    #7A6608;               --ps-sev-minor-bg:    var(--saip-amber-50); --ps-sev-minor-bd:    #ead7af;
  --ps-sev-pass-fg:     #156436;               --ps-sev-pass-bg:     var(--saip-green-50); --ps-sev-pass-bd:     #bcdcc4;
  --ps-sev-info-fg:     var(--saip-teal-600);  --ps-sev-info-bg:     var(--saip-teal-50);  --ps-sev-info-bd:     #b6dcdd;
  --ps-sev-neutral-fg:  var(--saip-grey-500);  --ps-sev-neutral-bg:  var(--saip-grey-200); --ps-sev-neutral-bd:  var(--saip-grey-300);
  /* Action-danger (destructive buttons) — AA on white; folds .app-btn-danger
     and the PE workspace .pe-ws-btn-danger onto ONE source of truth.
       fg on white ≈ 6.62:1 · white on bg ≈ 5.44:1 · white on bg-hover ≈ 6.62:1 */
  --ps-danger-fg:       #A93226;
  --ps-danger-bg:       #C0392B;
  --ps-danger-bd:       #A93226;
  --ps-danger-bg-hover: #A93226;
  /* Brand chrome — identical in light & dark (navy is already dark) */
  --ps-chrome-bg:      var(--saip-gradient-cta-navy);
  --ps-chrome-fg:      var(--saip-ice-0);
  --ps-chrome-fg-muted:var(--saip-slate-400);

  /* ============================================================
     FT-W2-APPEARANCE-PREF-01 — DARK-value primitives (--psd-*).
     Defined once here (raw hex lives in ONE place) and consumed by the
     two dark mapping blocks below, so the explicit-dark and system-dark
     maps can never drift value-wise. Navy-950-family canvas, surfaces one
     step lighter, ice/slate-light text — consistent with the navy/teal
     brand. Every text-bearing pair is WCAG-AA computed (guarded by the
     dark parametrisation in tests/web/test_ps_token_contrast_aa.py):
       text-primary on surface   #D7E1EF on #12233B = 11.97:1
       text-secondary on surface #A6B5CA on #12233B = 7.59:1
       text-muted on surface     #94A5BD on #12233B = 6.30:1 (canvas 7.25:1)
       link on surface           #5BC6C9 on #12233B = 7.80:1
       sev-critical fg/bg        #F2A6AC on #3D1A20 = 7.92:1
       sev-major    fg/bg        #ECB25E on #3A2A12 = 7.30:1
       sev-minor    fg/bg        #D9C35F on #34290F = 8.11:1
       sev-pass     fg/bg        #7ED0A2 on #10301F = 7.81:1
       sev-info     fg/bg        #64C9CC on #0E2C2D = 7.60:1
       sev-neutral  fg/bg        #B9C5D6 on #2A3850 = 6.75:1
       danger-fg on surface      #F0938B on #12233B = 6.96:1
       danger-bd vs surface      #E06055 on #12233B = 4.49:1 (non-text, >=3:1)
     Solid pill / danger-button backgrounds keep the light-mode values
     (white-on-solid ratios already AA: 5.91:1 / 5.44:1 / 6.62:1). */
  --psd-bg-canvas:        #0A1626;
  --psd-bg-surface:       #12233B;
  --psd-bg-surface-muted: #0E1C30;
  --psd-bg-inset:         #0E1C30;
  --psd-bg-table-head:    #16283F;
  --psd-text-primary:     #D7E1EF;
  --psd-text-heading:     #F4F7FB;
  --psd-text-secondary:   #A6B5CA;
  --psd-text-muted:       #94A5BD;
  --psd-border-hairline:  #263850;
  --psd-border-strong:    #3A5070;
  /* composer/primary-input border (non-text >= 3:1 vs the dark surfaces):
       #6E86A8 on #12233B = 4.19:1 · on #0E1C30 = 4.54:1 (both >= 3:1) */
  --psd-border-input:     #6E86A8;
  /* FT-W2-DARK-SWEEP-01 dark values (computed vs the dark surfaces):
       bg-fill        recessed fill (text-primary on it = 10.6:1,
                      text-secondary on it = 6.7:1)
       heading-brand  bright navy-tint on the dark surface = 11.5:1
       text-slate reuses --psd-text-secondary (7.59:1 on surface) — the
       light-mode slate-blue distinction is not preserved in dark (both
       secondary tiers converge to one legible light-grey). */
  --psd-bg-fill:            #1B2C46;
  --psd-text-heading-brand: #CBDDF7;
  --psd-link:             #5BC6C9;
  --psd-focus-ring:       #5BC6C9;
  --psd-shadow-card:      0 1px 4px rgba(0, 0, 0, 0.55);
  --psd-sev-critical-fg:  #F2A6AC;
  --psd-sev-critical-bg:  #3D1A20;
  --psd-sev-critical-bd:  #7C3038;
  --psd-sev-major-fg:     #ECB25E;
  --psd-sev-major-bg:     #3A2A12;
  --psd-sev-major-bd:     #7A5A28;
  --psd-sev-minor-fg:     #D9C35F;
  --psd-sev-minor-bg:     #34290F;
  --psd-sev-minor-bd:     #6E5E28;
  --psd-sev-pass-fg:      #7ED0A2;
  --psd-sev-pass-bg:      #10301F;
  --psd-sev-pass-bd:      #2C5E42;
  --psd-sev-info-fg:      #64C9CC;
  --psd-sev-info-bg:      #0E2C2D;
  --psd-sev-info-bd:      #2A5C5E;
  --psd-sev-neutral-fg:   #B9C5D6;
  --psd-sev-neutral-bg:   #2A3850;
  --psd-sev-neutral-bd:   #45577A;
  --psd-danger-fg:        #F0938B;
  --psd-danger-bd:        #E06055;
}

/* ============================================================
   FT-W2-APPEARANCE-PREF-01 — appearance modes (light / dark / system).
   base.html server-stamps <html data-theme="light|dark|system"> from the
   allowlist-validated saip_theme cookie (default system) — first paint is
   already correct, no head script. The dark SEMANTIC map applies under
   BOTH selector groups: explicit [data-theme="dark"], and
   [data-theme="system"] when the OS prefers dark. Brand chrome
   (--ps-chrome-*) is deliberately NOT remapped — the navy header/nav is
   identical in both modes per the charter. Pages that do not extend
   base.html (public landing, .lp-root/.hp-root) carry no data-theme and
   always render the light map. `color-scheme` keeps native widgets /
   scrollbars in step (design note FT-W2-APPEARANCE-PREF-01 section 5).
   ============================================================ */
:root { color-scheme: light; }
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }
:root[data-theme="system"] { color-scheme: light dark; }

:root[data-theme="dark"] {
  --ps-bg-canvas:        var(--psd-bg-canvas);
  --ps-bg-surface:       var(--psd-bg-surface);
  --ps-bg-surface-muted: var(--psd-bg-surface-muted);
  --ps-bg-inset:         var(--psd-bg-inset);
  --ps-bg-table-head:    var(--psd-bg-table-head);
  --ps-text-primary:     var(--psd-text-primary);
  --ps-text-heading:     var(--psd-text-heading);
  --ps-text-secondary:   var(--psd-text-secondary);
  --ps-text-muted:       var(--psd-text-muted);
  --ps-border-hairline:  var(--psd-border-hairline);
  --ps-border-strong:    var(--psd-border-strong);
  --ps-border-input:     var(--psd-border-input);
  --ps-bg-fill:            var(--psd-bg-fill);
  --ps-text-heading-brand: var(--psd-text-heading-brand);
  --ps-text-slate:         var(--psd-text-secondary);
  --ps-link:             var(--psd-link);
  --ps-focus-ring:       var(--psd-focus-ring);
  --ps-shadow-card:      var(--psd-shadow-card);
  --ps-sev-critical-fg:  var(--psd-sev-critical-fg);
  --ps-sev-critical-bg:  var(--psd-sev-critical-bg);
  --ps-sev-critical-bd:  var(--psd-sev-critical-bd);
  --ps-sev-major-fg:     var(--psd-sev-major-fg);
  --ps-sev-major-bg:     var(--psd-sev-major-bg);
  --ps-sev-major-bd:     var(--psd-sev-major-bd);
  --ps-sev-minor-fg:     var(--psd-sev-minor-fg);
  --ps-sev-minor-bg:     var(--psd-sev-minor-bg);
  --ps-sev-minor-bd:     var(--psd-sev-minor-bd);
  --ps-sev-pass-fg:      var(--psd-sev-pass-fg);
  --ps-sev-pass-bg:      var(--psd-sev-pass-bg);
  --ps-sev-pass-bd:      var(--psd-sev-pass-bd);
  --ps-sev-info-fg:      var(--psd-sev-info-fg);
  --ps-sev-info-bg:      var(--psd-sev-info-bg);
  --ps-sev-info-bd:      var(--psd-sev-info-bd);
  --ps-sev-neutral-fg:   var(--psd-sev-neutral-fg);
  --ps-sev-neutral-bg:   var(--psd-sev-neutral-bg);
  --ps-sev-neutral-bd:   var(--psd-sev-neutral-bd);
  --ps-danger-fg:        var(--psd-danger-fg);
  --ps-danger-bd:        var(--psd-danger-bd);
}

@media (prefers-color-scheme: dark) {
  :root[data-theme="system"] {
    --ps-bg-canvas:        var(--psd-bg-canvas);
    --ps-bg-surface:       var(--psd-bg-surface);
    --ps-bg-surface-muted: var(--psd-bg-surface-muted);
    --ps-bg-inset:         var(--psd-bg-inset);
    --ps-bg-table-head:    var(--psd-bg-table-head);
    --ps-text-primary:     var(--psd-text-primary);
    --ps-text-heading:     var(--psd-text-heading);
    --ps-text-secondary:   var(--psd-text-secondary);
    --ps-text-muted:       var(--psd-text-muted);
    --ps-border-hairline:  var(--psd-border-hairline);
    --ps-border-strong:    var(--psd-border-strong);
    --ps-border-input:     var(--psd-border-input);
    --ps-bg-fill:            var(--psd-bg-fill);
    --ps-text-heading-brand: var(--psd-text-heading-brand);
    --ps-text-slate:         var(--psd-text-secondary);
    --ps-link:             var(--psd-link);
    --ps-focus-ring:       var(--psd-focus-ring);
    --ps-shadow-card:      var(--psd-shadow-card);
    --ps-sev-critical-fg:  var(--psd-sev-critical-fg);
    --ps-sev-critical-bg:  var(--psd-sev-critical-bg);
    --ps-sev-critical-bd:  var(--psd-sev-critical-bd);
    --ps-sev-major-fg:     var(--psd-sev-major-fg);
    --ps-sev-major-bg:     var(--psd-sev-major-bg);
    --ps-sev-major-bd:     var(--psd-sev-major-bd);
    --ps-sev-minor-fg:     var(--psd-sev-minor-fg);
    --ps-sev-minor-bg:     var(--psd-sev-minor-bg);
    --ps-sev-minor-bd:     var(--psd-sev-minor-bd);
    --ps-sev-pass-fg:      var(--psd-sev-pass-fg);
    --ps-sev-pass-bg:      var(--psd-sev-pass-bg);
    --ps-sev-pass-bd:      var(--psd-sev-pass-bd);
    --ps-sev-info-fg:      var(--psd-sev-info-fg);
    --ps-sev-info-bg:      var(--psd-sev-info-bg);
    --ps-sev-info-bd:      var(--psd-sev-info-bd);
    --ps-sev-neutral-fg:   var(--psd-sev-neutral-fg);
    --ps-sev-neutral-bg:   var(--psd-sev-neutral-bg);
    --ps-sev-neutral-bd:   var(--psd-sev-neutral-bd);
    --ps-danger-fg:        var(--psd-danger-fg);
    --ps-danger-bd:        var(--psd-danger-bd);
  }
}

/* ============================================================
   Public landing layout — scope: .lp-root
   ============================================================ */

.lp-root {
  --lp-text-on-dark: var(--saip-ice-0);
  --lp-text-muted-on-dark: var(--saip-slate-400);
  --lp-text-on-light: var(--saip-grey-700);
  --lp-text-muted-on-light: var(--saip-grey-500);
  background: var(--saip-ice-100);
  color: var(--lp-text-on-light);
  font-family: var(--saip-font-ui);
  line-height: 1.6;
}

.lp-root *,
.lp-root *::before,
.lp-root *::after {
  box-sizing: border-box;
}

.lp-root .lp-container {
  max-width: var(--saip-container-max);
  margin: 0 auto;
  padding: 0 var(--saip-gutter);
}

.lp-root a {
  color: var(--saip-teal-600);
  text-decoration: none;
}

.lp-root a:hover {
  text-decoration: underline;
}

.lp-root .lp-skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--saip-navy-800);
  color: var(--saip-ice-0);
  padding: 8px 12px;
  z-index: 99;
}

.lp-root .lp-skip-link:focus {
  left: 8px;
  top: 8px;
  outline: 2px solid var(--ps-focus-ring);
  outline-offset: 2px;
}

/* ============================================================
   Header / nav (public)
   ============================================================ */

.lp-header {
  background: rgba(11, 26, 51, 0.92);
  color: var(--lp-text-on-dark);
  position: sticky;
  top: 0;
  z-index: 50;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  -webkit-backdrop-filter: blur(18px);
          backdrop-filter: blur(18px);
}

.lp-header .lp-header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--saip-spacing-4);
  padding: var(--saip-spacing-4) 0;
}

.lp-wordmark {
  display: inline-flex;
  align-items: center;
  gap: var(--saip-spacing-3);
  color: var(--lp-text-on-dark);
  font-weight: 600;
  font-size: 17px;
  letter-spacing: -0.005em;
}

.lp-wordmark .lp-wordmark-glyph {
  width: 32px;
  height: 32px;
  border-radius: 9px;
  background: var(--saip-gradient-cta-primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--saip-ice-0);
  font-weight: 700;
  font-size: 16px;
  letter-spacing: -0.02em;
}

.lp-nav {
  display: flex;
  align-items: center;
  gap: var(--saip-spacing-4);
  flex-wrap: wrap;
}

.lp-nav a {
  color: var(--saip-ice-0);
  font-size: 14px;
  font-weight: 500;
  padding: 8px 10px;
  border-radius: var(--saip-radius-sm);
}

.lp-nav a:hover {
  background: rgba(255, 255, 255, 0.08);
  text-decoration: none;
}

.lp-nav .lp-nav-cta-secondary,
.lp-nav .lp-nav-cta-primary {
  padding: 8px 14px;
  font-weight: 600;
}

.lp-nav .lp-nav-cta-secondary {
  border: 1px solid var(--saip-glass-border);
}

.lp-nav .lp-nav-cta-primary {
  background: var(--saip-gradient-cta-primary);
  color: var(--saip-ice-0);
}

/* ============================================================
   Buttons
   ============================================================ */

.lp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--saip-spacing-2);
  padding: 12px 22px;
  border-radius: var(--saip-radius);
  font-family: var(--saip-font-ui);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.4;
  border: 1px solid transparent;
  text-decoration: none;
  cursor: pointer;
  transition: transform 200ms ease-out, box-shadow 200ms ease-out, background 200ms ease-out;
}

.lp-btn-primary {
  background: var(--saip-gradient-cta-primary);
  color: var(--saip-ice-0);
}

.lp-btn-primary:hover {
  text-decoration: none;
  transform: translateY(-1px);
  box-shadow: var(--saip-shadow-md);
}

.lp-btn-navy {
  background: var(--saip-gradient-cta-navy);
  color: var(--saip-ice-0);
}

.lp-btn-navy:hover {
  text-decoration: none;
  transform: translateY(-1px);
  box-shadow: var(--saip-shadow-md);
}

.lp-btn-secondary {
  background: transparent;
  border-color: var(--saip-grey-300);
  color: var(--saip-grey-700);
}

.lp-btn-secondary:hover {
  background: var(--saip-ice-50);
  text-decoration: none;
}

.lp-btn-on-dark {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--saip-glass-border);
  color: var(--saip-ice-0);
}

.lp-btn-on-dark:hover {
  background: rgba(255, 255, 255, 0.14);
  text-decoration: none;
}

.lp-btn:focus-visible {
  outline: 2px solid var(--ps-focus-ring);
  outline-offset: 3px;
}

/* ============================================================
   Section base
   ============================================================ */

.lp-section {
  padding: var(--saip-spacing-9) 0;
}

.lp-section-light {
  background: var(--saip-ice-100);
  color: var(--lp-text-on-light);
}

.lp-section-dark {
  background: var(--saip-gradient-hero);
  color: var(--lp-text-on-dark);
}

.lp-section-slate {
  background:
    linear-gradient(180deg, rgba(11, 26, 51, 0.94) 0%, rgba(19, 41, 77, 0.94) 100%),
    radial-gradient(circle at 80% 0%, rgba(31, 168, 171, 0.18) 0%, transparent 60%);
  color: var(--lp-text-on-dark);
}

.lp-eyebrow {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--saip-teal-500);
  margin-bottom: var(--saip-spacing-4);
  display: block;
}

.lp-section-light .lp-eyebrow {
  color: var(--saip-teal-600);
}

.lp-section-header h2,
.lp-h2 {
  font-family: var(--saip-font-ui);
  font-size: 32px;
  line-height: 1.2;
  font-weight: 700;
  letter-spacing: -0.015em;
  margin: 0 0 var(--saip-spacing-4) 0;
}

.lp-section-header p,
.lp-lead {
  font-size: 17px;
  line-height: 1.6;
  max-width: 720px;
  margin: 0 0 var(--saip-spacing-6) 0;
  color: inherit;
  opacity: 0.92;
}

.lp-section-light .lp-lead {
  color: var(--saip-grey-700);
  opacity: 1;
}

/* ============================================================
   Hero
   ============================================================ */

.lp-hero {
  background: var(--saip-gradient-hero);
  color: var(--lp-text-on-dark);
  padding: var(--saip-spacing-9) 0 var(--saip-spacing-9) 0;
  position: relative;
  overflow: hidden;
}

.lp-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 80% 85%, rgba(31, 168, 171, 0.22) 0%, transparent 55%),
    radial-gradient(circle at 95% 5%, rgba(63, 92, 138, 0.30) 0%, transparent 50%);
  pointer-events: none;
}

.lp-hero-inner {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: var(--saip-spacing-8);
  align-items: center;
}

.lp-hero-text {
  max-width: 640px;
}

.lp-hero h1 {
  font-family: var(--saip-font-serif);
  font-size: 56px;
  line-height: 1.1;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0 0 var(--saip-spacing-5) 0;
  color: var(--saip-ice-0);
}

.lp-hero .lp-subhead {
  font-size: 19px;
  line-height: 1.6;
  color: var(--saip-slate-400);
  margin: 0 0 var(--saip-spacing-6) 0;
  max-width: 580px;
}

.lp-hero .lp-cta-row {
  display: flex;
  gap: var(--saip-spacing-3);
  flex-wrap: wrap;
  align-items: center;
}

.lp-hero .lp-hero-footnote {
  margin-top: var(--saip-spacing-6);
  font-size: 12px;
  color: var(--saip-slate-400);
  line-height: 1.5;
}

.lp-trust-strip {
  margin-top: var(--saip-spacing-7);
  padding-top: var(--saip-spacing-5);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  display: flex;
  flex-wrap: wrap;
  gap: var(--saip-spacing-3) var(--saip-spacing-6);
  font-size: 13px;
  color: var(--saip-slate-400);
}

.lp-trust-strip .lp-trust-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.lp-trust-strip .lp-trust-item::before {
  content: "•";
  color: var(--saip-teal-500);
  font-size: 18px;
  line-height: 1;
}

/* Hero illustration card (decorative dashboard preview) */

.lp-hero-art {
  position: relative;
  min-height: 380px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.lp-dashboard-card {
  background: var(--saip-glass-light);
  -webkit-backdrop-filter: var(--saip-blur-card);
          backdrop-filter: var(--saip-blur-card);
  border: 1px solid var(--saip-glass-border);
  border-radius: var(--saip-radius-lg);
  box-shadow: var(--saip-shadow-lg);
  padding: var(--saip-spacing-5);
  width: 100%;
  max-width: 420px;
  color: var(--saip-grey-700);
}

.lp-dashboard-card .lp-dc-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--saip-navy-800);
}

.lp-dashboard-card .lp-dc-title .lp-dc-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--saip-teal-500);
  display: inline-block;
}

.lp-dashboard-card .lp-dc-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: var(--saip-spacing-3);
  font-size: 13px;
}

.lp-dashboard-card .lp-dc-row .lp-dc-label {
  color: var(--saip-grey-500);
}

.lp-dashboard-card .lp-dc-row .lp-dc-value {
  color: var(--saip-grey-700);
  font-weight: 600;
}

.lp-dashboard-card .lp-dc-findings {
  margin-top: var(--saip-spacing-4);
  border: 1px solid var(--saip-grey-200);
  border-radius: var(--saip-radius);
  overflow: hidden;
  background: var(--saip-ice-0);
}

.lp-dashboard-card .lp-dc-finding {
  display: flex;
  align-items: center;
  gap: var(--saip-spacing-3);
  padding: 10px 12px;
  font-size: 13px;
  border-bottom: 1px solid var(--saip-grey-200);
}

.lp-dashboard-card .lp-dc-finding:last-child {
  border-bottom: none;
}

.lp-dashboard-card .lp-dc-finding .lp-dc-finding-id {
  font-weight: 600;
  color: var(--saip-navy-800);
}

.lp-dashboard-card .lp-dc-finding .lp-dc-finding-body {
  flex: 1;
  color: var(--saip-grey-700);
}

.lp-sev-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--saip-radius-sm);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.lp-sev-critical {
  background: var(--saip-rose-500);
  color: var(--saip-ice-0);
}

.lp-sev-major {
  background: var(--saip-amber-50);
  color: var(--saip-amber-500);
}

.lp-sev-minor {
  background: var(--saip-ice-100);
  color: var(--saip-slate-600);
}

.lp-sev-info {
  background: var(--saip-teal-50);
  color: var(--saip-teal-600);
}

/* ============================================================
   Cards / grids
   ============================================================ */

.lp-grid-3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--saip-spacing-5);
}

.lp-grid-4 {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--saip-spacing-5);
}

.lp-grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--saip-spacing-5);
}

.lp-grid-6 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--saip-spacing-5);
}

.lp-card {
  border-radius: var(--saip-radius-lg);
  padding: var(--saip-spacing-6);
  background: var(--saip-ice-50);
  border: 1px solid var(--saip-grey-200);
  box-shadow: var(--saip-shadow-md);
}

.lp-section-dark .lp-card,
.lp-section-slate .lp-card {
  background: var(--saip-glass-dark);
  -webkit-backdrop-filter: var(--saip-blur-card);
          backdrop-filter: var(--saip-blur-card);
  border-color: var(--saip-glass-border);
  color: var(--saip-ice-0);
}

.lp-card h3 {
  font-size: 19px;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.01em;
  margin: 0 0 var(--saip-spacing-3) 0;
}

.lp-card p {
  font-size: 15px;
  line-height: 1.6;
  margin: 0;
  color: inherit;
  opacity: 0.92;
}

.lp-section-light .lp-card p {
  color: var(--saip-grey-700);
  opacity: 1;
}

.lp-card-icon {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: var(--saip-teal-50);
  color: var(--saip-teal-600);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 17px;
  margin-bottom: var(--saip-spacing-4);
}

.lp-section-dark .lp-card-icon,
.lp-section-slate .lp-card-icon {
  background: rgba(31, 168, 171, 0.18);
  color: var(--saip-teal-500);
}

/* ============================================================
   How it works (timeline)
   ============================================================ */

.lp-timeline {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--saip-spacing-4);
  margin-top: var(--saip-spacing-6);
}

.lp-step {
  position: relative;
  padding: var(--saip-spacing-5);
  background: var(--saip-glass-dark);
  -webkit-backdrop-filter: var(--saip-blur-card);
          backdrop-filter: var(--saip-blur-card);
  border: 1px solid var(--saip-glass-border);
  border-radius: var(--saip-radius-lg);
}

.lp-step .lp-step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--saip-gradient-cta-primary);
  color: var(--saip-ice-0);
  font-weight: 700;
  font-size: 13px;
  margin-bottom: var(--saip-spacing-3);
}

.lp-step h3 {
  font-size: 16px;
  margin: 0 0 var(--saip-spacing-2) 0;
  color: var(--saip-ice-0);
}

.lp-step p {
  font-size: 13px;
  color: var(--saip-slate-400);
  line-height: 1.5;
  margin: 0;
}

/* ============================================================
   Trust block (2-col facts grid)
   ============================================================ */

.lp-facts-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--saip-spacing-5);
  margin-top: var(--saip-spacing-6);
}

.lp-fact {
  background: var(--saip-ice-0);
  border: 1px solid var(--saip-grey-200);
  border-radius: var(--saip-radius-lg);
  padding: var(--saip-spacing-5);
  box-shadow: var(--saip-shadow-sm);
}

.lp-fact h3 {
  font-size: 15px;
  font-weight: 600;
  margin: 0 0 var(--saip-spacing-2) 0;
  color: var(--saip-navy-800);
}

.lp-fact p {
  font-size: 14px;
  color: var(--saip-grey-700);
  margin: 0;
  line-height: 1.55;
}

/* ============================================================
   License block (4-card grid)
   ============================================================ */

.lp-license-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--saip-spacing-4);
  margin-top: var(--saip-spacing-6);
}

.lp-license-card {
  background: var(--saip-glass-dark);
  -webkit-backdrop-filter: var(--saip-blur-card);
          backdrop-filter: var(--saip-blur-card);
  border: 1px solid var(--saip-glass-border);
  border-radius: var(--saip-radius-lg);
  padding: var(--saip-spacing-5);
  color: var(--saip-ice-0);
}

.lp-license-card .lp-license-pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  background: rgba(31, 168, 171, 0.18);
  color: var(--saip-teal-500);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  margin-bottom: var(--saip-spacing-3);
}

.lp-license-card h3 {
  font-size: 18px;
  margin: 0 0 var(--saip-spacing-2) 0;
  color: var(--saip-ice-0);
}

.lp-license-card p {
  font-size: 13px;
  color: var(--saip-slate-400);
  line-height: 1.55;
  margin: 0;
}

/* ============================================================
   Final CTA band
   ============================================================ */

.lp-final-cta {
  background: var(--saip-gradient-hero);
  padding: var(--saip-spacing-8) 0;
  text-align: center;
  position: relative;
  overflow: hidden;
}

.lp-final-cta::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 50% 100%, rgba(31, 168, 171, 0.20) 0%, transparent 50%);
  pointer-events: none;
}

.lp-final-cta .lp-final-card {
  position: relative;
  background: var(--saip-glass-dark);
  -webkit-backdrop-filter: var(--saip-blur-card);
          backdrop-filter: var(--saip-blur-card);
  border: 1px solid var(--saip-glass-border);
  border-radius: var(--saip-radius-xl);
  padding: var(--saip-spacing-7) var(--saip-spacing-6);
  margin: 0 auto;
  max-width: 720px;
  color: var(--saip-ice-0);
  box-shadow: var(--saip-shadow-lg);
}

.lp-final-card h2 {
  margin-bottom: var(--saip-spacing-3);
}

.lp-final-card p {
  color: var(--saip-slate-400);
  font-size: 16px;
  margin: 0 0 var(--saip-spacing-5) 0;
}

.lp-final-card .lp-cta-row {
  justify-content: center;
}

/* ============================================================
   Footer
   ============================================================ */

.lp-footer {
  background: var(--saip-navy-900);
  color: var(--saip-slate-400);
  padding: var(--saip-spacing-7) 0 var(--saip-spacing-5) 0;
  font-size: 13px;
}

.lp-footer-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--saip-spacing-5);
}

.lp-footer-grid h4 {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--saip-ice-0);
  margin: 0 0 var(--saip-spacing-3) 0;
}

.lp-footer-grid p,
.lp-footer-grid li {
  margin: 0 0 6px 0;
  color: var(--saip-slate-400);
  line-height: 1.55;
}

.lp-footer-grid ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.lp-footer-grid a {
  color: var(--saip-slate-400);
}

.lp-footer-grid a:hover {
  color: var(--saip-ice-0);
  text-decoration: none;
}

.lp-footer-baseline {
  margin-top: var(--saip-spacing-6);
  padding-top: var(--saip-spacing-4);
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  font-size: 12px;
  color: var(--saip-slate-400);
  display: flex;
  justify-content: space-between;
  gap: var(--saip-spacing-3);
  flex-wrap: wrap;
}

/* ============================================================
   In-page license banner pass-through (logged-in)
   ============================================================ */

.lp-license-banner {
  margin: var(--saip-spacing-5) 0 0 0;
  padding: 14px 18px;
  border-radius: var(--saip-radius);
  background: var(--saip-amber-50);
  color: var(--saip-grey-700);
  font-size: 14px;
  line-height: 1.55;
  border: 1px solid #f0c987;
}

.lp-license-banner.is-suspended {
  background: var(--saip-rose-50);
  border-color: #f0a8a0;
}

.lp-license-banner.is-pending {
  background: var(--saip-ice-100);
  border-color: var(--saip-grey-300);
}

.lp-license-banner.is-info {
  background: var(--saip-teal-50);
  border-color: #b6dcdd;
}

/* ============================================================
   Responsive breakpoints
   ============================================================ */

@media (max-width: 1024px) {
  .lp-hero-inner {
    grid-template-columns: 1fr;
    gap: var(--saip-spacing-7);
  }
  .lp-hero h1 {
    font-size: 44px;
  }
  .lp-hero-art {
    min-height: 280px;
  }
  .lp-timeline {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .lp-license-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .lp-grid-6 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .lp-footer-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 720px) {
  .lp-section {
    padding: var(--saip-spacing-7) 0;
  }
  .lp-hero {
    padding: var(--saip-spacing-7) 0;
  }
  .lp-hero h1 {
    font-size: 36px;
  }
  .lp-section-header h2,
  .lp-h2 {
    font-size: 26px;
  }
  .lp-grid-3,
  .lp-grid-2,
  .lp-grid-6,
  .lp-grid-4,
  .lp-license-grid,
  .lp-facts-grid,
  .lp-timeline,
  .lp-footer-grid {
    grid-template-columns: 1fr;
  }
  .lp-header .lp-header-inner {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--saip-spacing-3);
  }
  .lp-nav {
    gap: var(--saip-spacing-2);
  }
  .lp-footer-baseline {
    flex-direction: column;
  }
}

/* ============================================================
   Reduced motion + reduced transparency
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  .lp-root *,
  .lp-root *::before,
  .lp-root *::after {
    transition: none !important;
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
  }
}

@media (prefers-reduced-transparency: reduce) {
  .lp-dashboard-card,
  .lp-step,
  .lp-license-card,
  .lp-final-cta .lp-final-card,
  .lp-section-dark .lp-card,
  .lp-section-slate .lp-card {
    background: var(--saip-navy-700);
    -webkit-backdrop-filter: none;
            backdrop-filter: none;
  }
  .lp-header {
    -webkit-backdrop-filter: none;
            backdrop-filter: none;
    background: var(--saip-navy-800);
  }
}

/* ============================================================
   Focus visible (a11y)
   ============================================================ */

.lp-root a:focus-visible,
.lp-root button:focus-visible {
  outline: 2px solid var(--ps-focus-ring);
  outline-offset: 3px;
  border-radius: var(--saip-radius-sm);
}

/* ============================================================
   ============================================================
   Phase 67F — authenticated app inner UI (.app-root)
   ============================================================
   Distinct scope so the public landing (.lp-root) stays untouched.
   ============================================================ */

.app-root {
  background: var(--ps-bg-canvas);
  color: var(--ps-text-primary);
  font-family: var(--saip-font-ui);
  line-height: 1.55;
  font-size: var(--saip-text-md);
  margin: 0;
  padding: 0;
}

.app-root *,
.app-root *::before,
.app-root *::after {
  box-sizing: border-box;
}

.app-root a {
  color: var(--ps-link);
  text-decoration: none;
}

.app-root a:hover {
  text-decoration: underline;
}

.app-root code {
  font-family: var(--saip-font-mono);
  font-size: 12.5px;
}

.app-root pre {
  font-family: var(--saip-font-mono);
  font-size: 12.5px;
  background: var(--ps-bg-inset);
  border: 1px solid var(--ps-border-hairline);
  border-radius: var(--saip-radius-sm);
  padding: 12px 14px;
  overflow: auto;
  margin: 8px 0;
  line-height: 1.5;
}

/* W5 — headings are anchored to the canonical type scale AND the UI family,
   so no surface can fall back to a browser default or inherit a stray family. */
.app-root h1,
.app-root h2,
.app-root h3,
.app-root h4,
.app-root h5,
.app-root h6 {
  font-family: var(--saip-font-ui);
}

.app-root h1 {
  font-size: var(--saip-text-h1);
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.2;
  margin: 0 0 8px 0;
  color: var(--saip-ice-0);
}

.app-root h2 {
  font-size: var(--saip-text-h2);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.3;
  margin: 0 0 var(--saip-spacing-4) 0;
  color: var(--ps-text-heading);
}

.app-root h3 {
  font-size: var(--saip-text-h3);
  font-weight: 600;
  letter-spacing: -0.005em;
  line-height: 1.3;
  margin: var(--saip-spacing-5) 0 var(--saip-spacing-3) 0;
  color: var(--ps-text-heading);
}

.app-root h4 {
  font-size: var(--saip-text-md);
  font-weight: 600;
  margin: var(--saip-spacing-4) 0 var(--saip-spacing-2) 0;
  color: var(--ps-text-heading);
}

.app-root p {
  margin: 0 0 var(--saip-spacing-3) 0;
}

.app-root ul,
.app-root ol {
  margin: 0 0 var(--saip-spacing-3) 0;
  padding-left: 22px;
}

.app-root ul li,
.app-root ol li {
  line-height: 1.6;
  margin-bottom: 4px;
}

.app-root .app-wrap {
  /* copie-conforme: maquette app container is 1340px (landing keeps 1180). */
  max-width: 1340px;
  margin: 0 auto;
  padding: 0 var(--saip-gutter);
}

.app-root .app-skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--saip-navy-800);
  color: var(--saip-ice-0);
  padding: 8px 12px;
  z-index: 99;
}

.app-root .app-skip-link:focus {
  left: 8px;
  top: 8px;
  outline: 2px solid var(--ps-focus-ring);
  outline-offset: 2px;
}

/* W0 a11y floor (G3) — visually-hidden utility for the per-page <h1> that
   restores the document outline (header band was trimmed in 2026-06-18, leaving
   pages starting at <h2>). Content stays in the accessibility tree for screen
   readers; it is removed from the visual layout without disabling focusability. */
.app-vh {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap;
}

/* -----------------------------------------------------------
   Header
   ----------------------------------------------------------- */

.app-root .app-header {
  background: var(--saip-gradient-cta-navy);
  color: var(--saip-ice-0);
  padding: var(--saip-spacing-5) 0 var(--saip-spacing-3) 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.app-root .app-header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--saip-spacing-4);
  flex-wrap: wrap;
}

.app-root .app-wordmark {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  color: var(--saip-ice-0);
  text-decoration: none;
  font-weight: 700;
  font-size: 26px;             /* enlarged brand wordmark — prominent header lockup */
  letter-spacing: -0.01em;
}

/* Copie-conforme chrome — signed-in identity in the navy header. */
.app-root .app-header-user {
  margin-left: auto;
  font-size: 12px;
  color: var(--saip-slate-400);
}

.app-root .app-header-user strong {
  color: #cdd9ef;
  font-weight: 600;
}

.app-root .app-header-user .app-auth-role {
  background: var(--saip-teal-600);
  color: var(--saip-ice-0);
  padding: 2px 8px;
  border-radius: 6px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* M22-BRAND-02-R1 — brand logo sizing tokens are defined once in the main
   :root block above (W5: the former second :root here was folded in so the
   design system has a single token root). */

/* M22-BRAND-02 / R1 — Profile Sentinel SVG mark replaces the legacy text-square
   glyph. Decorative (alt=""); the adjacent "Profile Sentinel" text remains the
   accessible label. R1: larger + a subtle teal-edged backing lozenge so the
   mark reads strongly on the dark navy header and never looks thin/invisible. */
.app-root .app-wordmark .app-wordmark-mark {
  width: var(--ps-logo-app-header);
  height: var(--ps-logo-app-header);
  display: block;
  flex: 0 0 auto;
  padding: 5px;
  border-radius: 12px;
  background: rgba(79, 216, 230, 0.08);
  box-shadow: inset 0 0 0 1px rgba(79, 216, 230, 0.28);
}

/* M22-BRAND-02 / R1 — Clause SVG mark, used next to "Clause" titles in the
   embedded panel header and on the /clause console lead. Decorative (alt=""). */
.app-root .clause-mark {
  display: inline-block;
  flex: 0 0 auto;
  vertical-align: middle;
}

.app-root .app-wordmark-sub {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--saip-slate-400);
  margin-top: 2px;
  display: block;
  font-weight: 500;
}

.app-root .app-header-title {
  margin: var(--saip-spacing-4) 0 0 0;
}

.app-root .app-header-title h1 {
  color: var(--saip-ice-0);
}

.app-root .app-header-sub {
  font-size: 12px;
  color: var(--saip-slate-400);
  margin-top: 2px;
}

/* -----------------------------------------------------------
   Top navigation
   ----------------------------------------------------------- */

.app-root .app-nav {
  background: var(--saip-navy-800);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  padding: 0;
  position: sticky;
  top: 0;
  z-index: 40;
}

.app-root .app-nav-inner {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
  padding: 8px 0;
}

.app-root .app-nav a {
  color: var(--saip-ice-0);
  text-decoration: none;
  font-weight: 500;
  font-size: 13px;
  padding: 8px 12px;
  border-radius: var(--saip-radius-sm);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: background 200ms ease-out;
}

.app-root .app-nav a:hover {
  background: rgba(255, 255, 255, 0.08);
  text-decoration: none;
}

.app-root .app-nav a.is-active {
  background: var(--saip-teal-600);
  color: var(--saip-ice-0);
}

.app-root .app-nav .app-nav-spacer {
  flex: 1;
}

/* Auth strip — small bar under the nav for sign-in state + license pill. */

/* UX-REFONTE-W1 (B4) — Profile Delta sub-nav (Compare / Reference library /
   Fleet query). The active link is distinguished by MORE than colour (weight +
   teal underline) so the "you are here" cue holds for sighted users and passes
   WCAG SC 1.4.1; AT gets it via aria-current="page". */
.app-root .app-subnav {
  display: flex;
  gap: var(--saip-spacing-4);
  flex-wrap: wrap;
  margin: 0 0 var(--saip-spacing-5);
  font-size: var(--saip-text-sm);
  border-bottom: 1px solid var(--saip-grey-200);
  padding-bottom: var(--saip-spacing-2);
}
.app-root .app-subnav a {
  color: var(--saip-grey-600);
  text-decoration: none;
  padding-bottom: var(--saip-spacing-1);
  border-bottom: 2px solid transparent;
}
.app-root .app-subnav a:hover { color: var(--saip-teal-600); }
.app-root .app-subnav a.is-active {
  color: var(--saip-navy-900);
  font-weight: 700;
  border-bottom-color: var(--saip-teal-600);
}

.app-root .app-auth-strip {
  background: var(--saip-ice-50);
  border-bottom: 1px solid var(--saip-grey-200);
  padding: 6px 0;
  font-size: 12.5px;
}

.app-root .app-auth-strip-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--saip-spacing-3);
  flex-wrap: wrap;
}

.app-root .app-auth-strip strong {
  color: var(--saip-navy-800);
}

.app-root .app-auth-strip .app-auth-role {
  display: inline-block;
  background: var(--saip-ice-100);
  color: var(--saip-navy-700);
  padding: 2px 8px;
  border-radius: var(--saip-radius-sm);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border: 1px solid var(--saip-grey-300);
  margin-left: 6px;
}

.app-root .app-auth-strip .app-auth-signin {
  color: var(--saip-rose-500);
  font-weight: 600;
}

.app-root .app-auth-strip .app-auth-link {
  color: var(--saip-teal-600);
  font-weight: 600;
  text-decoration: none;
  padding: 2px 10px;
  border: 1px solid var(--saip-grey-300);
  border-radius: var(--saip-radius-sm);
  background: var(--saip-ice-0);
}

.app-root .app-auth-strip .app-auth-link:hover {
  background: var(--saip-teal-50);
  text-decoration: none;
}

/* Mobile drawer (CSS-only via <details>) — appears on narrow viewports. */

.app-root .app-nav-drawer {
  display: none;
  margin: 0;
}

.app-root .app-nav-drawer summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  background: rgba(255, 255, 255, 0.08);
  color: var(--saip-ice-0);
  border-radius: var(--saip-radius-sm);
  font-size: 14px;
  font-weight: 600;
}

.app-root .app-nav-drawer summary::-webkit-details-marker {
  display: none;
}

.app-root .app-nav-drawer[open] summary::after {
  content: "▴";
  margin-left: 4px;
}

.app-root .app-nav-drawer summary::after {
  content: "▾";
  margin-left: 4px;
}

@media (max-width: 880px) {
  .app-root .app-nav-inner {
    display: none;
  }
  .app-root .app-nav-drawer {
    display: block;
    padding: 8px 0;
  }
  .app-root .app-nav-drawer .app-nav-drawer-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-top: 8px;
    background: var(--saip-navy-700);
    border-radius: var(--saip-radius);
    padding: 8px;
  }
  .app-root .app-nav-drawer .app-nav-drawer-list a {
    color: var(--saip-ice-0);
    text-decoration: none;
    padding: 10px 12px;
    border-radius: var(--saip-radius-sm);
    font-size: 14px;
    font-weight: 500;
  }
  .app-root .app-nav-drawer .app-nav-drawer-list a.is-active {
    background: var(--saip-teal-600);
  }
  .app-root .app-nav-drawer .app-nav-drawer-list a:hover {
    background: rgba(255, 255, 255, 0.08);
  }
}

/* -----------------------------------------------------------
   License pill in the auth strip
   ----------------------------------------------------------- */

.app-root .app-lic-pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  border: 1px solid var(--saip-grey-300);
  margin-left: 6px;
  text-decoration: none;
  vertical-align: middle;
}

.app-root .app-lic-pill-active {
  background: var(--saip-green-50);
  color: var(--saip-green-500);
  border-color: #bcdcc4;
}

.app-root .app-lic-pill-soon {
  background: var(--saip-amber-50);
  color: var(--saip-amber-500);
  border-color: #f0c987;
}

.app-root .app-lic-pill-expired {
  background: var(--saip-rose-50);
  color: var(--saip-rose-500);
  border-color: #f0a8a0;
}

.app-root .app-lic-pill-suspended {
  background: #f8e1ec;
  color: #7a1a3a;
  border-color: #e7b8c8;
}

.app-root .app-lic-pill-pending {
  background: var(--saip-ice-100);
  color: var(--saip-navy-700);
  border-color: var(--saip-grey-300);
}

/* -----------------------------------------------------------
   Page-level layout
   ----------------------------------------------------------- */

.app-root .app-main {
  padding: var(--saip-spacing-5) 0 var(--saip-spacing-7) 0;
  min-height: 60vh;
}

.app-root .app-breadcrumb {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
  font-size: 12px;
  margin: 0 0 var(--saip-spacing-4) 0;
}

.app-root .app-breadcrumb a {
  background: var(--ps-bg-surface);
  border: 1px solid var(--ps-border-hairline);
  border-radius: var(--saip-radius-sm);
  padding: 4px 10px;
  color: var(--ps-text-heading);
  font-weight: 600;
}

.app-root .app-breadcrumb a:hover {
  background: var(--ps-sev-info-bg);
  text-decoration: none;
  border-color: var(--ps-border-strong);
}

.app-root .app-breadcrumb .sep {
  color: var(--ps-border-strong);
  font-weight: 600;
}

.app-root .app-breadcrumb code {
  font-family: var(--saip-font-mono);
  color: var(--ps-text-primary);
  background: transparent;
  font-size: 12px;
}

/* -----------------------------------------------------------
   Section / card primitives
   ----------------------------------------------------------- */

/* HANDOFF §2.2 — cards: radius 12px, hairline border, soft shadow. */
.app-root .app-section {
  background: var(--ps-bg-surface);
  border: 1px solid var(--ps-border-hairline);
  border-radius: var(--saip-radius);
  box-shadow: var(--ps-shadow-card);
  padding: var(--saip-spacing-5) var(--saip-spacing-6);
  margin: 0 0 var(--saip-spacing-5) 0;
}

/* Non-compliant content card: rose border + 3px left accent. */
.app-root .app-section.is-noncompliant,
.app-root .app-card-noncompliant {
  border-color: #f0a8a0;
  border-left: 3px solid var(--saip-rose-500);
}

/* Absent / not-declared object: dashed border. */
.app-root .app-section.is-absent,
.app-root .app-card-absent {
  border-style: dashed;
}

.app-root .app-section h2 {
  border-bottom: 1px solid var(--saip-grey-200);
  padding-bottom: var(--saip-spacing-3);
  margin: 0 0 var(--saip-spacing-4) 0;
}

.app-root .app-section h3 {
  margin-top: var(--saip-spacing-4);
}

.app-root .app-section-tight {
  padding: var(--saip-spacing-4) var(--saip-spacing-5);
}

.app-root .app-section-muted {
  background: var(--saip-ice-50);
}

.app-root .app-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--saip-spacing-3);
  margin-bottom: var(--saip-spacing-3);
}

.app-root .app-stat-card {
  background: var(--ps-bg-surface);
  border: 1px solid var(--ps-border-hairline);
  border-radius: var(--saip-radius);
  box-shadow: var(--ps-shadow-card);
  padding: var(--saip-spacing-4) var(--saip-spacing-4);
}

.app-root .app-stat-card .app-stat-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ps-text-secondary);
  font-weight: 600;
}

.app-root .app-stat-card .app-stat-value {
  font-size: 18px;
  font-weight: 600;
  color: var(--ps-text-heading);
  margin-top: 4px;
  word-break: break-word;
}

.app-root .app-stat-card .app-stat-value a {
  color: var(--saip-teal-600);
}

/* Status-coloured stat cards (severity overview). */
.app-root .app-stat-card.is-pass {
  background: var(--saip-green-50);
  border-color: #bcdcc4;
}
.app-root .app-stat-card.is-pass .app-stat-value {
  color: var(--saip-green-500);
}
.app-root .app-stat-card.is-critical {
  background: var(--saip-rose-50);
  border-color: #f0a8a0;
}
.app-root .app-stat-card.is-critical .app-stat-value {
  color: var(--saip-rose-500);
}
.app-root .app-stat-card.is-major {
  background: var(--saip-amber-50);
  border-color: #f0c987;
}
.app-root .app-stat-card.is-major .app-stat-value {
  color: var(--saip-amber-500);
}
.app-root .app-stat-card.is-minor {
  background: var(--saip-amber-50);
  border-color: #ead7af;
}
.app-root .app-stat-card.is-minor .app-stat-value {
  color: var(--ps-sev-minor-fg); /* FT-DC-PILL-CONTRAST-AA-01: old olive ≈2.5:1 failed AA */
}
.app-root .app-stat-card.is-info {
  background: var(--saip-teal-50);
  border-color: #b6dcdd;
}
.app-root .app-stat-card.is-info .app-stat-value {
  color: var(--saip-teal-600);
}
.app-root .app-stat-card.is-skipped {
  background: var(--saip-grey-200);
  border-color: var(--saip-grey-300);
}
.app-root .app-stat-card.is-skipped .app-stat-value {
  color: var(--saip-grey-500);
}
.app-root .app-stat-card.is-error {
  background: var(--saip-grey-200);
  border-color: var(--saip-grey-300);
}
.app-root .app-stat-card.is-error .app-stat-value {
  color: var(--saip-grey-700);
}

/* -----------------------------------------------------------
   Tables
   ----------------------------------------------------------- */

.app-root table.app-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--ps-bg-surface);
  border: 1px solid var(--ps-border-hairline);
  border-radius: var(--saip-radius);
  overflow: hidden;
  font-size: 13px;
}

.app-root table.app-table th,
.app-root table.app-table td {
  text-align: left;
  vertical-align: top;
  padding: 10px 12px;
  border-bottom: 1px solid var(--ps-border-hairline);
}

/* ── Shared history-row grammar (Design Council T9, 2026-07-02) ─────────────
   One column dialect for every pillar history table (_history_cells.html):
   name-first row header (semibold, with the opaque id demoted to a mono
   sub-line), muted facts, human_dt dates, right-most nowrap actions. These
   classes replace the copy-pasted inline font/color styles on new markup. */
.app-root table.app-table th.app-cell-name {
  /* the <th scope="row"> name cell keeps BODY styling — it is a row header,
     not a column header (the column-header rules below are scoped to thead). */
  background: transparent;
  color: var(--ps-text-primary);
  font-weight: 600;
  font-size: var(--saip-text-sm);
  letter-spacing: normal;
  text-transform: none;
}
.app-root .app-cell-name .app-cell-id {
  display: block;
  margin-top: 2px;
  font-family: var(--saip-font-mono);
  font-size: var(--saip-text-2xs);
  font-weight: 400;
  color: var(--ps-text-secondary);
}
.app-root .app-cell-date {
  font-size: var(--saip-text-xs);
  color: var(--ps-text-primary);
  white-space: nowrap;
}
.app-root .app-cell-muted {
  font-size: var(--saip-text-xs);
  color: var(--ps-text-secondary);
}
.app-root .app-cell-actions { white-space: nowrap; }

/* HANDOFF §2.1 — table headers are always light; navy is chrome-only. */
.app-root table.app-table th {
  background: var(--ps-bg-table-head);
  color: var(--ps-text-secondary);
  font-weight: 700;
  font-size: 9.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--ps-border-hairline);
}

.app-root table.app-table tbody tr:nth-child(even) {
  background: var(--ps-bg-surface-muted);
}

.app-root table.app-table tbody tr:hover {
  background: var(--saip-row-hover);
}

.app-root table.app-table tbody tr:last-child td {
  border-bottom: none;
}

/* Responsive table wrapper for overflow on small screens. */
.app-root .app-table-wrap {
  overflow-x: auto;
  border-radius: var(--saip-radius);
  margin: 0 0 var(--saip-spacing-3) 0;
}

/* MR-M3-06 / BETA2-WP-13 — keep the row-action column (the last cell) always
   reachable. The date-heavy admin tables overflow horizontally, pushing the
   "Open"/action control off-screen and forcing a horizontal scroll (BETA2-016/
   023). Pin the last column sticky to the right edge of the scroll viewport so
   the action stays visible without scrolling. Opaque, row-matched backgrounds
   keep the scrolled-under data from showing through; a soft left shadow marks
   the seam. Sticky only engages when the table overflows, so non-overflowing
   tables are visually unchanged. Scoped to .app-table-wrap > table.app-table
   (the Profile Explorer filesystem table uses .pe-fs-table-wrap, untouched). */
/* The base table sets overflow:hidden (border-radius clip); that establishes a
   clip context which prevents the cells below from sticking to the OUTER
   .app-table-wrap scroll container. Inside the wrap, let the table overflow be
   visible so position:sticky resolves against the wrap (the wrap keeps the
   rounded corners + the horizontal scroll). */
.app-root .app-table-wrap table.app-table {
  overflow: visible;
}
.app-root .app-table-wrap table.app-table th:last-child,
.app-root .app-table-wrap table.app-table td:last-child {
  position: sticky;
  right: 0;
  z-index: 1;
  box-shadow: -6px 0 6px -6px rgba(0, 0, 0, 0.18);
}
.app-root .app-table-wrap table.app-table thead th:last-child {
  background: var(--ps-bg-table-head);
  z-index: 2;
}
.app-root .app-table-wrap table.app-table tbody td:last-child {
  background: var(--ps-bg-surface);
}
.app-root .app-table-wrap table.app-table tbody tr:nth-child(even) td:last-child {
  background: var(--saip-ice-50);
}
.app-root .app-table-wrap table.app-table tbody tr:hover td:last-child {
  /* opaque blend of --saip-row-hover over white (sticky cell must hide
     the content scrolling underneath it) */
  background: #F5FBFB;
}

/* MR-M3-10 / BETA2-014 — password reveal toggle (injected by
   /static/js/password_reveal.js next to each password input). */
.app-root .pw-reveal-toggle {
  margin-left: 8px;
  padding: 4px 10px;
  font-size: 12px;
  cursor: pointer;
  background: var(--saip-ice-50);
  border: 1px solid var(--saip-grey-200);
  border-radius: var(--saip-radius);
  color: var(--saip-navy-800);
}
.app-root .pw-reveal-toggle:hover {
  background: var(--saip-teal-50);
}

/* -----------------------------------------------------------
   Buttons
   ----------------------------------------------------------- */

.app-root .app-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  border-radius: var(--saip-radius-sm);
  font-size: 13px;
  font-weight: 600;
  font-family: var(--saip-font-ui);
  border: 1px solid var(--ps-border-strong);
  background: var(--ps-bg-surface);
  color: var(--ps-text-heading);
  text-decoration: none;
  cursor: pointer;
  transition: transform 200ms ease-out, box-shadow 200ms ease-out, background 200ms ease-out;
  line-height: 1.4;
}

.app-root .app-btn:hover {
  text-decoration: none;
  background: var(--saip-ice-50);
  box-shadow: var(--saip-shadow-sm);
}

.app-root .app-btn-primary {
  background: var(--saip-gradient-cta-primary);
  color: var(--saip-ice-0);
  border-color: transparent;
}

.app-root .app-btn-primary:hover {
  text-decoration: none;
  transform: translateY(-1px);
  box-shadow: var(--saip-shadow-md);
}

.app-root .app-btn-navy {
  background: var(--saip-gradient-cta-navy);
  color: var(--saip-ice-0);
  border-color: transparent;
}

.app-root .app-btn-navy:hover {
  text-decoration: none;
  transform: translateY(-1px);
  box-shadow: var(--saip-shadow-md);
}

.app-root .app-btn-ghost {
  background: transparent;
  border: 1px solid var(--saip-grey-300);
  color: var(--saip-grey-700);
}

.app-root .app-btn-ghost:hover {
  background: var(--saip-ice-50);
}

.app-root .app-btn-destructive {
  background: transparent;
  border-color: var(--saip-rose-500);
  color: var(--saip-rose-500);
}

.app-root .app-btn-destructive:hover {
  background: var(--saip-rose-50);
}

.app-root .app-btn[disabled],
.app-root .app-btn.is-disabled {
  opacity: 0.55;
  cursor: not-allowed;
  pointer-events: none;
}

/* HANDOFF §2.6 — visible focus everywhere in the app scope. */
.app-root :focus-visible {
  outline: 2px solid var(--ps-focus-ring);
  outline-offset: 2px;
}

.app-root .app-btn:focus-visible,
.app-root .app-nav a:focus-visible,
.app-root .app-auth-strip a:focus-visible {
  outline: 2px solid var(--ps-focus-ring);
  outline-offset: 2px;
  border-radius: var(--saip-radius-sm);
}

/* -----------------------------------------------------------
   Forms
   ----------------------------------------------------------- */

.app-root .app-form {
  max-width: 560px;
}

.app-root .app-form-row {
  margin-bottom: var(--saip-spacing-4);
}

.app-root .app-form-row label {
  display: block;
  font-size: 12px;
  color: var(--ps-text-heading);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 4px;
}

.app-root .app-form-row input[type="text"],
.app-root .app-form-row input[type="email"],
.app-root .app-form-row input[type="password"],
.app-root .app-form-row input[type="search"],
.app-root .app-form-row input[type="number"],
.app-root .app-form-row input[type="url"],
.app-root .app-form-row input[type="file"],
.app-root .app-form-row textarea,
.app-root .app-form-row select {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--ps-border-strong);
  border-radius: var(--saip-radius-sm);
  font-size: 14px;
  font-family: var(--saip-font-ui);
  background: var(--ps-bg-surface);
  color: var(--ps-text-primary);
}

.app-root .app-form-row textarea {
  min-height: 96px;
  resize: vertical;
}

.app-root .app-form-row input:focus,
.app-root .app-form-row textarea:focus,
.app-root .app-form-row select:focus {
  outline: 2px solid var(--ps-focus-ring);
  outline-offset: 0;
  border-color: var(--saip-teal-500);
}

.app-root .app-form-row .app-form-help {
  display: block;
  font-size: 12px;
  color: var(--ps-text-secondary);
  margin-top: 4px;
  line-height: 1.5;
}

.app-root .app-form-row.has-error input,
.app-root .app-form-row.has-error textarea,
.app-root .app-form-row.has-error select {
  border-color: var(--saip-rose-500);
}

.app-root .app-form-row.has-error .app-form-help {
  color: var(--saip-rose-500);
}

.app-root .app-form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--saip-spacing-2);
  margin-top: var(--saip-spacing-4);
}

.app-root .app-checkbox {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 13px;
  line-height: 1.5;
}

.app-root .app-checkbox input[type="checkbox"] {
  margin-top: 4px;
}

/* FT-W2-APPEARANCE-PREF-01 — My Profile > Appearance radio row. */
.app-root .app-appearance-fieldset {
  border: none;
  margin: 0;
  padding: 0;
}

.app-root .app-appearance-options {
  display: flex;
  flex-wrap: wrap;
  gap: var(--saip-spacing-3);
}

.app-root .app-appearance-option {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border: 1px solid var(--ps-border-strong);
  border-radius: var(--saip-radius-sm);
  background: var(--ps-bg-surface);
  color: var(--ps-text-primary);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}

.app-root .app-appearance-option:has(input:checked) {
  /* Council pass-2 m2: the checked outline rides the AA focus-ring token
     (teal-500 accent was 2.90:1 on white; the native radio dot independently
     conveys the state, this ring is reinforcement). */
  border-color: var(--ps-focus-ring);
  outline: 1px solid var(--ps-focus-ring);
}

/* Phase 68E — responsive reason input for admin lifecycle actions.
   Replaces the hard-coded `width:480px;` that previously overflowed the
   admin user-detail card on small viewports. Box-sizing border-box +
   max-width 100% guarantee the input never extends past its container,
   while a generous min-width keeps short labels readable on wide
   viewports. */
.app-root .app-reason-input {
  display: block;
  width: 100%;
  max-width: 480px;
  box-sizing: border-box;
  padding: 8px 10px;
  font-size: 14px;
  font-family: var(--saip-font-ui);
  border: 1px solid var(--ps-border-strong);
  border-radius: var(--saip-radius-sm);
  background: var(--ps-bg-surface);
  color: var(--ps-text-primary);
  margin-top: 4px;
}

.app-root .app-reason-input:focus {
  outline: 2px solid var(--ps-focus-ring);
  outline-offset: 0;
  border-color: var(--saip-teal-500);
}

/* Phase 68E — danger styling for destructive lifecycle actions
   (Disable / Archive / Delete / Cancel-invitation). The .app-btn-danger
   variant inherits .app-btn structure but uses the rose palette for the
   border + label so destructive buttons read as different from primary
   actions. */
.app-root .app-btn-danger {
  /* FT-DC-PILL-CONTRAST-AA-01: rose-500 label on white was ≈4.46:1; the
     --ps-danger-* action tokens are the AA set shared with the PE workspace
     danger button (fg ≈6.62:1 on white). */
  background: var(--ps-bg-surface);
  color: var(--ps-danger-fg);
  border-color: var(--ps-danger-bd);
}

.app-root .app-btn-danger:hover,
.app-root .app-btn-danger:focus {
  background: var(--ps-danger-bg);
  color: var(--saip-ice-0);
  border-color: var(--ps-danger-bd);
}

/* -----------------------------------------------------------
   Banners
   ----------------------------------------------------------- */

.app-root .app-banner {
  display: flex;
  gap: var(--saip-spacing-3);
  padding: 12px 16px;
  border-radius: var(--saip-radius);
  border: 1px solid var(--ps-border-strong);
  background: var(--ps-bg-surface-muted);
  color: var(--ps-text-primary);
  font-size: 13.5px;
  line-height: 1.55;
  margin-bottom: var(--saip-spacing-4);
}

.app-root .app-banner strong {
  color: var(--ps-text-heading);
}

.app-root .app-banner.is-success {
  background: var(--ps-sev-pass-bg);
  border-color: var(--ps-sev-pass-bd);
}

.app-root .app-banner.is-warning {
  background: var(--ps-sev-major-bg);
  border-color: var(--ps-sev-major-bd);
}

.app-root .app-banner.is-error {
  background: var(--ps-sev-critical-bg);
  border-color: var(--ps-sev-critical-bd);
}

.app-root .app-banner.is-info {
  background: var(--ps-sev-info-bg);
  border-color: var(--ps-sev-info-bd);
}

.app-root .app-banner.is-suspended {
  background: #f8e1ec;
  border-color: #e7b8c8;
}

.app-root .app-banner.is-pending {
  background: var(--ps-bg-canvas);
  border-color: var(--ps-border-strong);
}

.app-root .app-banner .app-banner-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background: rgba(11, 26, 51, 0.06);
  color: var(--saip-navy-800);
  font-weight: 700;
  flex: none;
}

.app-root .app-banner.is-success .app-banner-icon {
  background: rgba(43, 164, 110, 0.18);
  color: var(--saip-green-500);
}

.app-root .app-banner.is-warning .app-banner-icon {
  background: rgba(216, 142, 47, 0.18);
  color: var(--saip-amber-500);
}

.app-root .app-banner.is-error .app-banner-icon,
.app-root .app-banner.is-suspended .app-banner-icon {
  background: rgba(196, 81, 99, 0.18);
  color: var(--saip-rose-500);
}

.app-root .app-banner.is-info .app-banner-icon {
  background: rgba(31, 168, 171, 0.18);
  color: var(--saip-teal-600);
}

.app-root .app-banner-body {
  flex: 1;
}

.app-root .app-banner-body .app-banner-cta {
  margin-top: 6px;
  font-size: 12.5px;
}

.app-root .app-banner-body .app-banner-cta a {
  color: var(--ps-link);
  font-weight: 600;
}

/* -----------------------------------------------------------
   KV layout (read-only key/value)
   ----------------------------------------------------------- */

.app-root .app-kv {
  display: flex;
  gap: var(--saip-spacing-4);
  padding: 6px 0;
  font-size: 13px;
  border-bottom: 1px dashed var(--ps-border-hairline);
}

.app-root .app-kv:last-child {
  border-bottom: none;
}

.app-root .app-kv .app-kv-k {
  flex: 0 0 220px;
  color: var(--ps-text-secondary);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
}

.app-root .app-kv .app-kv-v {
  flex: 1;
  color: var(--ps-text-primary);
  word-break: break-word;
}

@media (max-width: 600px) {
  .app-root .app-kv {
    flex-direction: column;
    gap: 2px;
  }
  .app-root .app-kv .app-kv-k {
    flex: none;
  }
}

/* -----------------------------------------------------------
   Status / severity pills
   ----------------------------------------------------------- */

.app-root .app-pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: var(--saip-radius-sm);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  border: 1px solid transparent;
}

/* Severity pills now consume the --ps-sev-* semantic tokens (single source
   of truth; identical computed values as before → no light regression). The
   [data-tone] variants are the unified API brief 02 collapses every pillar's
   badge idiom onto (.pe-badge-*, .ds-verdict-*, .m34-vt-chip.* migrate to it
   in Wave 2). ok=pass · fail=critical-wash · warn=major · info · neutral. */
.app-root .app-pill-active,
.app-root .app-pill-pass,
.app-root .app-pill-diagnostic-pass,
.app-root .app-pill[data-tone="ok"] {
  background: var(--ps-sev-pass-bg);
  color: var(--ps-sev-pass-fg);
  border-color: var(--ps-sev-pass-bd);
}

.app-root .app-pill-critical {
  /* FT-DC-PILL-CONTRAST-AA-01: solid variant — white on rose-500 was ≈4.46:1
     (borderline fail); the solid token is darkened to ≈5.91:1. */
  background: var(--ps-sev-critical-solid-bg);
  color: var(--saip-ice-0);
}

.app-root .app-pill-major,
.app-root .app-pill-warning,
.app-root .app-pill-diagnostic-findings,
.app-root .app-pill[data-tone="warn"] {
  background: var(--ps-sev-major-bg);
  color: var(--ps-sev-major-fg);
  border-color: var(--ps-sev-major-bd);
}

.app-root .app-pill-minor {
  background: var(--ps-sev-minor-bg);
  color: var(--ps-sev-minor-fg);
  border-color: var(--ps-sev-minor-bd);
}

.app-root .app-pill-info,
.app-root .app-pill-partial-analysis,
.app-root .app-pill-trial,
.app-root .app-pill[data-tone="info"] {
  background: var(--ps-sev-info-bg);
  color: var(--ps-sev-info-fg);
  border-color: var(--ps-sev-info-bd);
}

.app-root .app-pill-skipped,
.app-root .app-pill-archived {
  background: var(--ps-sev-neutral-bg);
  color: var(--ps-sev-neutral-fg);
}

.app-root .app-pill[data-tone="neutral"] {
  background: var(--ps-sev-neutral-bg);
  color: var(--ps-sev-neutral-fg);
  border-color: var(--ps-sev-neutral-bd);
}

.app-root .app-pill-expired,
.app-root .app-pill-fail,
.app-root .app-pill-error,
.app-root .app-pill[data-tone="fail"] {
  background: var(--ps-sev-critical-bg);
  color: var(--ps-sev-critical-fg);
  border-color: var(--ps-sev-critical-bd);
}

.app-root .app-pill-suspended {
  background: #f8e1ec;
  color: #7a1a3a;
  border-color: #e7b8c8;
}

.app-root .app-pill-pending {
  background: var(--saip-ice-100);
  color: var(--saip-navy-700);
  border-color: var(--saip-grey-300);
}

.app-root .app-pill-internal,
.app-root .app-pill-annual,
.app-root .app-pill-enterprise {
  background: var(--saip-ice-100);
  color: var(--saip-navy-700);
  border-color: var(--saip-grey-300);
}

/* -----------------------------------------------------------
   Enterprise redesign primitives — HANDOFF §2.3/§2.4/§2.5/§2.8
   (design_handoff_profile_sentinel · 01 - Design Charter)
   ----------------------------------------------------------- */

/* §2.3 — section heading pattern: 15/700 title + labelled count pill. */
.app-root .app-sec-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}

.app-root .app-sec-title {
  font-size: var(--saip-text-lg);
  font-weight: 700;
  color: var(--ps-text-heading);
  margin: 0;
}

/* W5 — dense table-group header label. A NAMED component (13px/700) so a
   row-group title never has to shrink the 15px .app-sec-title with a one-off
   inline override (the rules-table inconsistency the Sponsor saw). */
.app-root .app-group-label {
  font-size: var(--saip-text-base);
  font-weight: 700;
  color: var(--ps-text-heading);
  margin: 0;
}

/* Counts appear ONLY with an explicit label (e.g. "2 applet instances"),
   never as a bare number badge. */
.app-root .app-count-pill {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 700;
  background: var(--ps-bg-canvas);
  border: 1px solid var(--ps-border-hairline);
  color: var(--ps-text-secondary);
  white-space: nowrap;
}

/* "▾ Detailed … rows (n)" line that precedes every detail table. */
.app-root .app-detail-line {
  font-size: 12px;
  font-weight: 600;
  color: var(--ps-text-heading);
  margin: 10px 0 6px;
}

.app-root .app-detail-line .app-detail-note {
  font-weight: 400;
  color: var(--saip-grey-400);
}

/* §2.4 — field rows: uppercase muted label above a mono value. */
.app-root .app-field-row {
  padding: 7px 0;
  border-bottom: 1px solid var(--saip-grey-200);
}

.app-root .app-field-row:last-child {
  border-bottom: none;
}

.app-root .app-field-label {
  display: block;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--saip-grey-400);
}

.app-root .app-field-value {
  display: block;
  margin-top: 3px;
  font-family: var(--saip-font-mono);
  font-size: 11px;
  color: var(--saip-navy-700);
  word-break: break-all;
}

.app-root .app-field-value.is-prose {
  font-family: var(--saip-font-ui);
  font-size: 12.5px;
  word-break: normal;
}

/* §2.5 — muted text at charter contrast. */
.app-root .app-muted {
  color: var(--saip-grey-400);
}

/* "standard default" marker — defaults are always explicitly marked. */
.app-root .app-std-default {
  font-size: 10px;
  font-weight: 600;
  color: var(--saip-grey-400);
  text-transform: none;
}

/* Card-grid + label utilities (Dashboard.dc.html port). */
.app-root .app-card-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--saip-grey-500);
  font-weight: 600;
  margin: 0 0 var(--saip-spacing-3) 0;
}

.app-root .app-section h2.app-card-label {
  border-bottom: none;
  padding-bottom: 0;
}

.app-root .app-grid-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 14px;
  margin-bottom: 14px;
}

.app-root .app-grid-2-1 {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr);
  gap: 14px;
  margin-bottom: 14px;
}

@media (max-width: 900px) {
  .app-root .app-grid-2-1 {
    grid-template-columns: 1fr;
  }
}

.app-root .app-card-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--saip-navy-900);
  margin: 8px 0 0;
}

.app-root .app-stat-value-xl {
  font-size: 34px;
  font-weight: 700;
  color: var(--saip-navy-900);
  letter-spacing: -0.02em;
  margin-top: 6px;
}

.app-root .app-btn-stack {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 10px;
}

.app-root .app-btn-stack .app-btn {
  justify-content: center;
}

.app-root .app-link-arrow {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--saip-teal-600);
}

/* Sign-in hero (Sign In.dc.html port) — auth area on the navy radial
   gradient with the access-controls list beside the card. Scoped by the
   per-page body modifier `is-auth-hero` so other auth pages keep the
   light surface until they are ported. */
.app-root.is-auth-hero .app-main {
  background: var(--saip-gradient-hero);
  padding: var(--saip-spacing-6) 0 var(--saip-spacing-7) 0;
}

.app-root.is-auth-hero .app-footer {
  margin-top: 0;
}

.app-root .app-auth-grid {
  display: grid;
  grid-template-columns: minmax(0, 440px) minmax(0, 1fr);
  gap: 48px;
  align-items: start;
}

@media (max-width: 1000px) {
  .app-root .app-auth-grid {
    grid-template-columns: 1fr;
    gap: 24px;
  }
}

.app-root.is-auth-hero .app-auth-card {
  border: none;
  border-radius: 18px;
  box-shadow: 0 16px 48px rgba(11, 26, 51, 0.30);
  max-width: none;
  margin: 0;
}

.app-root .app-auth-controls {
  color: #cdd9ef;
  padding-top: 4px;
}

.app-root .app-auth-controls .app-auth-controls-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #46E0E3;
}

.app-root .app-auth-controls ul {
  margin: 16px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 13px;
}

.app-root .app-auth-controls li {
  display: flex;
  gap: 11px;
  font-size: 13.5px;
  line-height: 1.5;
  margin: 0;
}

.app-root .app-auth-controls li::before {
  content: "◆";
  color: #46E0E3;
  flex: 0 0 auto;
}

.app-root .app-auth-controls strong {
  color: var(--saip-ice-0);
}

.app-root.is-auth-hero .app-posture-line {
  color: var(--saip-slate-400);
}

/* Upload screen (Upload.dc.html port) — drop zone + pipeline steps. */
.app-root .app-grid-1-4-1 {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(300px, 1fr);
  gap: 18px;
  align-items: start;
}

@media (max-width: 1000px) {
  .app-root .app-grid-1-4-1 {
    grid-template-columns: 1fr;
  }
}

/* FT-W2-DARK-SWEEP-01 — the dropzone was a self-consistent LIGHT card in both
   modes (a white ice-50 card floating on the dark canvas). Folded onto the
   semantic tier so the dark map repaints it; light values are identical. The
   green has-file success state stays on the primitive (FT-DC-PILL-CONTRAST-AA
   scope). */
.app-root .app-dropzone {
  margin-top: 18px;
  border: 2px dashed var(--ps-border-strong);
  border-radius: 14px;
  background: var(--ps-bg-surface-muted);
  padding: 30px 24px;
  text-align: center;
}

.app-root .app-dropzone-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 12px;
  background: var(--ps-sev-info-bg);
  color: var(--ps-sev-info-fg);
  font-size: 24px;
  margin-bottom: 12px;
}

.app-root .app-dropzone-title {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--ps-text-heading);
}

.app-root .app-dropzone-hint {
  margin: 8px 0 0;
  font-size: 12px;
  color: var(--ps-text-muted);
}

.app-root .app-dropzone input[type="file"] {
  margin-top: 12px;
  font-size: 12.5px;
  max-width: 100%;
}
/* Drop feedback (wired by dropzone.js) — global so the upload panel + Profile
   Delta zones both show drag-over highlight + the chosen filename. */
.app-root .app-dropzone { cursor: pointer; }
.app-root .app-dropzone.is-dragover { border-color: var(--ps-text-heading-brand); background: var(--ps-bg-canvas); }
.app-root .app-dropzone.has-file { border-color: var(--saip-green-500); background: var(--saip-green-50); }
.app-root .app-dropzone-filename { margin: 8px 0 0; font-weight: 600; font-size: 12.5px; color: var(--ps-sev-pass-fg); }

.app-root .app-steps {
  margin-top: 14px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.app-root .app-step {
  display: flex;
  gap: 13px;
}

.app-root .app-step-num {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--saip-navy-900);
  color: var(--saip-ice-0);
  font-size: 12px;
  font-weight: 700;
}

.app-root .app-step-num.is-active {
  background: var(--saip-gradient-cta-primary);
}

.app-root .app-step-num.is-muted {
  background: var(--saip-grey-200);
  color: var(--saip-grey-500);
}

.app-root .app-step-title {
  margin: 0;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--saip-navy-900);
}

.app-root .app-step-desc {
  margin: 2px 0 0;
  font-size: 12.5px;
  color: var(--saip-grey-500);
  line-height: 1.5;
}

/* Loading skeletons (02 - Edge States.dc.html §5) — pulse 1.4s
   ease-in-out, blocks #E2E7EE on #F4F7FB, mirroring the layout being
   loaded. Server-rendered pages use them on async surfaces only. */
@keyframes app-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.45; }
}

.app-root .app-skeleton-bar {
  height: 12px;
  border-radius: 6px;
  background: var(--saip-grey-200);
  animation: app-pulse 1.4s ease-in-out infinite;
}

.app-root .app-skeleton-pill {
  width: 64px;
  height: 14px;
  border-radius: 999px;
  background: var(--saip-grey-200);
  animation: app-pulse 1.4s ease-in-out infinite;
}

.app-root .app-skeleton-tile {
  height: 64px;
  border-radius: 10px;
  background: var(--saip-ice-100);
  border: 1px solid var(--saip-grey-200);
  animation: app-pulse 1.4s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .app-root .app-skeleton-bar,
  .app-root .app-skeleton-pill,
  .app-root .app-skeleton-tile {
    animation: none;
  }
}

/* Upload — guided analysis-progress overlay (Sponsor 2026-06-12;
   fetch rework + polish 2026-06-16). A dimmed full-viewport backdrop with a
   clean centered card; the form is submitted via fetch() so the animation
   actually runs (a native navigation would freeze JS timers). */
.app-root .app-progress-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
  overflow-y: auto;
}

/* display:flex above would defeat the hidden attribute's display:none —
   keep the server-rendered hidden state authoritative. */
.app-root .app-progress-overlay[hidden] {
  display: none;
}

/* Dimmed, lightly-blurred backdrop covering the whole viewport so the page
   chrome behind reads as cleanly dimmed (not washed-out / missing). */
.app-root .app-progress-backdrop {
  position: fixed;
  inset: 0;
  z-index: -1;
  background: rgba(8, 21, 43, 0.55); /* --saip-navy-900 @ 55% */
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}

.app-root .app-progress-card {
  position: relative;
  width: min(520px, 100%);
  background: var(--saip-ice-0);
  border-radius: var(--saip-radius-lg);
  box-shadow: var(--saip-shadow-lg);
  padding: var(--saip-spacing-6);
  animation: app-progress-card-in 0.22s ease-out;
}

@keyframes app-progress-card-in {
  from { opacity: 0; transform: translateY(8px) scale(0.985); }
  to { opacity: 1; transform: none; }
}

/* Title + climbing percentage on one row. */
.app-root .app-progress-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}

.app-root .app-progress-title {
  margin: 0;
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--saip-navy-800);
}

.app-root .app-progress-percent {
  font-size: 26px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--saip-teal-600);
  letter-spacing: -0.01em;
}

/* Determinate progress bar — a smooth fill that climbs toward the cap. */
.app-root .app-progress-bar {
  height: 8px;
  border-radius: 999px;
  background: var(--saip-grey-200);
  overflow: hidden;
  margin: 0 0 14px;
  position: relative;
}

/* Honest wait line under the bar. */
.app-root .app-progress-wait {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--saip-grey-500);
  margin: 0 0 18px;
}

/* Retryable error line (network / unexpected non-2xx). */
.app-root .app-progress-error {
  margin: 14px 0 0;
  padding: 10px 12px;
  border-radius: var(--saip-radius-sm);
  background: #fdecec;
  border: 1px solid #f3c2c2;
  color: #9a2a2a;
  font-size: 12.5px;
  line-height: 1.45;
}

.app-root .app-progress-error[hidden] {
  display: none;
}

.app-root .app-progress-bar-fill {
  height: 100%;
  width: 0%;
  border-radius: 999px;
  background: var(--saip-gradient-cta-primary);
  transition: width 0.28s ease-out;
}

/* Step list — done / active / pending visual states. */
.app-root .app-progress-steps {
  margin-top: 4px;
  border-top: 1px solid var(--saip-grey-200);
}

.app-root .app-progress-step {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--saip-grey-200);
  font-size: 13.5px;
  color: var(--saip-grey-400);
  transition: color 0.2s ease;
}

.app-root .app-progress-step:last-child {
  border-bottom: none;
}

/* The status marker — a small disc that becomes a check (done) or an
   accented pulsing dot (active). */
.app-root .app-progress-step-mark {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 999px;
  border: 2px solid var(--saip-grey-300);
  background: var(--saip-ice-0);
  font-size: 12px;
  line-height: 1;
  color: var(--saip-ice-0);
}

/* Pending (default) — muted text, hollow marker. */
.app-root .app-progress-step[data-step-state="pending"] {
  color: var(--saip-grey-400);
}

/* Active — highlighted text + accent marker with a subtle pulse. */
.app-root .app-progress-step[data-step-state="active"] {
  color: var(--saip-grey-700);
  font-weight: 600;
}

.app-root .app-progress-step[data-step-state="active"] .app-progress-step-mark {
  border-color: var(--saip-teal-500);
  background: var(--saip-teal-50);
  animation: app-progress-pulse 1.2s ease-in-out infinite;
}

/* Done — recovered text colour + filled teal marker with a check glyph. */
.app-root .app-progress-step[data-step-state="done"] {
  color: var(--saip-grey-700);
}

.app-root .app-progress-step[data-step-state="done"] .app-progress-step-mark {
  border-color: var(--saip-teal-600);
  background: var(--saip-teal-600);
}

.app-root .app-progress-step[data-step-state="done"] .app-progress-step-mark::after {
  content: "\2713"; /* ✓ */
}

@keyframes app-progress-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(31, 168, 171, 0.45); }
  50% { box-shadow: 0 0 0 5px rgba(31, 168, 171, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .app-root .app-progress-bar-fill {
    transition: none;
  }
  .app-root .app-progress-card {
    animation: none;
  }
  .app-root .app-progress-step[data-step-state="active"] .app-progress-step-mark {
    animation: none;
  }
}

/* In-content posture footer line (charter rule: on every page). */
.app-root .app-posture-line {
  margin: 20px 0 0;
  font-size: 11px;
  color: var(--saip-grey-400);
}

/* §2.8 — conformity rule (semantic only): green = matches standard,
   red = does not match, gray = standard undefined. */
.app-root .app-conf-match {
  color: var(--saip-green-500);
  font-weight: 600;
}

.app-root .app-conf-mismatch {
  color: var(--saip-rose-500);
  font-weight: 600;
}

.app-root .app-conf-undefined {
  color: var(--saip-grey-400);
  font-weight: 600;
}

/* -----------------------------------------------------------
   Filter chips (admin lists)
   ----------------------------------------------------------- */

.app-root .app-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--saip-spacing-2);
  margin-bottom: var(--saip-spacing-4);
}

.app-root .app-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  background: var(--saip-ice-0);
  border: 1px solid var(--saip-grey-300);
  border-radius: 999px;
  color: var(--saip-navy-700);
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
}

.app-root .app-chip:hover {
  background: var(--saip-ice-50);
  text-decoration: none;
}

.app-root .app-chip.is-active {
  background: var(--saip-navy-800);
  color: var(--saip-ice-0);
  border-color: transparent;
}

.app-root .app-chip .app-chip-count {
  background: rgba(255, 255, 255, 0.16);
  color: inherit;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
}

.app-root .app-chip:not(.is-active) .app-chip-count {
  background: var(--saip-ice-100);
  color: var(--saip-grey-700);
}

/* -----------------------------------------------------------
   Empty state
   ----------------------------------------------------------- */

.app-root .app-empty {
  text-align: center;
  background: var(--saip-ice-50);
  border: 1px dashed var(--saip-grey-300);
  border-radius: var(--saip-radius);
  padding: var(--saip-spacing-7) var(--saip-spacing-6);
  color: var(--saip-grey-700);
}

/* Edge-state variants (02 - Edge States.dc.html §4). */
.app-root .app-empty.is-success {
  background: var(--saip-ice-0);
  border-style: solid;
  border-color: var(--saip-grey-200);
  box-shadow: var(--saip-shadow-card);
}

/* UX-REFONTE-W4-COMPONENT-LAYER-01 §2 (A5) — inline-SVG icon glyph.
   Renders via {{ icon('name') }} → <svg class="app-icon"><use href="#i-name">.
   Sizes to the surrounding text (1em), inherits its colour (currentColor) so
   semantic state stays in the pill/text, never hard-coded on the glyph. */
.app-root .app-icon,
.hp-root .app-icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  vertical-align: -0.125em;
  flex: none;
  /* stroke + fill both currentColor: outline symbols set fill="none" on their
     own <symbol>, which overrides this, so this is safe for them; a future
     fill-based symbol (no fill="none") will pick up currentColor and be visible */
  fill: currentColor;
  stroke: currentColor;
  color: currentColor;
}

.app-root .app-empty.is-success .app-empty-icon {
  background: var(--saip-green-50);
  color: var(--saip-green-500);
}

.app-root .app-empty.is-nomatch .app-empty-icon {
  background: var(--saip-ice-100);
  color: var(--saip-grey-400);
}

.app-root .app-empty .app-empty-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--saip-teal-50);
  color: var(--saip-teal-600);
  font-weight: 700;
  font-size: 18px;
  margin-bottom: var(--saip-spacing-3);
}

.app-root .app-empty h3 {
  margin: 0 0 var(--saip-spacing-2) 0;
  color: var(--saip-navy-800);
}

.app-root .app-empty p {
  font-size: 13.5px;
  color: var(--saip-grey-500);
  max-width: 480px;
  margin: 0 auto var(--saip-spacing-4) auto;
}

/* -----------------------------------------------------------
   Footer
   ----------------------------------------------------------- */

.app-root .app-footer {
  background: var(--saip-navy-900);
  color: var(--saip-slate-400);
  padding: var(--saip-spacing-5) 0;
  margin-top: var(--saip-spacing-7);
  font-size: 12px;
}

.app-root .app-footer-inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--saip-spacing-3);
}

.app-root .app-footer a {
  color: var(--saip-slate-400);
  text-decoration: none;
}

.app-root .app-footer a:hover {
  color: var(--saip-ice-0);
}

.app-root .app-footer-posture {
  font-size: 11px;
}

/* -----------------------------------------------------------
   Inline severity hint (for the dashboard sessions table)
   ----------------------------------------------------------- */

.app-root .app-sev-line {
  font-family: var(--saip-font-mono);
  font-size: 12px;
}

.app-root .app-sev-line .pass {
  color: var(--saip-green-500);
  font-weight: 700;
}

.app-root .app-sev-line .fail {
  color: var(--saip-rose-500);
  font-weight: 700;
}

.app-root .app-sev-line .skip {
  color: var(--saip-grey-500);
  font-weight: 600;
}

/* -----------------------------------------------------------
   Auth pages (login / request-access / password reset)
   ----------------------------------------------------------- */

.app-root .app-auth-card {
  background: var(--saip-ice-0);
  border: 1px solid var(--saip-grey-200);
  border-radius: var(--saip-radius);
  box-shadow: var(--saip-shadow-card);
  padding: var(--saip-spacing-7) var(--saip-spacing-6);
  max-width: 540px;
  margin: var(--saip-spacing-5) auto;
}

.app-root .app-auth-card h2 {
  margin-top: 0;
  border-bottom: none;
  padding-bottom: 0;
}

.app-root .app-auth-card .app-auth-meta {
  font-size: 13px;
  color: var(--saip-grey-500);
  margin-bottom: var(--saip-spacing-4);
}

.app-root .app-auth-card .app-auth-help {
  margin-top: var(--saip-spacing-5);
  border-top: 1px solid var(--saip-grey-200);
  padding-top: var(--saip-spacing-4);
  font-size: 12.5px;
  color: var(--saip-grey-500);
}

/* -----------------------------------------------------------
   Responsive tweaks
   ----------------------------------------------------------- */

@media (max-width: 720px) {
  .app-root .app-header-inner {
    flex-direction: column;
    align-items: flex-start;
  }
  /* Copie-conforme chrome: the in-header identity is desktop chrome; on a
     phone it would wrap into a second line — account identity stays one tap
     away on /profile. */
  .app-root .app-header-user {
    display: none;
  }
  .app-root .app-wrap {
    padding: 0 16px;
  }
  /* M22-BRAND-02-R1 — keep the mark prominent but clean on mobile. */
  .app-root .app-wordmark .app-wordmark-mark {
    width: var(--ps-logo-app-header-mobile);
    height: var(--ps-logo-app-header-mobile);
  }
  .app-root .app-wordmark { font-size: 20px; }
  .app-root .app-section {
    padding: var(--saip-spacing-4) var(--saip-spacing-4);
  }
  .app-root h1 {
    font-size: 22px;
  }
  .app-root h2 {
    font-size: 18px;
  }
  .app-root .app-stat-card .app-stat-value {
    font-size: 16px;
  }
  .app-root .app-footer-inner {
    flex-direction: column;
    align-items: flex-start;
  }
  .app-root .app-form-row input,
  .app-root .app-form-row textarea {
    font-size: 16px; /* prevent iOS zoom-in on focus */
  }
}

/* -----------------------------------------------------------
   Reduced motion + transparency (mirrors .lp-root)
   ----------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .app-root *,
  .app-root *::before,
  .app-root *::after {
    transition: none !important;
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
  }
}

@media (prefers-reduced-transparency: reduce) {
  .app-root .app-section,
  .app-root .app-stat-card,
  .app-root .app-auth-card,
  .app-root .app-empty,
  .app-root .app-banner {
    box-shadow: none;
  }
}

/* -----------------------------------------------------------
   Phase 83B — Profile Explorer UX refresh.

   Additive only. Re-uses existing design tokens; introduces no
   new colour values. All rules namespaced under `.app-root` to
   match the rest of the design system.
   ----------------------------------------------------------- */

.app-root .pe-sticky-header {
  position: sticky;
  top: 0;
  z-index: 30;
  background: var(--saip-ice-0);
  border: 1px solid var(--saip-grey-200);
  border-radius: var(--saip-radius);
  padding: var(--saip-spacing-3) var(--saip-spacing-4);
  margin-bottom: var(--saip-spacing-3);
  box-shadow: 0 1px 3px rgba(11, 26, 51, 0.06);
}

.app-root .pe-sticky-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.app-root .pe-sticky-row-primary {
  margin-bottom: 4px;
}

.app-root .pe-sticky-eyebrow {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 700;
  color: var(--saip-navy-800);
  margin-right: 4px;
}

.app-root .pe-sticky-stat {
  font-size: 12px;
  color: var(--saip-grey-700);
  padding: 3px 8px;
  border-radius: 999px;
  border: 1px solid var(--saip-grey-200);
  background: var(--saip-ice-50);
}

.app-root .pe-sticky-stat.is-pass {
  border-color: #bcdcc4;
  background: var(--saip-green-50);
  color: var(--saip-green-500);
}

.app-root .pe-sticky-stat.is-fail {
  border-color: #f0c987;
  background: var(--saip-amber-50);
  color: var(--saip-amber-500);
}

.app-root .pe-sticky-stat.is-info {
  border-color: #b6dcdd;
  background: var(--saip-teal-50);
  color: var(--saip-teal-600);
}

.app-root .pe-sticky-stat code {
  font-family: var(--saip-font-mono);
  font-weight: 700;
}

/* M22-UX-05a — at-a-glance status tiles (clickable jump anchors).
   Rendered as a sibling immediately below the sticky header (NOT inside
   the pinned box) so the pinned header height is unchanged — journey_07
   asserts the header pins at top:0 within ±1px even at full-page scroll. */
.app-root .pe-glance-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  margin-top: -4px;
  margin-bottom: var(--saip-spacing-3);
}

.app-root .pe-glance-tile {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--saip-grey-200);
  background: var(--saip-ice-50);
  text-decoration: none;
  color: var(--saip-grey-700);
  line-height: 1.4;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.app-root .pe-glance-tile:hover,
.app-root .pe-glance-tile:focus-visible {
  border-color: var(--saip-navy-800);
  box-shadow: 0 1px 4px rgba(11, 26, 51, 0.1);
}

.app-root .pe-glance-tile.is-critical {
  border-color: #f0c987;
  background: var(--saip-amber-50);
}

.app-root .pe-glance-tile.is-major {
  border-color: #f0c987;
  background: var(--saip-amber-50);
}

.app-root .pe-glance-tile.is-review {
  border-color: #b6dcdd;
  background: var(--saip-teal-50);
}

.app-root .pe-glance-tile.is-report {
  border-color: #bcdcc4;
  background: var(--saip-green-50);
}

.app-root .pe-glance-clause {
  border-color: var(--saip-navy-800);
  background: var(--saip-ice-0);
  font-weight: 600;
}

.app-root .pe-glance-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 700;
  color: var(--saip-grey-500);
  white-space: nowrap;
}

.app-root .pe-glance-value {
  font-size: 12px;
  color: var(--saip-grey-800);
}

.app-root .pe-glance-value code {
  font-family: var(--saip-font-mono);
  font-weight: 700;
}

.app-root .pe-glance-sev.is-critical {
  color: var(--saip-amber-500);
  font-weight: 600;
}

.app-root .pe-glance-sev.is-major {
  color: var(--saip-amber-500);
}

.app-root .pe-glance-sev.is-minor,
.app-root .pe-glance-sev.is-info {
  color: var(--saip-teal-600);
}

/* TOC pill bar. */
.app-root .pe-toc {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: var(--saip-spacing-3);
  padding: 4px 0;
}

.app-root .pe-toc-pill {
  font-size: 11px;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--ps-border-strong);
  background: var(--ps-bg-surface);
  color: var(--ps-text-heading);
  text-decoration: none;
}

.app-root .pe-toc-pill:hover {
  background: var(--saip-amber-50);
  border-color: var(--saip-amber-500);
}

/* Sub-headings inside the summary section. */
.app-root .pe-summary-subhead {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 700;
  color: var(--saip-navy-800);
  margin-top: var(--saip-spacing-3);
  margin-bottom: var(--saip-spacing-2);
  border-bottom: 1px solid var(--saip-grey-200);
  padding-bottom: 4px;
}

/* Triage grid + tile. */
.app-root .pe-triage-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--saip-spacing-3);
}

.app-root .pe-triage-tile {
  background: var(--saip-amber-50);
  border: 1px solid #f0c987;
  border-radius: var(--saip-radius);
  padding: var(--saip-spacing-3);
}

.app-root .pe-triage-tile.is-empty {
  background: var(--saip-ice-50);
  border-color: var(--saip-grey-200);
  opacity: 0.75;
}

.app-root .pe-triage-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--saip-navy-800);
  margin-bottom: 6px;
}

.app-root .pe-triage-list {
  margin: 0;
  padding-left: 16px;
  font-size: 11px;
}

.app-root .pe-triage-list li {
  margin-bottom: 2px;
}

.app-root .pe-triage-more {
  font-size: 11px;
  color: var(--saip-grey-500);
  margin-top: 4px;
}

.app-root .pe-triage-empty {
  font-size: 11px;
  color: var(--saip-grey-600);
  margin-top: 4px;
}

.app-root .pe-triage-apply {
  margin-top: 8px;
  font-size: 11px;
  padding: 4px 10px;
  border-radius: var(--saip-radius-sm);
  border: 1px solid var(--saip-navy-700);
  background: var(--saip-ice-0);
  color: var(--saip-navy-700);
  cursor: pointer;
}

.app-root .pe-triage-apply:hover {
  background: var(--saip-navy-800);
  color: var(--saip-ice-0);
}

/* Filter chip bar. */
.app-root .pe-filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  margin-bottom: var(--saip-spacing-2);
}

.app-root .pe-filter-chip {
  font-size: 12px;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--saip-grey-300);
  background: var(--saip-ice-0);
  color: var(--saip-navy-700);
  cursor: pointer;
  user-select: none;
  font-family: var(--saip-font-ui);
}

.app-root .pe-filter-chip:hover {
  background: var(--saip-ice-50);
}

.app-root .pe-filter-chip.is-active {
  background: var(--saip-navy-800);
  color: var(--saip-ice-0);
  border-color: var(--saip-navy-800);
}

.app-root .pe-filter-chip code {
  font-family: var(--saip-font-mono);
  font-size: 11px;
}

.app-root .pe-filter-result-count {
  font-size: 11px;
  color: var(--saip-grey-500);
  margin-left: 6px;
}

/* Hidden table rows during filtering. */
.app-root tr.is-hidden { display: none; }

/* -----------------------------------------------------------
   Phase 83F — Profile Explorer filesystem table interactions.

   - Sticky Action / Path / Name columns so the primary "Inspect"
     control and the file identity stay visible even when the
     wider table scrolls horizontally on narrow viewports. The
     remaining columns (Kind / FID / SFI / Structure / Size /
     Content / Decoder / Access / Findings / Std / PE) scroll
     horizontally as before, but never push the action off-
     screen.
   - .pe-fs-row clickable affordance: cursor pointer, hover
     highlight, keyboard-focus ring, selected-row highlight.
   - Name-column source variants: dim grey for the file_id /
     node_id fallback so the user knows when the rendered name
     is synthetic.
   ----------------------------------------------------------- */
.app-root .pe-fs-table-wrap { position: relative; }
.app-root .pe-fs-table { table-layout: auto; }
.app-root .pe-fs-table th.pe-fs-col-action,
.app-root .pe-fs-table td.pe-fs-col-action {
  position: sticky;
  left: 0;
  z-index: 3;
  background: var(--saip-ice-0);
  min-width: 110px;
  box-shadow: 1px 0 0 var(--saip-grey-200);
}
.app-root .pe-fs-table th.pe-fs-col-path,
.app-root .pe-fs-table td.pe-fs-col-path {
  position: sticky;
  left: 110px;
  z-index: 2;
  background: var(--saip-ice-0);
  min-width: 200px;
}
.app-root .pe-fs-table th.pe-fs-col-name,
.app-root .pe-fs-table td.pe-fs-col-name {
  position: sticky;
  left: 310px;
  z-index: 2;
  background: var(--saip-ice-0);
  min-width: 140px;
  box-shadow: 1px 0 0 var(--saip-grey-200);
}
/* Header sticks above the body when the table is taller than its
   wrapper, so column labels never disappear during scroll. */
.app-root .pe-fs-table thead th {
  position: sticky;
  top: 0;
  z-index: 4;
  background: var(--saip-ice-50);
}
.app-root .pe-fs-table thead th.pe-fs-col-action { z-index: 5; }
.app-root .pe-fs-table thead th.pe-fs-col-path,
.app-root .pe-fs-table thead th.pe-fs-col-name { z-index: 5; }
/* Clickable row affordance. */
.app-root tr.pe-fs-row {
  cursor: pointer;
  transition: background 100ms ease-out;
}
.app-root tr.pe-fs-row:hover td {
  background: var(--saip-amber-50);
}
.app-root tr.pe-fs-row:focus {
  outline: 2px solid var(--ps-focus-ring);
  outline-offset: -2px;
}
.app-root tr.pe-fs-row.is-selected td {
  background: var(--saip-amber-50);
  border-left: 3px solid var(--saip-amber-500);
}
.app-root tr.pe-fs-row.is-selected td.pe-fs-col-action {
  background: var(--saip-amber-50);
}
.app-root tr.pe-fs-row.is-selected td.pe-fs-col-path,
.app-root tr.pe-fs-row.is-selected td.pe-fs-col-name {
  background: var(--saip-amber-50);
}
/* Name-column source colour-coding (deterministic; passive). */
.app-root .pe-fs-col-name.pe-fs-name-well_known code,
.app-root .pe-fs-col-name.pe-fs-name-canonical code {
  color: var(--saip-navy-800);
  font-weight: 600;
}
.app-root .pe-fs-col-name.pe-fs-name-inline_tag code {
  color: var(--saip-navy-700);
}
.app-root .pe-fs-col-name.pe-fs-name-file_id code {
  color: var(--saip-grey-700);
}
.app-root .pe-fs-col-name.pe-fs-name-node_id code,
.app-root .pe-fs-col-name.pe-fs-name-unknown code {
  color: var(--saip-grey-500);
}
/* Inspect button + toggle button live in the same cell. */
.app-root .pe-fs-col-action .pe-row-focus {
  margin-right: 4px;
}

/* Inline detail row toggle button. */
.app-root .pe-row-toggle {
  display: inline-block;
  font-size: 12px;
  padding: 2px 8px;
  border-radius: var(--saip-radius-sm);
  border: 1px solid var(--saip-grey-300);
  background: var(--saip-ice-0);
  color: var(--saip-navy-700);
  cursor: pointer;
}

.app-root .pe-row-toggle:hover {
  background: var(--saip-amber-50);
  border-color: var(--saip-amber-500);
}

/* Paired detail row body. */
.app-root tr.pe-row-detail-row > td {
  background: var(--saip-ice-50);
  border-bottom: 1px solid var(--saip-grey-200);
  padding: 0;
}

.app-root .pe-row-detail-body {
  padding: var(--saip-spacing-3) var(--saip-spacing-4);
}

.app-root .pe-row-detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--saip-spacing-3);
}

.app-root .pe-row-detail-kv {
  display: flex;
  flex-direction: column;
  margin-bottom: 6px;
  font-size: 12px;
}

.app-root .pe-row-detail-kv > span:first-child {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 700;
  color: var(--saip-grey-500);
  margin-bottom: 2px;
}

.app-root .pe-row-detail-kv code {
  font-family: var(--saip-font-mono);
  font-size: 11px;
}

/* Profile Elements collapsible wrapper. */
.app-root details.pe-pes-collapse > summary {
  cursor: pointer;
  font-size: 12px;
  color: var(--saip-navy-700);
  padding: 6px 0;
  font-weight: 600;
}

.app-root details.pe-pes-collapse[open] > summary {
  color: var(--saip-navy-800);
  margin-bottom: var(--saip-spacing-2);
}

/* MR-M21-09c HOTFIX2 — reduce the file-system table from 14 columns
   to 7 by default. The original column set tried to fit too much in
   one row; an expert needs the IDENTITY of the file first (action /
   path / name / kind / FID), its STRUCTURE (transparent / linear_fixed
   + match badge), and its SIZE. Everything else (Content count /
   Decoder pill / Access status / Findings count / Std family / PE
   index / SFI) is one click away via the per-row ▼ expand button
   AND is also rendered as filter-chip metadata + per-row data-*
   attributes — so the data isn't hidden, just decluttered. */
.app-root table#profile-explorer-filesystem-table th:nth-child(6),
.app-root table#profile-explorer-filesystem-table td:nth-child(6),   /* SFI */
.app-root table#profile-explorer-filesystem-table th:nth-child(9),
.app-root table#profile-explorer-filesystem-table td:nth-child(9),   /* Content */
.app-root table#profile-explorer-filesystem-table th:nth-child(10),
.app-root table#profile-explorer-filesystem-table td:nth-child(10),  /* Decoder */
.app-root table#profile-explorer-filesystem-table th:nth-child(11),
.app-root table#profile-explorer-filesystem-table td:nth-child(11),  /* Access */
.app-root table#profile-explorer-filesystem-table th:nth-child(12),
.app-root table#profile-explorer-filesystem-table td:nth-child(12),  /* Findings count */
.app-root table#profile-explorer-filesystem-table th:nth-child(13),
.app-root table#profile-explorer-filesystem-table td:nth-child(13),  /* Std family */
.app-root table#profile-explorer-filesystem-table th:nth-child(14),
.app-root table#profile-explorer-filesystem-table td:nth-child(14)   /* PE index */ {
  display: none;
}

@media (max-width: 900px) {
  /* Narrow viewport — also hide the Kind pill (encoded in the icon
     + path already). */
  .app-root table#profile-explorer-filesystem-table th:nth-child(4),
  .app-root table#profile-explorer-filesystem-table td:nth-child(4) {
    display: none;
  }
}

/* HANDOFF §2.1 (supersedes MR-M21-09c navy header) — FS-table header
   stays LIGHT like every in-app table; visibility comes from the
   uppercase 700 type + the hairline, not a navy band. */
.app-root .pe-fs-table thead th {
  background: var(--saip-ice-50) !important;
  color: var(--saip-grey-500);
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 700;
  padding: 6px 8px;
  border-bottom: 1px solid var(--saip-grey-200);
}

/* Keep the sticky-left header cells matching the row background-shift
   when the table scrolls horizontally. */
.app-root .pe-fs-table thead th.pe-fs-col-action,
.app-root .pe-fs-table thead th.pe-fs-col-path,
.app-root .pe-fs-table thead th.pe-fs-col-name {
  background: var(--saip-ice-50) !important;
  color: var(--saip-grey-500);
}

/* -----------------------------------------------------------
   Phase 83D — Two-column workspace + consolidated findings panel.

   Additive only — reuses existing tokens; no new colour values
   introduced. The workspace places the file table in a left column
   and the per-file detail panel in a right sticky column so an
   expert can scan files and read their detail without scrolling.
   Below 900 px the grid collapses to a single column and the
   sticky pin releases.
   ----------------------------------------------------------- */

.app-root .pe-workspace {
  display: grid;
  /* MR-M21-09c HOTFIX2 — drop the 2-col mode entirely. The Sponsor
     2026-05-28 review showed the 14-column file system table can
     never fit cleanly in a 2-col workspace's narrow left lane on
     typical laptop viewports. Always stacked: file system table on
     top at full width, EF detail panel below at full width. The
     legacy 2-col rule below now never applies — preserved for the
     phase_83d literal-string contract test only. */
  grid-template-columns: 1fr;
  gap: var(--saip-spacing-4);
  align-items: start;
  margin-bottom: var(--saip-spacing-4);
}

.app-root .pe-workspace > .pe-workspace-left,
.app-root .pe-workspace > .pe-workspace-right {
  min-width: 0;
}

/* MR-M4-06 — the right grid cell must STRETCH to the full row height so the
   nested sticky `.pe-detail-panel` has a tall containing block to pin within.
   The grid sets `align-items: start`, which would otherwise leave this cell
   content-height; a sticky element inside a content-height block has no room
   to stick and simply scrolls away with the page (proven by journey 10 —
   the panel moved the full scroll delta despite `position: sticky`). */
.app-root .pe-workspace > .pe-workspace-right {
  align-self: stretch;
}

.app-root .pe-detail-panel {
  /* MR-M21-09c HOTFIX2 — workspace always stacked, so sticky pinning
     is no longer relevant. Position is static; the panel sits below
     the file-system table at full content width. */
  position: static;
  background: var(--saip-ice-0);
  border: 1px solid var(--saip-grey-200);
  border-radius: var(--saip-radius);
  padding: var(--saip-spacing-3);
  box-shadow: 0 1px 3px rgba(11, 26, 51, 0.06);
  /* MR-M21-09 — establish a CSS container so the kv rows inside can
     reflow based on the panel's own width (independent of viewport). */
  container-type: inline-size;
  container-name: pe-detail-panel;
}

/* MR-M21-09 — protect dense expert content from near-vertical rendering.
   Long unbreakable hex tokens (AID/TAR/FID/rule IDs) use overflow-wrap so
   one identifier never pushes the panel to its narrowest column width.
   The min-width:0 on .app-kv-v lets a wide nested table shrink without
   forcing a horizontal scroll on the whole panel. */
.app-root .pe-detail-panel code,
.app-root .pe-detail-panel-eyebrow code {
  overflow-wrap: anywhere;
}
.app-root .pe-detail-panel .app-kv .app-kv-v {
  min-width: 0;
}
/* Nested expert tables (decoded payload, conformance) inside the kv
   value column scroll horizontally rather than render at one character
   per line when the panel is narrower than the table's natural width. */
.app-root .pe-detail-panel .app-kv .app-kv-v > table.app-table {
  display: block;
  overflow-x: auto;
  max-width: 100%;
}

/* MR-M21-09 — container-query collapse. When the panel itself is
   narrower than ~520px (regardless of viewport size — happens when the
   user opens a sidebar or uses a partner browser at fixed width), the
   .app-kv rows switch to a stacked label/value layout, returning the
   full panel width to the value column. Solves the "near-vertical
   text" BETA defect reported on the EF detail panel. */
@container pe-detail-panel (max-width: 520px) {
  .app-kv {
    flex-direction: column;
    gap: 2px;
  }
  .app-kv .app-kv-k {
    flex: none;
  }
}

.app-root .pe-detail-panel > .app-section {
  margin-bottom: var(--saip-spacing-3);
  padding: 0;
  background: transparent;
  border: none;
  box-shadow: none;
}

.app-root .pe-detail-panel > .app-section:last-child {
  margin-bottom: 0;
}

.app-root .pe-detail-panel h2 {
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--saip-navy-800);
  margin: 0 0 var(--saip-spacing-2) 0;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--saip-grey-200);
}

.app-root .pe-detail-panel-eyebrow {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--saip-grey-500);
  font-weight: 700;
  margin-bottom: 4px;
}

/* Consolidated findings panel (grouped by severity). */
.app-root .pe-finding-group {
  margin-bottom: var(--saip-spacing-3);
  border-left: 4px solid var(--saip-grey-200);
  background: var(--saip-ice-50);
  padding: var(--saip-spacing-2) var(--saip-spacing-3);
  border-radius: var(--saip-radius);
}

.app-root .pe-finding-group.is-critical { border-left-color: var(--saip-rose-500); background: var(--saip-rose-50); }
.app-root .pe-finding-group.is-major    { border-left-color: var(--saip-amber-500); background: var(--saip-amber-50); }
.app-root .pe-finding-group.is-minor    { border-left-color: var(--ps-sev-minor-fg); background: var(--saip-amber-50); }
.app-root .pe-finding-group.is-info     { border-left-color: var(--saip-teal-600); background: var(--saip-teal-50); }
.app-root .pe-finding-group.is-pass     { border-left-color: var(--saip-green-500); background: var(--saip-green-50); }
.app-root .pe-finding-group.is-skipped  { border-left-color: var(--saip-grey-500); }
.app-root .pe-finding-group.is-error    { border-left-color: var(--saip-grey-700); }

.app-root .pe-finding-group-header {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  font-weight: 700;
  color: var(--saip-navy-800);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: var(--saip-spacing-2);
}

.app-root .pe-finding-group-header-count {
  font-family: var(--saip-font-mono);
  font-weight: 600;
  color: var(--saip-grey-700);
}

/* Wrap legacy mock-pack and candidate-rule tables on result pages
   into a discreet <details> shell. */
.app-root details.pe-legacy-collapse > summary {
  cursor: pointer;
  font-size: 12px;
  color: var(--saip-navy-700);
  padding: 6px 0;
  font-weight: 600;
}

.app-root details.pe-legacy-collapse[open] > summary {
  color: var(--saip-navy-800);
  margin-bottom: var(--saip-spacing-2);
}

.app-root details.pe-legacy-collapse > summary::before {
  content: "▶ ";
  display: inline-block;
  transition: transform 200ms ease-out;
}

.app-root details.pe-legacy-collapse[open] > summary::before {
  content: "▼ ";
}

/* MR-M21-09 / MR-M21-09c — workspace single-column collapse.
   Originally raised from 900px → 1199px in MR-M21-09; raised again to
   1399px in MR-M21-09c after the Sponsor's live review on a typical
   laptop (1280-1440px viewport) showed the file-system table forced
   into a narrow horizontal-scroll lane with most columns invisible.
   At <=1399px we stack the workspace single-column so both the file
   system table and the EF detail panel get the full content width.
   The journey_10 sticky-detail test viewport (1280px) sits at the
   stacked layout — but its assertions are scrolling-behaviour pinned,
   not two-column-grid pinned. */
@media (max-width: 1399px) {
  .app-root .pe-workspace {
    grid-template-columns: 1fr;
  }
  .app-root .pe-detail-panel {
    position: static;
    max-height: none;
    overflow-y: visible;
  }
}
@media (max-width: 900px) {
  /* Legacy single-column collapse — preserved for archival contracts. */
  .app-root .pe-workspace {
    grid-template-columns: 1fr;
  }
  .app-root .pe-detail-panel {
    position: static;
    max-height: none;
    overflow-y: visible;
  }
}

/* Phase 83D — brief highlight flash when a finding's target jump lands
   the user on the corresponding file row. The class is toggled off by
   the inline JS after ~1.6 s. */
.app-root tr.pe-row-flash {
  animation: pe-row-flash 1.6s ease-out;
}

@keyframes pe-row-flash {
  0% { background: var(--saip-amber-50); }
  50% { background: var(--saip-amber-50); }
  100% { background: transparent; }
}

/* ===========================================================
   MR-M21-09b — Profile Explorer Expert UX Crisis Redesign.

   The MR-M21-09 hotfix collapsed the workspace to single-column at
   <=1199px and added a 440px floor on the right detail panel, but the
   panel itself still stacked 6 dense cards top-to-bottom with no
   landing summary. Sponsor 2026-05-28 live review: still reads as an
   accumulation of widgets, not an expert analysis product.

   This block adds:

     - `.pe-ef-at-a-glance`   — the 30-second expert summary at the
       top of the EF detail panel (definition-list grid, 2-column).
     - `.pe-ef-sections`      — accordion container around the
       MR-M21-03 six expert blocks. Native <details>/<summary>; no JS.
     - `.pe-ef-section`       — one accordion section per block, with
       the Identity section open by default.
     - `.pe-mono`             — controlled monospace token rendering
       that wraps on word boundaries first, character boundary only as
       fallback — never mid-word.
     - `.pe-ef-decoded-list`  — decoded payload rendered as key/value
       cards instead of a nested <table> inside a narrow panel.
     - `.pe-ef-rules-headline` — per-EF rule severity rollup chips
       (material findings first; pass-only collapsed).
     - Hardening: any <code> inside the detail panel uses
       overflow-wrap:anywhere so no rule_id / AID / TAR / FID can ever
       render mid-character at panel widths >=520px.
   =========================================================== */

/* At-a-glance card — landing summary. */
.app-root .pe-ef-at-a-glance {
  background: linear-gradient(180deg, var(--saip-ice-50), var(--saip-ice-0));
  border: 1px solid var(--saip-grey-200);
  border-radius: var(--saip-radius);
  padding: var(--saip-spacing-3) var(--saip-spacing-3) var(--saip-spacing-2);
  margin-bottom: var(--saip-spacing-3);
  box-shadow: 0 1px 2px rgba(11, 26, 51, 0.04);
}

.app-root .pe-ef-at-a-glance-eyebrow {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 700;
  color: var(--saip-navy-800);
  margin-bottom: var(--saip-spacing-2);
  border-bottom: 1px solid var(--saip-grey-200);
  padding-bottom: 4px;
}

.app-root .pe-ef-at-a-glance-grid {
  display: grid;
  grid-template-columns: minmax(0, max-content) minmax(0, 1fr);
  column-gap: var(--saip-spacing-3);
  row-gap: 6px;
  margin: 0;
  font-size: 12px;
  line-height: 1.45;
}

.app-root .pe-ef-at-a-glance-grid > dt {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 700;
  color: var(--saip-grey-500);
  min-width: 0;
  white-space: nowrap;
}

.app-root .pe-ef-at-a-glance-grid > dd {
  margin: 0;
  color: var(--saip-navy-800);
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: normal;
}

.app-root .pe-ef-at-a-glance-sub {
  font-size: 11px;
  color: var(--saip-grey-500);
  margin-left: 6px;
}

.app-root .pe-na {
  font-size: 11px;
  color: var(--saip-grey-500);
  font-style: italic;
}

/* M28-KEYSET-ALGO-MODE-G13-01 — algorithm known but the per-message mode
   bits are not stored in the SAIP keyset (TS 102 225 §5.1.2/§5.1.3 DES rows).
   Renders the honest "algorithm (mode not declared)" label muted, distinct
   from a fully-determinate AES chip. */
.app-root .pe-algo-undeclared {
  font-size: 11px;
  color: var(--saip-grey-600);
  font-style: italic;
}

/* Compact pills used inside the at-a-glance card. */
.app-root .pe-pill-xs {
  font-size: 9px;
  padding: 1px 6px;
  margin-left: 6px;
  vertical-align: middle;
}

/* Mono token rendering — wrap on word boundary first, character boundary
   only as a fallback. NEVER mid-word. */
.app-root .pe-mono {
  font-family: var(--saip-font-mono);
  font-size: 11px;
  overflow-wrap: anywhere;
  word-break: normal;
}

/* Accordion sections wrapping the six MR-M21-03 expert blocks. */
.app-root .pe-ef-sections > details.pe-ef-section {
  border: 1px solid var(--saip-grey-200);
  border-radius: var(--saip-radius);
  background: var(--saip-ice-0);
  margin-bottom: var(--saip-spacing-2);
  overflow: hidden;
}

.app-root details.pe-ef-section > summary.pe-ef-section-summary {
  cursor: pointer;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--saip-navy-800);
  padding: 10px var(--saip-spacing-3);
  background: var(--saip-ice-50);
  list-style: none;
  user-select: none;
}

.app-root details.pe-ef-section > summary.pe-ef-section-summary::-webkit-details-marker {
  display: none;
}

.app-root details.pe-ef-section > summary.pe-ef-section-summary::before {
  content: "▶";
  display: inline-block;
  width: 14px;
  margin-right: 6px;
  font-size: 10px;
  color: var(--saip-grey-500);
  transition: transform 150ms ease-out;
}

.app-root details.pe-ef-section[open] > summary.pe-ef-section-summary::before {
  transform: rotate(90deg);
}

.app-root details.pe-ef-section[open] > summary.pe-ef-section-summary {
  border-bottom: 1px solid var(--saip-grey-200);
}

.app-root details.pe-ef-section > .app-stat-card {
  border: none;
  background: transparent;
  margin: 0;
  padding: var(--saip-spacing-3);
  box-shadow: none;
}

.app-root details.pe-ef-section > .pe-ef-decoded-cards {
  padding: var(--saip-spacing-3);
}

/* Linked-rules severity headline — chips row above the per-tier list. */
.app-root .pe-ef-rules-headline {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  margin-bottom: var(--saip-spacing-2);
  padding: 6px 8px;
  background: var(--saip-grey-50);
  border-radius: var(--saip-radius-sm);
}

.app-root .pe-ef-rules-subnote {
  font-size: 10px;
  color: var(--saip-grey-500);
  font-style: italic;
}

/* Decoded payload — key/value cards (no nested table). */
.app-root .pe-ef-decoded-cards {
  margin-top: var(--saip-spacing-2);
}

.app-root .pe-ef-decoded-cards-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 700;
  color: var(--saip-grey-500);
  margin-bottom: 6px;
}

.app-root ul.pe-ef-decoded-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: 4px;
}

.app-root .pe-ef-decoded-item {
  display: grid;
  grid-template-columns: minmax(0, 140px) minmax(0, 1fr);
  gap: var(--saip-spacing-3);
  padding: 6px 8px;
  background: var(--saip-ice-0);
  border: 1px solid var(--saip-grey-200);
  border-radius: var(--saip-radius-sm);
}

.app-root .pe-ef-decoded-key {
  font-size: 11px;
  color: var(--saip-grey-700);
  font-weight: 600;
  min-width: 0;
  overflow-wrap: anywhere;
}

.app-root .pe-ef-decoded-value {
  font-size: 11px;
  color: var(--saip-navy-800);
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: normal;
}

/* Below 700px (narrow panel) — stack the decoded key/value pair. */
@media (max-width: 700px) {
  .app-root .pe-ef-decoded-item {
    grid-template-columns: 1fr;
    gap: 2px;
  }
}

/* Hardening — every <code> token inside the detail panel uses
   overflow-wrap:break-word (NOT `anywhere`) so identifiers wrap on
   word boundaries first and only break mid-character as a last
   resort. `anywhere` was destroying intrinsic min-content sizing of
   table columns, which collapsed the FIELD column of the L2 data
   tables (decoded payload / conformance / findings / interpreted
   content) to ~1ch and produced character-per-line wrapping. The
   raw-hex blocks keep their intentional `word-break:break-all`
   inline style (hex is meant to break per-character). */
.app-root .pe-detail-panel code:not([data-raw-encoded-full]):not([data-raw-encoded-full-file]):not([data-field="content_hex"]) {
  overflow-wrap: break-word;
  word-break: normal;
}

/* ===========================================================
   MR-M21-09b HOTFIX (sponsor live review 2026-05-28).

   The accordion sections were deployed correctly but their content
   (the legacy MR-M21-03 `.app-kv` rows) still rendered with massive
   blank space between label and value when the container-query
   collapse changed `.app-kv` to flex-column. Root cause: the legacy
   `.app-kv .app-kv-v { flex: 1 }` from line 2043 stretched the value
   to fill the (very tall) column track that flex-column produced
   inside the section card.

   Fix: inside every `.pe-ef-section` of the EF detail panel, REPLACE
   the legacy `.app-kv` flex layout with a deterministic CSS-grid
   layout. The grid has predictable row heights (content-sized) and
   does not stretch. Above 520px panel width we render as a 2-column
   grid (label, value); below 520px we collapse to a single-column
   stack with tight 2px row gap.

   This pattern also drops the redundant eyebrow visual ("1 · Identity",
   "2 · Structure", …) when the accordion summary already names the
   section — those eyebrows are kept in the markup for backwards
   compatibility with the MR-M21-03 visual hooks but visually
   de-emphasised so the section reads as one tight grid.
   =========================================================== */

/* ===========================================================
   MR-M21-09c — Technical-Report-Driven Profile Explorer Rework
   (Sponsor 2026-05-28, AMD-027).

   The IDEMIA EPS technical reports use exactly three layouts for
   every section: L1 (dense bordered Parameter|Value table), L2
   (multi-column dense data table), L3 (numbered subsection heading
   §N.M.K). Every report-mirroring Profile Explorer surface uses
   these three primitives — no cards, no flex kv-rows, no nested
   tables inside <td>, no character-per-line wrapping.

   This block defines the canonical primitives. Per-surface markup
   converts to use them; legacy `.app-kv` / `.app-stat-card` /
   card-grid layouts are deprecated for report-mirroring surfaces.
   =========================================================== */

/* --- L3 — Numbered subsection heading -------------------------- */

.app-root .pe-report-section {
  margin: 0 0 var(--saip-spacing-3);
}

.app-root .pe-report-section-heading {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--saip-navy-800);
  margin: 0 0 6px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--saip-grey-300);
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.app-root .pe-report-section-heading > .pe-report-section-num {
  font-family: var(--saip-font-mono);
  font-size: 11px;
  color: var(--saip-grey-500);
  font-weight: 600;
  min-width: 36px;
}

.app-root .pe-report-section-heading > .pe-report-section-title {
  flex: 1 1 auto;
}

.app-root .pe-report-section-heading > .pe-report-section-meta {
  font-size: 10px;
  color: var(--saip-grey-500);
  font-weight: 500;
  letter-spacing: 0;
}

/* --- L1 — Dense bordered Parameter|Value table ----------------- */
/* Use on a <table class="pe-report-table"> with one <tr> per row,
   <th class="pe-report-k"> for label, <td class="pe-report-v"> for value.
   Or use the <div class="pe-report-table"> + <div class="pe-report-row">
   variant when a real <table> isn't appropriate (no nested table inside
   <td> ever). Both render identically. */

.app-root .pe-report-table {
  width: 100%;
  border-collapse: collapse;
  border: 1px solid var(--saip-grey-300);
  background: var(--saip-ice-0);
  font-size: 11px;
  line-height: 1.4;
  margin: 0 0 var(--saip-spacing-3);
  table-layout: fixed;
}

.app-root .pe-report-table > tbody > tr,
.app-root .pe-report-table > tr,
.app-root div.pe-report-table > .pe-report-row {
  display: table-row;
}

.app-root .pe-report-table .pe-report-k {
  width: 38%;
  padding: 5px 10px;
  background: var(--saip-ice-50);
  border: 1px solid var(--saip-grey-200);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 700;
  color: var(--saip-grey-700);
  vertical-align: top;
  text-align: left;
  word-break: normal;
  overflow-wrap: anywhere;
}

.app-root .pe-report-table .pe-report-v {
  padding: 5px 10px;
  background: var(--saip-ice-0);
  border: 1px solid var(--saip-grey-200);
  color: var(--saip-navy-800);
  vertical-align: top;
  text-align: left;
  word-break: normal;
  overflow-wrap: anywhere;
  min-width: 0;
}

.app-root .pe-report-table .pe-report-v code,
.app-root .pe-report-table .pe-report-v .pe-mono {
  font-family: var(--saip-font-mono);
  font-size: 11px;
  word-break: normal;
  overflow-wrap: anywhere;
}

/* `div.pe-report-table` variant — used where we can't have a <table>
   (e.g. inside another <td>). Identical visuals. */
.app-root div.pe-report-table {
  display: table;
  width: 100%;
}
.app-root div.pe-report-table > .pe-report-row > .pe-report-k,
.app-root div.pe-report-table > .pe-report-row > .pe-report-v {
  display: table-cell;
}

/* --- L2 — Dense multi-column data table ------------------------ */
.app-root .pe-report-data-table {
  width: 100%;
  border-collapse: collapse;
  border: 1px solid var(--saip-grey-300);
  background: var(--saip-ice-0);
  font-size: 11px;
  line-height: 1.4;
  margin: 0 0 var(--saip-spacing-3);
}

.app-root .pe-report-data-table thead th {
  padding: 5px 8px;
  background: var(--saip-ice-50);
  color: var(--saip-grey-500);
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 700;
  text-align: left;
  border: 1px solid var(--saip-grey-200);
  vertical-align: bottom;
}

.app-root .pe-report-data-table tbody td {
  padding: 5px 8px;
  border: 1px solid var(--saip-grey-200);
  vertical-align: top;
  color: var(--saip-navy-800);
  word-break: normal;
  overflow-wrap: break-word;
}

.app-root .pe-report-data-table tbody tr:nth-child(even) td {
  background: var(--saip-ice-50);
}

.app-root .pe-report-data-table tbody td code,
.app-root .pe-report-data-table tbody td .pe-mono {
  font-family: var(--saip-font-mono);
  font-size: 10.5px;
  word-break: normal;
  overflow-wrap: break-word;
}

/* Inside the detail panel, force the L2 data tables to use a fixed
   table layout with explicit first-column width. Without this, the
   browser's auto algorithm collapses the field column to ~1ch when
   the value column carries a long unbreakable string. */
.app-root .pe-detail-panel .pe-report-data-table {
  table-layout: fixed;
  width: 100%;
}
.app-root .pe-detail-panel .pe-report-data-table thead th:first-child,
.app-root .pe-detail-panel .pe-report-data-table tbody td:first-child {
  width: 38%;
}

/* MR-M21-09c HOTFIX3 — explicit widths for the slimmed 5-col per-file
   findings table (Rule id · Title · Status · Severity · Message).
   Rule IDs are long monospace strings — give them 22%. Title needs
   ~26% so sentences don't wrap mid-word. Status / Severity are pill
   columns (~70px each). Message takes the rest. */
.app-root table#profile-explorer-file-findings-table {
  table-layout: fixed;
  width: 100%;
}
.app-root table#profile-explorer-file-findings-table thead th:nth-child(1),
.app-root table#profile-explorer-file-findings-table tbody td:nth-child(1) {
  width: 22%;
}
.app-root table#profile-explorer-file-findings-table thead th:nth-child(2),
.app-root table#profile-explorer-file-findings-table tbody td:nth-child(2) {
  width: 26%;
}
.app-root table#profile-explorer-file-findings-table thead th:nth-child(3),
.app-root table#profile-explorer-file-findings-table tbody td:nth-child(3),
.app-root table#profile-explorer-file-findings-table thead th:nth-child(4),
.app-root table#profile-explorer-file-findings-table tbody td:nth-child(4) {
  width: 8%;
}

/* Right-align numeric columns. */
.app-root .pe-report-data-table th.pe-report-num,
.app-root .pe-report-data-table td.pe-report-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Subdued caption row used for empty-data fallbacks. */
.app-root .pe-report-empty {
  padding: 8px 10px;
  font-size: 11px;
  color: var(--saip-grey-500);
  font-style: italic;
  border: 1px dashed var(--saip-grey-200);
  background: var(--saip-ice-50);
  border-radius: var(--saip-radius-sm);
  margin: 0 0 var(--saip-spacing-3);
}

/* --- Subtle table when nested inside accordion section --------- */
.app-root details.pe-ef-section .pe-report-table,
.app-root details.pe-ef-section .pe-report-data-table {
  margin-bottom: 0;
}

/* === Legacy MR-M21-09b CSS retained below for completeness ==== */

/* MR-M21-09b HOTFIX2 (sponsor live review 2026-05-28).
   Render the legacy `.app-kv` rows inside `.pe-ef-section` as a dense,
   bordered Parameter | Value table — the format expert technical
   reports use (IDEMIA EPS 2.4.1 3G Codes / 2.4.2 ADM Codes / 2.10
   Application tables). Single source of truth for the EF detail panel:
   every "kv row" is one table row with the parameter name on the left
   and the decoded value on the right, separated by a hairline border.
   No stretching, no card padding, no blank space between label and
   value.
   MR-M21-09c (Sponsor live re-review): the kept block below applies
   only to the LEGACY `.app-kv` markup that has not yet been rewritten.
   New surfaces use `.pe-report-table` / `.pe-report-data-table`
   directly. */

/* Strip the residual card chrome — inside an accordion section the
   surrounding accordion already provides borders + header. The card
   becomes a tight inline table container. */
.app-root .pe-detail-panel .pe-ef-section .app-stat-card {
  display: block;
  padding: 0;
  margin: 0;
  border: none;
  background: transparent;
  box-shadow: none;
}

/* Hide the legacy "1 · Identity" / "2 · Structure" eyebrow visual noise
   inside each accordion section. The accordion summary already names
   the section — the eyebrow is keeping it as a textual hook for the
   MR-M21-03 regression tests but removing it from view. */
.app-root .pe-detail-panel .pe-ef-section .app-stat-card > div:first-child:not([class]) {
  position: absolute !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(1px,1px,1px,1px);
  white-space: nowrap;
  margin: -1px;
  padding: 0;
  border: 0;
}

/* The legacy `.app-kv` row becomes a TABLE-ROW visual: a 2-column grid
   (label,value) with a hairline border, just like the EPS Parameter|Value
   tables. Predictable height = content height. NO stretching. */
.app-root .pe-detail-panel .pe-ef-section .app-kv {
  display: grid;
  grid-template-columns: minmax(140px, 38%) minmax(0, 1fr);
  column-gap: 0;
  row-gap: 0;
  padding: 0;
  border: 1px solid var(--saip-grey-200);
  border-top: none;
  font-size: 11px;
  background: var(--saip-ice-0);
}

.app-root .pe-detail-panel .pe-ef-section .app-kv:first-of-type {
  border-top: 1px solid var(--saip-grey-200);
  border-top-left-radius: var(--saip-radius-sm);
  border-top-right-radius: var(--saip-radius-sm);
}

.app-root .pe-detail-panel .pe-ef-section .app-kv:last-of-type {
  border-bottom-left-radius: var(--saip-radius-sm);
  border-bottom-right-radius: var(--saip-radius-sm);
}

.app-root .pe-detail-panel .pe-ef-section .app-kv > .app-kv-k {
  display: block;
  flex: none;
  align-self: stretch;
  padding: 6px 10px;
  background: var(--saip-ice-50);
  border-right: 1px solid var(--saip-grey-200);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 700;
  color: var(--saip-grey-700);
  margin: 0;
  line-height: 1.3;
  word-break: normal;
  overflow-wrap: anywhere;
}

.app-root .pe-detail-panel .pe-ef-section .app-kv > .app-kv-v {
  display: block;
  flex: none;
  align-self: stretch;
  padding: 6px 10px;
  min-width: 0;
  font-size: 11px;
  color: var(--saip-navy-800);
  margin: 0;
  line-height: 1.4;
  word-break: normal;
  overflow-wrap: anywhere;
}

/* The legacy "interpretation_state pill row" + decoded-cards + raw-hex
   <details> inside the Content section are NOT .app-kv rows; tighten
   their margins so they sit flush against the table. */
.app-root .pe-detail-panel .pe-ef-section .pe-ef-decoded-cards {
  padding: 0;
  margin: 8px 0 0;
}

/* On very narrow panel widths (<=420px), the 2-col table collapses to
   a single column. Each cell becomes its own row inside the same
   bordered container — still no blank space, just stacked. */
@container pe-detail-panel (max-width: 420px) {
  .pe-detail-panel .pe-ef-section .app-kv {
    grid-template-columns: minmax(0, 1fr);
  }
  .pe-detail-panel .pe-ef-section .app-kv > .app-kv-k {
    border-right: none;
    border-bottom: 1px solid var(--saip-grey-200);
  }
}

/* MR-M21-09c — apply the same dense table-row treatment to ALL legacy
   `.app-kv` rows inside the EF detail panel (not only the accordion
   sections). This catches the legacy `#profile-explorer-file-detail-
   canonical` 8-field summary + the `file-detail__row` rows + the
   engineering <details> block. No template change needed for these
   surfaces; CSS only. */
.app-root .pe-detail-panel #profile-explorer-file-detail-canonical .app-kv,
.app-root .pe-detail-panel .file-detail__user .app-kv,
.app-root .pe-detail-panel .file-detail__engineering .app-kv {
  display: grid;
  grid-template-columns: minmax(140px, 38%) minmax(0, 1fr);
  column-gap: 0;
  row-gap: 0;
  padding: 0;
  border: 1px solid var(--saip-grey-200);
  border-top: none;
  font-size: 11px;
  background: var(--saip-ice-0);
}

.app-root .pe-detail-panel #profile-explorer-file-detail-canonical .app-kv:first-of-type,
.app-root .pe-detail-panel .file-detail__user .app-kv:first-of-type,
.app-root .pe-detail-panel .file-detail__engineering .app-kv:first-of-type {
  border-top: 1px solid var(--saip-grey-200);
}

.app-root .pe-detail-panel #profile-explorer-file-detail-canonical .app-kv > .app-kv-k,
.app-root .pe-detail-panel .file-detail__user .app-kv > .app-kv-k,
.app-root .pe-detail-panel .file-detail__engineering .app-kv > .app-kv-k {
  display: block;
  flex: none;
  margin: 0;
  padding: 5px 10px;
  background: var(--saip-ice-50);
  border-right: 1px solid var(--saip-grey-200);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 700;
  color: var(--saip-grey-700);
  line-height: 1.3;
  word-break: normal;
  overflow-wrap: anywhere;
  align-self: stretch;
}

.app-root .pe-detail-panel #profile-explorer-file-detail-canonical .app-kv > .app-kv-v,
.app-root .pe-detail-panel .file-detail__user .app-kv > .app-kv-v,
.app-root .pe-detail-panel .file-detail__engineering .app-kv > .app-kv-v {
  display: block;
  flex: none;
  margin: 0;
  padding: 5px 10px;
  background: var(--saip-ice-0);
  font-size: 11px;
  color: var(--saip-navy-800);
  line-height: 1.4;
  word-break: normal;
  overflow-wrap: anywhere;
  min-width: 0;
  align-self: stretch;
}

/* Drop the old "At a glance — canonical EF view" eyebrow on the legacy
   block when both the new MR-M21-09b at-a-glance card + the canonical
   block are present (we now hide the canonical block — same data, the
   new at-a-glance is the source of truth). */
.app-root .pe-detail-panel #profile-explorer-file-detail-canonical {
  display: none;
}

/* MR-M21-09c — strip the inline-bordered "Standards conformance —
   diagnostic" container chrome around the conformance table; the
   table itself carries the .pe-report-data-table styling. */
.app-root #profile-explorer-file-detail-conformance {
  padding: 0 !important;
  background: transparent !important;
  border: none !important;
}

.app-root #profile-explorer-file-detail-conformance > div:first-child {
  font-size: 12px !important;
  text-transform: none !important;
  letter-spacing: 0.02em !important;
  color: var(--saip-navy-800) !important;
  border-bottom: 1px solid var(--saip-grey-300);
  padding-bottom: 4px;
  margin-bottom: 6px !important;
}

/* ── M27 dashboard merge ── */
/* Sponsor 2026-06-12 dashboard-merge — per-section row overflow: the server
   renders ALL rows; rows beyond the first 10 are hidden until the CSP-safe
   "See more" toggle (dashboard_sections.js) adds .is-expanded on the
   section's [data-dash-rows] container. */
.app-root [data-dash-rows] .app-row-overflow {
  display: none;
}

.app-root [data-dash-rows].is-expanded .app-row-overflow {
  display: table-row;
}

/* ── Profile Element Explorer filter tiles (Sponsor 2026-06-18 Wave 2) ──
   The tiles are <button data-pe-filter-tile> rows. The RESTING and .is-active
   states are expressed PURELY in CSS here — never via inline style — so the JS
   reflectTiles() toggle (.is-active) gives an OBVIOUS visual change on click
   (defect B). Two palettes: GREEN (per-group filters) + GREY (diagnostic
   filters: All · With findings · Not fully interpreted). */
.app-root .pe-explorer-tile {
  font-size: 10px;
  line-height: 1.2;
  cursor: pointer;
  border-radius: 9px;
  padding: 3px 10px;
  border: 1px solid transparent;
  font-weight: 500;
  transition: background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.app-root .pe-explorer-tile:focus-visible {
  outline: 2px solid var(--ps-focus-ring);
  outline-offset: 1px;
}

/* GREEN — per-group filters. Resting = light fill / green text; hover deepens;
   active = solid green fill / white text. */
.app-root .pe-explorer-tile-green {
  background: var(--saip-green-50);
  color: var(--saip-green-500);
  border-color: var(--saip-green-500);
}
.app-root .pe-explorer-tile-green:hover {
  background: #c8ecd7;
}
.app-root .pe-explorer-tile-green.is-active {
  background: var(--saip-green-500);
  color: #ffffff;
  border-color: var(--saip-green-500);
}

/* GREY — diagnostic filters. Resting = light grey / grey text; hover deepens;
   active = solid navy fill / white text. */
.app-root .pe-explorer-tile-grey {
  background: var(--saip-grey-200);
  color: var(--saip-grey-700);
  border-color: var(--saip-grey-300);
}
.app-root .pe-explorer-tile-grey:hover {
  background: var(--saip-grey-300);
}
.app-root .pe-explorer-tile-grey.is-active {
  background: var(--saip-navy-800);
  color: #ffffff;
  border-color: var(--saip-navy-800);
}

/* The horizontal tile STRIP (defect A): full-width, directly under the
   sub-banner title and ABOVE the 3-column grid. Grey row on top, green below. */
.app-root [data-pe-explorer-tilestrip] {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: var(--saip-spacing-3);
}
.app-root [data-pe-explorer-tilestrip] [data-pe-explorer-tiles-grey],
.app-root [data-pe-explorer-tilestrip] [data-pe-explorer-tiles-green] {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
}
.app-root [data-pe-explorer-tilestrip] .pe-explorer-tilestrip-label {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--saip-grey-500);
  margin-right: 2px;
}

/* ===================================================================== *
 * M34 Wave 1A — Active-Profile context spine (value-free cohesion bar)   *
 * SUITE-ACTIVE-PROFILE-SPINE-UX-01                                       *
 * ===================================================================== */
.app-root .app-active-profile {
  /* DA-A1-NAV-FINISH-01 — re-skinned as a context ribbon (a card about one
     object), not a nav surface: white surface + a teal left spine + a bottom
     hairline. */
  background: var(--saip-white);
  border-left: 3px solid var(--saip-teal-600);
  border-bottom: 1px solid var(--saip-grey-200);
}
.app-root .app-active-profile[hidden] { display: none; }
.app-root .app-active-profile-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--saip-spacing-3);
  padding: 8px 0;
  flex-wrap: wrap;
}
.app-root .app-active-profile-id {
  display: flex;
  align-items: center;
  gap: var(--saip-spacing-2);
  min-width: 0;
  flex-wrap: wrap;
}
.app-root .app-active-profile-eyebrow {
  font-size: var(--saip-text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--saip-grey-600);
  font-weight: 600;
}
.app-root .app-active-profile-file {
  font-size: var(--saip-text-base);
  font-weight: 700;
  color: var(--saip-navy-900);
  max-width: 38ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-root .app-active-profile-count {
  font-size: var(--saip-text-xs);
  color: var(--saip-grey-600);
}
/* SUITE-CLAUSE-PROACTIVE-AMBIENT-01 — ambient "Clause · N standards
   implications" indicator. Shown only when N>0; reads as a compact, quiet pill
   that links to the on-screen consequences/implications section. */
.app-root .app-active-profile-clause {
  font-size: var(--saip-text-xs);
  font-weight: 600;
  color: var(--saip-navy-700);
  text-decoration: none;
  padding: 1px 8px;
  border: 1px solid var(--saip-navy-200);
  border-radius: 999px;
  white-space: nowrap;
}
.app-root .app-active-profile-clause:hover,
.app-root .app-active-profile-clause:focus-visible {
  background: var(--saip-navy-50);
  border-color: var(--saip-navy-700);
}
.app-root .app-active-profile-actions {
  display: flex;
  align-items: center;
  gap: var(--saip-spacing-3);
  flex-wrap: wrap;
}
/* DA-A1-NAV-FINISH-01 — actions read as quiet chips (the auth-link chip idiom),
   not nav links. ≥24px min height for the touch/click target. */
.app-root .app-ap-action {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  font-size: var(--saip-text-xs);
  font-weight: 600;
  color: var(--saip-navy-700);
  text-decoration: none;
  padding: 3px 10px;
  border: 1px solid var(--saip-grey-300);
  border-radius: var(--saip-radius-sm);
  background: var(--saip-white);
  white-space: nowrap;
}
.app-root .app-ap-action:hover,
.app-root .app-ap-action:focus-visible {
  border-color: var(--saip-teal-600);
  background: var(--saip-teal-50);
}
/* DA-A1-NAV-FINISH-01 — "Open analysis" is the one primary action on the ribbon
   (the only "go to the Cockpit" verb); fill it so it out-ranks the secondary
   handoffs. White-on-teal-600 clears AA; the hover deepens to navy for contrast. */
.app-root .app-ap-action-primary {
  color: var(--saip-white);
  background: var(--saip-teal-600);
  border-color: var(--saip-teal-600);
}
.app-root .app-ap-action-primary:hover,
.app-root .app-ap-action-primary:focus-visible {
  color: var(--saip-white);
  background: var(--saip-navy-700);
  border-color: var(--saip-navy-700);
}
.app-root .app-ap-dismiss {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--saip-grey-500);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  min-width: 24px;
  min-height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 4px;
}
.app-root .app-ap-dismiss:hover,
.app-root .app-ap-dismiss:focus-visible { color: var(--saip-navy-700); }

/* ===================================================================== *
 * M34 Wave 1A — Dashboard workspace hero + 5-pillar launchpad            *
 * ===================================================================== */
.app-root .app-dash-hero {
  background: var(--ps-bg-surface-muted);
  border: 1px solid var(--ps-border-hairline);
  border-radius: var(--saip-radius-lg);
  padding: var(--saip-spacing-5);
}
.app-root .app-dash-hero-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--saip-spacing-4);
  flex-wrap: wrap;
}
.app-root .app-dash-hero-sub {
  color: var(--ps-text-secondary);
  font-size: var(--saip-text-sm);
  margin: .35rem 0 0;
}
.app-root .app-dash-continue {
  display: flex;
  flex-direction: column;
  gap: 3px;
  text-decoration: none;
  background: var(--ps-bg-surface);
  border: 1px solid var(--ps-border-hairline);
  border-radius: var(--saip-radius-sm);
  padding: 10px 14px;
  min-width: 220px;
}
.app-root .app-dash-continue:hover { border-color: var(--ps-accent); }
.app-root .app-dash-continue-eyebrow {
  font-size: var(--saip-text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ps-text-secondary);
  font-weight: 600;
}
.app-root .app-dash-continue-file {
  font-size: var(--saip-text-sm);
  font-weight: 600;
  color: var(--ps-text-heading);
  max-width: 34ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-root .app-dash-continue-health { display: flex; align-items: center; gap: 8px; }
.app-root .app-dash-continue-count { font-size: var(--saip-text-xs); color: var(--ps-text-secondary); }
.app-root .app-dash-launchpad {
  display: grid;
  /* DA-A1-NAV-FINISH-01 — 5 pillars in nav order (Studio first); responsive
     5-up that wraps to 2-up below tablet width. List markup → reset the
     default list styling. */
  grid-template-columns: repeat(5, 1fr);
  gap: var(--saip-spacing-3);
  margin-top: var(--saip-spacing-4);
  list-style: none;
  padding: 0;
}
.app-root .app-dash-launchpad > li { margin: 0; }
.app-root .app-dash-launchpad > li > .app-dash-pillar { height: 100%; }
@media (max-width: 760px) {
  .app-root .app-dash-launchpad { grid-template-columns: repeat(2, 1fr); }
}
.app-root .app-dash-pillar {
  display: flex;
  flex-direction: column;
  gap: 2px;
  text-decoration: none;
  background: var(--ps-bg-surface);
  border: 1px solid var(--ps-border-hairline);
  border-radius: var(--saip-radius-sm);
  padding: 12px 14px;
}
.app-root .app-dash-pillar:hover,
.app-root .app-dash-pillar:focus-visible {
  border-color: var(--ps-accent);
  box-shadow: var(--ps-shadow-card);
}
.app-root .app-dash-pillar-name {
  font-size: var(--saip-text-sm);
  font-weight: 700;
  color: var(--ps-text-heading);
}
.app-root .app-dash-pillar-desc {
  font-size: var(--saip-text-xs);
  color: var(--ps-text-secondary);
}

/* M34 1A — finding -> KB tolerant-search handoff link (evidence trace). */
.app-root .app-kb-find {
  font-size: var(--saip-text-xs);
  font-weight: 600;
  color: var(--ps-link);
  text-decoration: none;
  margin-left: 6px;
  white-space: nowrap;
}
.app-root .app-kb-find:hover,
.app-root .app-kb-find:focus-visible { text-decoration: underline; }

/* ===================================================================== *
 * M34 Wave 1D — Consequence engine section (ranked + bucketed)           *
 * ===================================================================== */
.app-root .m34-consequences { }
.app-root .m34-conseq-frame {
  font-size: var(--saip-text-sm);
  color: var(--saip-slate-600);
  margin: .25rem 0 .6rem;
}
.app-root .m34-conseq-counts {
  display: flex;
  gap: var(--saip-spacing-3);
  flex-wrap: wrap;
  margin: 0 0 var(--saip-spacing-4);
}
.app-root .m34-conseq-count {
  font-size: var(--saip-text-xs);
  font-weight: 700;
  padding: 2px 10px;
  border-radius: 999px;
}
.app-root .m34-conseq-count.is-blocking { background: var(--saip-red-100); color: var(--saip-red-700); }
.app-root .m34-conseq-count.is-review   { background: var(--saip-amber-100); color: var(--saip-amber-600); }
.app-root .m34-conseq-count.is-info     { background: var(--saip-ice-100); color: var(--saip-navy-700); }
.app-root .m34-conseq-bucket { margin-bottom: var(--saip-spacing-4); }
.app-root .m34-conseq-buckethead {
  font-size: var(--saip-text-sm);
  margin: 0 0 var(--saip-spacing-2);
  color: var(--saip-grey-600);
}
.app-root .m34-conseq-item {
  border: 1px solid var(--saip-grey-200);
  border-left-width: 3px;
  border-radius: 6px;
  padding: var(--saip-spacing-2) var(--saip-spacing-3);
  margin-bottom: 6px;
}
.app-root .m34-conseq-item.is-blocking { border-left-color: var(--saip-red-700); }
.app-root .m34-conseq-item.is-review   { border-left-color: #d97706; }
.app-root .m34-conseq-item.is-info     { border-left-color: var(--saip-navy-700); }
.app-root .m34-conseq-summary {
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--saip-spacing-2);
  flex-wrap: wrap;
}
.app-root .m34-conseq-sev {
  font-size: var(--saip-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 1px 7px;
  border-radius: 4px;
}
.app-root .m34-conseq-sev.is-blocking { background: var(--saip-red-100); color: var(--saip-red-700); }
.app-root .m34-conseq-sev.is-review   { background: var(--saip-amber-100); color: var(--saip-amber-600); }
.app-root .m34-conseq-sev.is-info     { background: var(--saip-ice-100); color: var(--saip-navy-700); }
.app-root .m34-conseq-title { font-weight: 600; font-size: var(--saip-text-sm); color: var(--saip-navy-700); }
.app-root .m34-conseq-subsystem { font-size: var(--saip-text-xs); color: var(--saip-grey-500); margin-left: auto; }
.app-root .m34-conseq-body { margin-top: var(--saip-spacing-2); display: flex; flex-direction: column; gap: 4px; }
.app-root .m34-conseq-statement { font-size: var(--saip-text-sm); line-height: 1.55; margin: 0; }
.app-root .m34-conseq-fix { font-size: var(--saip-text-sm); color: var(--saip-slate-600); margin: 0; }
.app-root .m34-conseq-refs { font-size: var(--saip-text-xs); color: var(--saip-grey-600); margin: 0; }

/* M34 Wave 1C — requirement conformance result (reason-coded chips + rows). */
.app-root .m34-conf-chip {
  font-size: var(--saip-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 1px 8px;
  border-radius: 999px;
  white-space: nowrap;
}
.app-root .m34-conf-chip.is-met   { background: var(--ps-sev-pass-bg); color: var(--saip-green-700); }
.app-root .m34-conf-chip.is-unmet { background: var(--saip-red-100); color: var(--saip-red-700); }
.app-root .m34-conf-row.is-unmet td { background: rgba(155, 28, 28, 0.03); }
.app-root .m34-conf-table th {
  font-size: var(--saip-text-xs);
  color: var(--saip-grey-600);
  border-bottom: 1px solid var(--saip-grey-200);
  padding: 6px 8px;
}
.app-root .m34-conf-table td {
  padding: 6px 8px;
  border-bottom: 1px solid var(--saip-grey-200);
  vertical-align: top;
}

/* M34 2A — Save-as-reference inline button in the Active-Profile bar. */
.app-root .app-ap-form { display: inline; margin: 0; }
/* DA-A1-NAV-FINISH-01 — the save-reference submit button must read as a chip
   like its sibling actions: reset only the button-native chrome and inherit the
   .app-ap-action chip border/background/padding (do NOT zero them). */
.app-root button.app-ap-action-btn {
  appearance: none;
  cursor: pointer;
  font: inherit;
}

/* ===================================================================== *
 * M34 Wave 2D — Fleet Query (aggregate chips + fact filters)             *
 * ===================================================================== */
.app-root .m34-fleet-agg { display: flex; flex-wrap: wrap; gap: var(--saip-spacing-2); }
.app-root .m34-fleet-chip {
  font-size: var(--saip-text-xs);
  font-weight: 600;
  color: var(--saip-navy-700);
  text-decoration: none;
  background: var(--saip-ice-50);
  border: 1px solid var(--saip-grey-200);
  border-radius: 999px;
  padding: 3px 12px;
}
.app-root .m34-fleet-chip:hover { border-color: var(--saip-navy-700); }
.app-root .m34-fleet-chip.is-active { background: var(--saip-navy-700); color: var(--saip-ice-0); border-color: var(--saip-navy-700); }
.app-root .m34-fleet-label {
  font-size: var(--saip-text-xs);
  color: var(--saip-navy-700);
  text-decoration: none;
  margin-right: 8px;
  border-bottom: 1px solid transparent;
}
.app-root .m34-fleet-label.is-active { border-bottom-color: var(--saip-navy-700); font-weight: 700; }
.app-root .m34-fleet-yes { color: var(--saip-green-700); font-weight: 700; }
.app-root .m34-fleet-no { color: var(--saip-grey-400); }

/* M34 1B / audit C5 — persistent STRUCTURAL mode pill on the Delta result. */
.app-root .m34-structural-pill {
  display: inline-block;
  vertical-align: middle;
  margin-left: 10px;
  font-size: var(--saip-text-2xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--saip-navy-700);
  background: var(--saip-ice-100);
  border: 1px solid var(--saip-grey-200);
  border-radius: 4px;
  padding: 2px 8px;
}

/* ===================================================================== *
 * M34 Wave 2E — Value-true compare (verdict-only) pill + chips           *
 * ===================================================================== */
.app-root .m34-valuetrue-pill {
  display: inline-block;
  vertical-align: middle;
  margin-left: 8px;
  font-size: var(--saip-text-2xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  /* FT-DC-PILL-CONTRAST-AA-01: the former deep-green keep (≈6.86:1) folds
     onto the darkened pass token (≈6.26:1) — RGB Δ≈14.6, imperceptible;
     both clear AA with margin. */
  color: var(--ps-sev-pass-fg);
  background: var(--ps-sev-pass-bg);
  border: 1px solid var(--ps-sev-pass-bd);
  border-radius: 4px;
  padding: 2px 8px;
}
.app-root .m34-vt-family { margin-bottom: var(--saip-spacing-3); }
.app-root .m34-vt-famhead {
  font-size: var(--saip-text-sm);
  color: var(--saip-grey-600);
  margin: 0 0 4px;
}
.app-root .m34-vt-table td {
  padding: 5px 8px;
  border-bottom: 1px solid var(--saip-grey-200);
}
.app-root .m34-vt-chip {
  font-size: var(--saip-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 1px 9px;
  border-radius: 999px;
  white-space: nowrap;
}
.app-root .m34-vt-chip.is-identical { background: var(--ps-sev-pass-bg); color: var(--saip-green-700); }
.app-root .m34-vt-chip.is-differs { background: var(--saip-red-100); color: var(--saip-red-700); }
.app-root .m34-vt-chip.is-only { background: var(--saip-amber-100); color: var(--saip-amber-600); }
.app-root .m34-vt-chip.is-indeterminate { background: var(--saip-ice-100); color: var(--saip-navy-700); }
.app-root .m34-vt-row.is-differs td { background: rgba(155, 28, 28, 0.03); }

/* ===================================================================== *
 * FT-WAVES-2-5 batch B3 — inline-style token utilities                   *
 *                                                                        *
 * The recurring raw-hex inline-style idioms across the admin / auth /    *
 * onboarding templates (the dark-mode blockers, brief 02 T5) fold onto   *
 * these small token-backed utilities. Guard:                             *
 * tests/web/test_semantic_token_adoption.py                              *
 * ::test_template_inline_styles_carry_no_raw_hex_colours.                *
 * Mapping rule: --ps-* semantic first, --saip-* primitive fallback,      *
 * identical or ≤1 ramp step from the retired literal.                    *
 * ===================================================================== */

/* Body prose — was the raw dark-grey `font-size:base` + `line-height:1.6` idiom (×12). */
.app-root .app-prose {
  font-size: var(--saip-text-base);
  color: var(--ps-text-primary);
  line-height: 1.6;
}
/* Plain body text — was the raw dark-grey `font-size:base` idiom (+variants). */
.app-root .app-text-body {
  font-size: var(--saip-text-base);
  color: var(--ps-text-primary);
}
/* Secondary body text — was the raw mid-grey `font-size:base` idiom (+variants). */
.app-root .app-text-quiet {
  font-size: var(--saip-text-base);
  color: var(--ps-text-secondary);
}
/* Small helper/hint text — was the raw mid-grey `font-size:xs` idiom (+variants). */
.app-root .app-hint {
  font-size: var(--saip-text-xs);
  color: var(--ps-text-secondary);
}
/* Uppercase field eyebrow label — was the raw section-navy idiom (×10). */
.app-root .app-label-eyebrow {
  display: block;
  font-size: var(--saip-text-sm);
  color: var(--saip-navy-700);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
/* Full-width form input — was the raw light-grey-border idiom (×10). */
.app-root .app-input-plain {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--ps-border-strong);
  border-radius: 6px;
  font-size: var(--saip-text-md);
  margin-top: 4px;
}
/* Compact filter/toolbar input — same border idiom, dense variant (×16). */
.app-root .app-input-inline {
  padding: 6px 8px;
  border: 1px solid var(--ps-border-strong);
  border-radius: 6px;
  font-size: var(--saip-text-sm);
}
/* Left-accent note — was the ad-hoc `background+border-left` callouts. */
.app-root .app-note {
  border-left: 4px solid var(--ps-border-strong);
  padding: 10px 14px;
}
.app-root .app-note-warn    { background: var(--saip-amber-100); border-left-color: var(--saip-amber-500); }
.app-root .app-note-info    { background: var(--saip-blue-100);  border-left-color: var(--saip-blue-700); }
.app-root .app-note-success { background: var(--saip-green-100); border-left-color: var(--saip-green-600); }
.app-root .app-note-danger  { background: var(--saip-red-100);   border-left-color: var(--ps-danger-bg); }
.app-root .app-note-neutral { background: var(--saip-grey-100);  border-left-color: var(--saip-grey-400); }
/* Simple ruled table cells — was the raw strong/hairline border-bottom idiom. */
.app-root .app-th-rule { padding: 8px; border-bottom: 1px solid var(--ps-border-strong); }
.app-root .app-td-rule { padding: 8px; border-bottom: 1px solid var(--ps-border-hairline); }
