:root {
    /* `only light` (not plain `light`) is what actually opts the page out
       of Android Chrome's auto-dark ("Force dark") engine — plain `light`
       stopped being honoured, which is why the app was being force-darkened
       into the muddy mixed rendering on Android. The designed dark theme
       lives under html[data-theme="dark"] below. */
    color-scheme: only light;
    /* JAGS aviation palette over the Achromatic Precision layout — navy
       primary, slate secondary, cool blue-tinted surfaces. Layout structure
       (radii, tracking, shadows, spacing) stays from the design system. */
    --bg: #F7F9FC;
    --card: #FFFFFF;
    /* Alias used by several pages as var(--card-bg, #fff). It was never
       defined, so the #fff fallback ALWAYS fired — defining it here makes
       those pages theme-correct in one place. */
    --card-bg: var(--card);
    /* RGB triplet for frosted-glass chrome (topbar, bottom nav, sheets,
       sticky action bars) — used as rgba(var(--glass-rgb), <alpha>) so each
       surface keeps its tuned alpha while the tint follows the theme. */
    --glass-rgb: 255, 255, 255;
    --surface: #FFFFFF;
    --surface-low: #F7F9FC;
    --surface-high: #FFFFFF;
    --surface-container: #EEF1F7;
    --surface-container-high: #E6EAF3;
    --surface-container-highest: #DDE3EE;
    --inverse-surface: #1B1F2E;
    --inverse-on-surface: #F2F4FA;
    /* Primary ink is a deep brand navy (not near-black): headings, body and
       table text all read as part of the JAGS identity. 14.9:1 on --card. */
    --text: #10173B;
    --text-strong: #0A102C;
    --muted: #5E6472;
    --muted-strong: #4B5061;
    --primary: #171756;
    --primary-hover: #0B0B2F;
    --secondary: #274270;
    --secondary-hover: #1B345B;
    --link: #274270;
    --border: #E2E6EE;
    --border-strong: #C7D1E2;
    --outline: #7E7576;
    --success: #4A6733;
    --info: #5A79A5;
    --danger: #B83235;
    --warning: #B6883A;
    /* Airy ambient shadows kept from the design system — long blur, low
       opacity, navy-tinted so the lift reads as part of the brand. */
    --shadow-xs: 0 1px 1px rgba(14, 14, 18, 0.025);
    --shadow-sm: 0 1px 2px rgba(14, 14, 18, 0.035);
    --shadow-md: 0 8px 24px rgba(14, 14, 18, 0.05);
    --shadow-lg: 0 30px 60px rgba(11, 11, 47, 0.08), 0 2px 4px rgba(14, 14, 18, 0.03);
    --ring-focus: 0 0 0 3px rgba(90, 121, 165, 0.22);
    --radius: 12px;
    --radius-sm: 8px;
    --radius-lg: 16px;
    --grad-jags: linear-gradient(135deg, #171756 0%, #274270 60%, #5A79A5 100%);
    --grad-soft: linear-gradient(180deg, #F7F9FC 0%, #FFFFFF 100%);

    /* ------------------------------------------------------------------
       Aliases — names that read closer to brand language. Each maps to
       an existing token so adopting the alias does not change a colour.
       Use these in NEW code so future palette tweaks happen in one place.
       ------------------------------------------------------------------ */
    --jags-blue:        #171756;  /* same as --primary */
    --jags-blue-deep:   #0B0B2F;  /* same as --primary-hover */
    --jags-blue-soft:   #5A79A5;  /* same as --info */
    --jags-navy:        #274270;  /* same as --secondary */
    --jags-surface:     #FFFFFF;
    --jags-surface-low: #F7F9FC;
    --jags-success:     #4A6733;  /* same as --success */
    --jags-warning:     #B6883A;  /* same as --warning */
    --jags-danger:      #B83235;  /* same as --danger */

    /* ------------------------------------------------------------------
       Dark sidebar — premium executive shell (2026-05-22 MVP UI pass).
       The authenticated app sits on a white/soft canvas with a deep navy
       rail, matching the reference's "elegant dark sidebar" while staying
       on the JAGS navy/indigo brand. Single source of truth so the desktop
       rail and the mobile slide-in drawer never drift. The brand logo keeps
       a LIGHT lockup panel (--sidebar-brand-bg): the logo asset is locked
       and must not be recoloured, so it reads cleanly on its own white card.
       --sidebar-accent is a lighter periwinkle tint of --jags-blue-soft
       (#5A79A5) so the active marker reads as an accent against the navy.
       Display/TV boards (layout_display_open) and auth pages
       (layout_blank_open) never use the app shell, so these never reach
       them. Tune the whole rail from here. ------------------------------ */
    --sidebar-bg:        #0E1230;  /* deep brand navy-indigo (rail base) */
    --sidebar-bg-2:      #161C40;  /* lifted top of the rail gradient */
    --sidebar-text:      #EAEDF7;  /* primary nav label */
    --sidebar-muted:     #98A1C6;  /* section labels, idle icons, account sub */
    --sidebar-border:    rgba(255, 255, 255, 0.08);
    --sidebar-hover-bg:  rgba(255, 255, 255, 0.06);
    --sidebar-active-bg: rgba(255, 255, 255, 0.11);
    --sidebar-accent:    #8AA3D6;  /* active rail/marker — light tint of blue-soft */
    --sidebar-brand-bg:  #FFFFFF;  /* light lockup panel for the locked logo */
    --grad-sidebar:      linear-gradient(180deg, #161C40 0%, #0E1230 62%, #0B0E26 100%);

    /* ------------------------------------------------------------------
       Typography — Inter when available, system stack everywhere else.
       Sizes follow a relaxed 1.18 scale tuned for dense aviation tables
       without compressing report headings. Mono is used for hours / regs.
       ------------------------------------------------------------------ */
    --font-sans:    Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Segoe UI", sans-serif;
    --font-display: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", sans-serif;
    --font-mono:    ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

    --text-xs:   12px;
    --text-sm:   13px;
    --text-base: 14px;
    --text-lg:   16px;
    --text-xl:   20px;
    --text-2xl:  24px;
    --text-3xl:  32px;

    /* Tracking: tighter on display/headings, slight negative on body for the
       "locked-in" editorial feel. Uppercase labels keep wider spacing. */
    --tracking-tight:  -0.02em;
    --tracking-normal: -0.006em;
    --tracking-wide:   0.05em;

    --line-tight:   1.2;
    --line-normal:  1.5;
    --line-relaxed: 1.65;

    /* Motion system — tokens used across buttons, cards, tables, nav, modal.
       Apple-style decelerated easings. Calm, not flashy. */
    --motion-fast: 140ms;
    --motion-med:  220ms;
    --motion-slow: 380ms;
    --ease-premium: cubic-bezier(0.2, 0.8, 0.2, 1);
    --ease-soft:    cubic-bezier(0.22, 0.61, 0.36, 1);
    --ease-out:     cubic-bezier(0.4, 0, 0.2, 1);

    /* ------------------------------------------------------------------
       Mobile fixed bottom-nav geometry — single source of truth.
       .mobile-bottom-nav is position:fixed at the viewport bottom on
       phones (<=900px). Every surface that must sit clear of it — page
       content, sticky action bars, toasts, the docked walkthrough card —
       derives its offset from these tokens instead of repeating magic
       numbers, so the bar's reserved space is tuned in ONE place.

       --safe-area-bottom carries an explicit 0px fallback. Without it, a
       calc()/max() that references env(safe-area-inset-bottom) becomes
       INVALID on in-app browsers / older WebViews that don't implement
       safe-area insets (WhatsApp Business, some Chrome Custom Tabs, older
       Android System WebView). An invalid clearance declaration is
       dropped, the reserved space collapses to the base .content padding,
       and the fixed bar then overlaps the last cards / footer / buttons —
       exactly the reported overlap. The fallback keeps the calc() valid
       everywhere so the clearance always applies.

       --mobile-bottom-nav-height is the bar's intrinsic height with no
       inset (icon + label + paddings + hairline ≈ 61px, rounded up to
       64px for a small cushion). Footprint = height + device safe area
       (the space the bar actually occupies); clearance = footprint +
       comfortable breathing room so the final content never meets the
       bar. Sticky action bars sit on the footprint; page content reserves
       the full clearance. Desktop (>900px) never consumes these. */
    --mobile-bottom-nav-height: 64px;
    --safe-area-bottom: env(safe-area-inset-bottom, 0px);
    --mobile-bottom-nav-footprint: calc(var(--mobile-bottom-nav-height) + var(--safe-area-bottom));
    --mobile-bottom-nav-clearance: calc(var(--mobile-bottom-nav-footprint) + 22px);

    /* ------------------------------------------------------------------
       SEMANTIC TOKENS (2026-08 application design system).
       One vocabulary for every shared component: surfaces, ink tiers,
       separators, accent, status pairs (strong + soft tint), depth, radii
       and an 8-point spacing scale. Each maps onto the palette above so
       the theme is tuned in one place; the dark block re-derives the same
       names. New/updated components should reach for THESE first.
       ------------------------------------------------------------------ */
    --surface-page:      var(--bg);
    --surface-primary:   var(--card);
    --surface-secondary: var(--surface-container);
    --surface-elevated:  var(--surface-high);
    --surface-selected:  rgba(39, 66, 112, 0.08);
    --text-primary:      var(--text);
    --text-secondary:    var(--muted);
    --text-tertiary:     #8A91A6;
    --text-inverse:      #FFFFFF;
    --separator:         var(--border);
    --border-subtle:     rgba(23, 23, 86, 0.08);
    --focus-ring:        var(--ring-focus);
    --accent:            var(--secondary);
    --accent-hover:      var(--secondary-hover);
    --accent-soft:       rgba(90, 121, 165, 0.14);
    --status-success:      var(--success);
    --status-success-soft: rgba(74, 103, 51, 0.12);
    --status-warning:      var(--warning);
    --status-warning-soft: rgba(182, 136, 58, 0.16);
    --status-danger:       var(--danger);
    --status-danger-soft:  rgba(184, 50, 53, 0.10);
    --status-info:         var(--info);
    --status-info-soft:    rgba(90, 121, 165, 0.14);
    /* Ink for text sitting ON a soft status surface (--status-*-soft, or a
       raw rgba tint of the same hue). The soft background re-tints itself
       per theme; the ink never could, which is why status chips, alerts and
       the reservation vocabulary all read as dark-on-dark in dark mode.
       These values ARE the literals that were previously hardcoded, so light
       mode is unchanged; the dark block below supplies the counterparts. */
    --status-success-ink: #3B5326;
    --status-warning-ink: #7C5A1F;
    --status-danger-ink:  #8E2226;
    --status-info-ink:    #244A78;
    --status-neutral-ink: var(--muted-strong);
    --shadow-card:     0 1px 2px rgba(11, 11, 47, 0.04), 0 10px 30px rgba(11, 11, 47, 0.06);
    --shadow-elevated: var(--shadow-md);
    --radius-control: 12px;
    --radius-card:    16px;
    --radius-panel:   20px;
    --radius-round:   999px;
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 20px;
    --space-6: 24px;
    --space-8: 32px;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* Light is the default scheme; `only light` hard-opts-out of browser
   force-darkening (see :root note). The designed dark theme is activated by
   stamping data-theme="dark" on <html> — server-side from the jags_theme
   cookie, or by the head bootstrap when the preference is System and the
   device is dark. Display boards (TV wallboards) keep their own separate
   dark scheme via layout_display_open() and never load this stylesheet. */
html { color-scheme: only light; background: var(--bg); }
body {
    font-family: var(--font-sans);
    background: var(--bg);
    color: var(--text);
    font-size: var(--text-base);
    line-height: var(--line-normal);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    font-feature-settings: "ss01", "cv11"; /* Inter stylistic alternates when present */
}
/* ======================================================================
   DESIGNED DARK THEME — activated by html[data-theme="dark"].
   Aviation navy/charcoal, layered surfaces, not pure black. All text/token
   pairings meet WCAG AA on their surfaces (ratios noted). The navy hero
   gradient keeps the exact JAGS identity; interactive --primary shifts to
   a periwinkle-indigo of the same family for dark-surface contrast.
   Never applied to display boards (separate shell) or print (guard below).
   ====================================================================== */
html[data-theme="dark"] {
    color-scheme: dark; /* native dark form controls, pickers, keyboard */

    /* Surfaces — layered, calm */
    --bg:                        #0E1220;
    --card:                      #171C2B;
    --surface:                   #171C2B;
    --surface-low:               #10141F;
    --surface-high:              #1B2133;
    --surface-container:         #1E2438;
    --surface-container-high:    #232A40;
    --surface-container-highest: #29314A;
    --inverse-surface:           #E6E9F2;
    --inverse-on-surface:        #171C2B;

    /* Text — 13.9:1 on card / 15.3:1 on bg; muted 7.3:1 on card */
    --text:         #E6E9F2;
    --text-strong:  #F5F7FB;
    --muted:        #A2AAC0;
    --muted-strong: #BAC1D4;

    /* Brand / interactive — JAGS navy family, dark-adjusted (8.0:1 on card) */
    --primary:        #9DB0F0;
    --primary-hover:  #B4C3F5;
    --secondary:      #93A6DE;
    --secondary-hover:#A9B8E8;
    --link:           #9DB0F0;

    /* Borders */
    --border:        #2C3346;
    --border-strong: #3C4560;

    /* Status — all >= 4.5:1 as text on --card */
    --success: #7FB069;
    --info:    #7CA5D8;
    --danger:  #E0797B;
    --warning: #E0B25C;

    /* Elevation — darker shadows; surface layering does the separating */
    --shadow-xs: 0 1px 1px rgba(0,0,0,0.30);
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.40);
    --shadow-md: 0 8px 24px rgba(0,0,0,0.45);
    --shadow-lg: 0 24px 60px rgba(0,0,0,0.55), 0 2px 4px rgba(0,0,0,0.40);
    --ring-focus: 0 0 0 3px rgba(157,176,240,0.45);

    /* Hero keeps the JAGS navy identity; soft gradient goes dark */
    --grad-jags: linear-gradient(135deg, #171756 0%, #274270 55%, #3D5A8A 100%);
    --grad-soft: linear-gradient(180deg, #10141F 0%, #171C2B 100%);

    /* Brand-language aliases — same dark-adjusted family as --primary etc.
       These are used as TEXT/accent colours; the one brand FILL that must
       stay navy (bottom-nav Guide button) is pinned separately below. */
    --jags-blue:        #9DB0F0;
    --jags-blue-deep:   #B4C3F5;
    --jags-blue-soft:   #7CA5D8;
    --jags-navy:        #93A6DE;
    --jags-surface:     #171C2B;
    --jags-surface-low: #10141F;
    --jags-success:     #7FB069;
    --jags-warning:     #E0B25C;
    --jags-danger:      #E0797B;

    /* The sidebar rail is already deep navy in light mode — unchanged.
       Its brand lockup chip softens from pure white to a soft-white so the
       locked dark-navy logo artwork stays crisp without a glaring slab. */
    --sidebar-brand-bg: #F4F6FC;

    /* Frosted chrome tint (see :root note) */
    --glass-rgb: 23, 28, 43;

    /* Semantic tokens — dark derivations of the same vocabulary. Tokens
       that alias other tokens (--surface-page, --text-primary, --accent…)
       follow automatically; only the literal values need restating. */
    --surface-selected:  rgba(157, 176, 240, 0.12);
    --text-tertiary:     #7C86A0;
    --text-inverse:      #0B0E1A;
    --border-subtle:     rgba(255, 255, 255, 0.07);
    --accent-soft:       rgba(147, 166, 222, 0.16);
    --status-success-soft: rgba(127, 176, 105, 0.16);
    --status-warning-soft: rgba(224, 178, 92, 0.18);
    --status-danger-soft:  rgba(224, 121, 123, 0.16);
    --status-info-soft:    rgba(124, 165, 216, 0.16);
    /* Dark counterparts. Same values the .badge-* dark overrides already use,
       so a chip and a badge of the same status are the same colour. */
    --status-success-ink: #A9D392;
    --status-warning-ink: #E6C078;
    --status-danger-ink:  #EDA0A2;
    --status-info-ink:    #A6C4E6;
    --status-neutral-ink: var(--muted-strong);
    --shadow-card:     0 1px 2px rgba(0, 0, 0, 0.35), 0 10px 30px rgba(0, 0, 0, 0.40);
}

/* --- Dark component rules tokens alone can't express ------------------- */

/* Primary/danger buttons: dark theme is tonal — light fill + dark ink
   (white-on-periwinkle would fail contrast). 9.1:1 both states. */
html[data-theme="dark"] .btn-primary,
html[data-theme="dark"] .btn-primary:hover { color: #0B0E1A; }
html[data-theme="dark"] .btn-danger { color: #1A0B0B; }
html[data-theme="dark"] .btn-danger:hover { background: #E89294; color: #1A0B0B; }
html[data-theme="dark"] .btn-ghost:hover { background: rgba(157,176,240,0.10); }

/* Badge soft-tints: light theme uses dark ink on pale tints — flip to
   light ink on dark tints. */
html[data-theme="dark"] .badge-success { background: rgba(127,176,105,0.18); color: #A9D392; }
html[data-theme="dark"] .badge-warn    { background: rgba(224,178,92,0.20);  color: #E6C078; }
html[data-theme="dark"] .badge-danger  { background: rgba(224,121,123,0.18); color: #EDA0A2; }
html[data-theme="dark"] .badge-info    { background: rgba(124,165,216,0.18); color: #A6C4E6; }
html[data-theme="dark"] .badge-neutral { background: rgba(162,170,192,0.16); color: var(--muted); }
html[data-theme="dark"] .countdown-chip.success { background: rgba(127,176,105,0.16); color: #A9D392; }
html[data-theme="dark"] .countdown-chip.info    { background: rgba(124,165,216,0.16); color: #A6C4E6; }
html[data-theme="dark"] .countdown-chip.warn    { background: rgba(224,178,92,0.18);  color: #E6C078; }
html[data-theme="dark"] .countdown-chip.danger  { background: rgba(224,121,123,0.16); color: #EDA0A2; }
html[data-theme="dark"] .feature-value.warn .feat-val    { color: #E6C078; }
html[data-theme="dark"] .feature-value.danger .feat-val  { color: #EDA0A2; }
html[data-theme="dark"] .feature-value.success .feat-val { color: #A9D392; }

/* Toast variants: gradients ended in #fff — end them in the card surface. */
html[data-theme="dark"] .jags-toast.success { background: linear-gradient(180deg, rgba(127,176,105,0.08), var(--card)); }
html[data-theme="dark"] .jags-toast.warn    { background: linear-gradient(180deg, rgba(224,178,92,0.10),  var(--card)); }
html[data-theme="dark"] .jags-toast.danger  { background: linear-gradient(180deg, rgba(224,121,123,0.08), var(--card)); }
html[data-theme="dark"] .jags-toast.info    { background: linear-gradient(180deg, rgba(124,165,216,0.09), var(--card)); }
html[data-theme="dark"] .jags-toast.warn .toast-icon   { color: var(--warning); }
html[data-theme="dark"] .jags-toast.danger .toast-icon { color: var(--danger); }

/* Tables: headers/zebra/hover were hard-coded near-whites. */
html[data-theme="dark"] table.tbl th { background: linear-gradient(180deg, #1E2438 0%, #171C2B 100%); }
html[data-theme="dark"] table.tbl tr:hover td { background: var(--surface-high); }
html[data-theme="dark"] table.tbl-sticky-first tbody tr:hover td:first-child,
html[data-theme="dark"] table.tbl-sticky-first tbody tr:nth-child(even) td:first-child { background: var(--surface-container); }
html[data-theme="dark"] table.dr th { background: linear-gradient(180deg, #232A40 0%, #1E2438 100%); color: var(--muted-strong); }
html[data-theme="dark"] table.dr tbody td.reg-cell { background: var(--surface-low); }
html[data-theme="dark"] .cell-list li { background: rgba(255,255,255,0.04); }
html[data-theme="dark"] .legend { background: var(--surface-low); }
html[data-theme="dark"] .ops-bulk-table thead th { background: var(--surface-container); }

/* Compliance/report cell states: light-tint + dark ink flipped for dark. */
html[data-theme="dark"] .cell-warn        { background: rgba(124,165,216,0.18) !important; color: #A6C4E6; }
html[data-theme="dark"] .cell-green       { background: rgba(127,176,105,0.16) !important; color: #A9D392; }
html[data-theme="dark"] .cell-major       { background: rgba(224,178,92,0.16)  !important; color: #E6C078; }
html[data-theme="dark"] .cell-outstanding { background: rgba(224,121,123,0.14) !important; color: #EDA0A2; }
html[data-theme="dark"] .cell-coa-soon    { background: rgba(127,176,105,0.20) !important; color: #A9D392; }
html[data-theme="dark"] .cell-cmr-soon    { background: rgba(186,140,220,0.18) !important; color: #CDA9E0; }
html[data-theme="dark"] .cell-expired     { background: rgba(224,121,123,0.22) !important; color: #EDA0A2; }
html[data-theme="dark"] .dr-kw-critical { color: #EDA0A2; }
html[data-theme="dark"] .dr-kw-warn     { color: #E6C078; }
html[data-theme="dark"] .dr-kw-info     { color: #A6C4E6; }

/* Form controls: hard-coded #FFF fills go to a recessed input surface. */
html[data-theme="dark"] .field input[type=text], html[data-theme="dark"] .field input[type=email],
html[data-theme="dark"] .field input[type=password], html[data-theme="dark"] .field input[type=date],
html[data-theme="dark"] .field input[type=time], html[data-theme="dark"] .field input[type=number],
html[data-theme="dark"] .field input[type=search], html[data-theme="dark"] .field input[type=tel],
html[data-theme="dark"] .field input[type=url], html[data-theme="dark"] .field input[type=datetime-local],
html[data-theme="dark"] .field select, html[data-theme="dark"] .field textarea,
html[data-theme="dark"] .time24-input { background: var(--surface-low); }

/* Chrome autofill paints its own light fill — repaint via inset shadow
   (background-color is ignored on :-webkit-autofill). */
html[data-theme="dark"] input:-webkit-autofill,
html[data-theme="dark"] input:-webkit-autofill:hover,
html[data-theme="dark"] input:-webkit-autofill:focus,
html[data-theme="dark"] textarea:-webkit-autofill,
html[data-theme="dark"] select:-webkit-autofill {
    -webkit-text-fill-color: var(--text);
    -webkit-box-shadow: 0 0 0 1000px var(--surface-low) inset;
    box-shadow: 0 0 0 1000px var(--surface-low) inset;
    caret-color: var(--text);
}

/* Walkthrough / tour card: light glass panel goes to dark glass so its
   token-coloured text stays readable. */
html[data-theme="dark"] .jags-tour-card {
    background: linear-gradient(180deg, rgba(30,36,56,0.96) 0%, rgba(23,28,43,0.94) 100%);
    border-color: rgba(157,176,240,0.18);
    box-shadow:
      0 1px 0 rgba(255,255,255,0.06) inset,
      0 0 0 1px rgba(0,0,0,0.40),
      0 28px 60px -12px rgba(0,0,0,0.60),
      0 8px 18px -8px rgba(0,0,0,0.40);
}

/* Bottom-nav Guide button: keep the brand-navy FILL (white glyph needs the
   navy, not the periwinkle text alias); ring matches the dark chrome. */
html[data-theme="dark"] .mobile-bottom-nav .mobile-nav-primary .jags-icon-wrap {
    background: #171756;
    border-color: rgba(23, 28, 43, 0.96);
}

/* Horizontal table scrollbars: navy-on-light thumb is invisible on dark. */
html[data-theme="dark"] .table-wrap { scrollbar-color: rgba(157,176,240,0.35) transparent; }
html[data-theme="dark"] .table-wrap::-webkit-scrollbar-thumb { background: rgba(157,176,240,0.30); }
html[data-theme="dark"] .table-wrap::-webkit-scrollbar-thumb:hover { background: rgba(157,176,240,0.50); }

/* Print stays a light paper document no matter the app theme. */
@media print {
    html[data-theme="dark"] { color-scheme: light; }
    html[data-theme="dark"] body { background: #fff; color: #111; }
}
/* Baseline heading rhythm — page-level pages can still override per card. */
h1, h2, h3, h4 {
    font-family: var(--font-display);
    color: var(--text-strong);
    line-height: var(--line-tight);
    letter-spacing: var(--tracking-tight);
    margin: 0;
    font-weight: 600;
}
h1 { font-size: var(--text-2xl); }
h2 { font-size: var(--text-xl); }
h3 { font-size: var(--text-lg); }
h4 { font-size: var(--text-base); font-weight: 600; }
p  { margin: 0 0 12px; }
a  { color: var(--link); text-decoration: none; }
a:hover { color: var(--primary); }
hr { border: none; border-top: 1px solid var(--border); margin: 24px 0; }
.muted        { color: var(--muted); }
.muted-strong { color: var(--muted-strong); }
.small        { font-size: var(--text-sm); }
.xs           { font-size: var(--text-xs); }
.mono         { font-family: var(--font-mono); }
.eyebrow {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
    color: var(--muted);
    font-weight: 600;
}

/* App shell */
.app-shell { min-height: 100vh; display: grid; grid-template-columns: 248px minmax(0, 1fr); }
.sidebar {
    /* Deep navy executive rail (2026-05-22 MVP UI pass) — premium dark
       sidebar over the white app canvas, on the JAGS navy/indigo brand.
       Tuned from the --sidebar-* tokens in :root so desktop + mobile drawer
       stay in lockstep. */
    background: var(--grad-sidebar);
    color: var(--sidebar-text);
    border-right: 1px solid var(--sidebar-border);
    padding: 20px 16px 24px;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(255,255,255,0.18) transparent;
}
.sidebar::-webkit-scrollbar { width: 6px; }
.sidebar::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.16); border-radius: 6px; }
.sidebar::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.28); }
.sidebar-brand {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    margin-bottom: 24px;
    padding: 10px;
    /* Light lockup panel — the logo asset is locked and may not be
       recoloured, so it keeps its own white card to stay crisp on the
       dark rail. */
    background: var(--sidebar-brand-bg);
    border: 1px solid rgba(255, 255, 255, 0.10);
    border-radius: var(--radius);
    box-shadow: 0 6px 18px rgba(5, 7, 22, 0.35);
}
.sidebar-brand img { width: 100%; height: auto; max-height: 56px; object-fit: contain; background: var(--sidebar-brand-bg); display: block; }
/* Animated brand mark (plays once per session, then rests on its final
   frame). The video is inert chrome: no pointer events, fixed 16:9 box so
   nothing shifts while it loads. Falls back to the static <img> above. */
.jags-brand-motion { display: block; width: 100%; }
.jags-brand-motion video {
    display: block; width: 100%; aspect-ratio: 16 / 9;
    /* Matches the static <img> chip directly above, NOT a theme surface.
       The logo artwork is dark navy, and object-fit:contain letterboxes a
       16:9 box around it — with --card here, dark mode painted those bars
       navy and the lockup read as two black slabs flanking the logo. */
    object-fit: contain; background: var(--sidebar-brand-bg);
    pointer-events: none; border-radius: 6px;
}
/* In the sidebar chip the mark keeps the compact lockup height the static
   logo had (max-height 56-64px), instead of a full-width 16:9 block that
   dominates the mobile drawer. Fixed height = still no layout shift. */
.sidebar-brand .jags-brand-motion video {
    aspect-ratio: auto; height: 64px; max-height: 64px;
}
.jags-brand-motion.jags-brand-motion-failed video { display: none; }
.jags-brand-motion .jags-brand-motion-fallback:not([hidden]) { display: block; }
.jags-brand-motion .jags-brand-motion-fallback[hidden] { display: none; }
.sidebar-brand .brand-sub { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.1em; text-align: center; padding-bottom: 2px; }
.sidebar-section {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
    color: var(--sidebar-muted);
    margin: 20px 10px 10px;
    font-weight: 600;
}
.sidebar nav a {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 11px;
    border-radius: var(--radius-sm);
    color: var(--sidebar-text);
    font-weight: 500;
    font-size: var(--text-base);
    letter-spacing: -0.005em;
    margin-bottom: 2px;
    transition:
        background var(--motion-fast) var(--ease-out),
        color      var(--motion-fast) var(--ease-out),
        box-shadow var(--motion-fast) var(--ease-out),
        transform  var(--motion-fast) var(--ease-out);
    position: relative;
}
.sidebar nav a:hover { background: var(--sidebar-hover-bg); color: #fff; }
.sidebar nav a:hover .nav-icon { color: #fff; opacity: 1; }
.sidebar nav a.active {
    /* Selected nav — a frosted raised pill with a bright accent marker so
       the active destination reads clearly against the dark navy rail. */
    background: var(--sidebar-active-bg);
    color: #fff;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.10);
}
.sidebar nav a.active .nav-icon { color: #fff; opacity: 1; }
.sidebar nav a.active::before {
    content: "";
    position: absolute; left: -16px; top: 8px; bottom: 8px;
    width: 3px; border-radius: 0 3px 3px 0;
    background: var(--sidebar-accent);
    opacity: 0.95;
}
.nav-icon {
    width: 18px; height: 18px;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--sidebar-muted);
    opacity: 0.92;
    transition: color var(--motion-fast) var(--ease-out), opacity var(--motion-fast) var(--ease-out);
    flex: 0 0 18px;
}
.nav-icon svg { width: 18px; height: 18px; display: block; }
.nav-icon .jags-icon-glyph { font-size: 14px; line-height: 1; }

/* ---------- Admin grouped workspace navigation ----------
   Used only by ROLE_ADMIN / ROLE_SYSTEM_ADMIN. Each entry in the admin
   nav list carries a 'group' key; layout_header renders a section
   header (.nav-group-section) every time the group changes and wraps
   the items in a .nav-group container. Non-admin roles never opt in,
   so this block has zero effect on their sidebars. */
.sidebar nav.nav-grouped { display: flex; flex-direction: column; }
.sidebar nav.nav-grouped .nav-group {
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding-bottom: 6px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--sidebar-border);
}
.sidebar nav.nav-grouped .nav-group:last-of-type {
    border-bottom: 0;
    margin-bottom: 0;
    padding-bottom: 0;
}
.sidebar nav.nav-grouped .nav-group-section {
    margin: 14px 10px 6px;
    padding-top: 2px;
    color: var(--sidebar-muted);
    /* Restate the inherited .sidebar-section typography so the section
       header reads as a calm department label rather than a heavy title. */
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.sidebar nav.nav-grouped .nav-group-section--first { margin-top: 4px; }
.nav-utilities { padding: 0 8px 8px; position: relative; }
.nav-search-trigger, .nav-rail-toggle, .nav-settings-toggle, .nav-settings-reset {
    appearance: none; border: 1px solid var(--sidebar-border); color: var(--sidebar-text);
    background: rgba(255,255,255,.045); font: inherit; cursor: pointer;
}
.nav-search-trigger { width: 100%; min-height: 42px; padding: 9px 10px; border-radius: 10px; display:flex; align-items:center; gap:9px; text-align:left; }
.nav-search-trigger:hover, .nav-rail-toggle:hover, .nav-settings-toggle:hover { background: var(--sidebar-hover-bg); color:#fff; }
.nav-shortcut { margin-left:auto; color:var(--sidebar-muted); font: 600 10px/1 var(--font-mono); }
.nav-utility-actions { display:flex; gap:6px; margin-top:6px; }
.nav-rail-toggle, .nav-settings-toggle { flex:1; min-height:36px; border-radius:8px; display:flex; align-items:center; justify-content:center; gap:7px; font-size:12px; }
.nav-settings { margin-top:8px; padding:12px; border:1px solid var(--sidebar-border); border-radius:10px; background:#111735; box-shadow:0 14px 30px rgba(0,0,0,.28); }
.nav-settings-title { color:#fff; font-weight:700; font-size:13px; }
.nav-settings p { margin:5px 0 10px; color:var(--sidebar-muted); font-size:11px; line-height:1.45; }
.nav-settings-groups { display:grid; gap:3px; }
.nav-settings-option { display:flex; align-items:center; gap:8px; min-height:32px; color:var(--sidebar-text); font-size:12px; }
.nav-settings-option input { width:16px; height:16px; accent-color:var(--sidebar-accent); }
.nav-settings-reset { width:100%; min-height:34px; margin-top:9px; border-radius:8px; font-size:12px; }
.nav-workspace { border-bottom:1px solid var(--sidebar-border); }
.sidebar nav.nav-grouped .nav-workspace:last-child { border-bottom:0; }
.sidebar nav.nav-grouped .nav-group-section {
    width:100%; min-height:42px; margin:0; padding:8px 10px; border:0; border-radius:7px;
    background:transparent; display:flex; align-items:center; gap:9px; cursor:pointer; text-align:left;
}
.sidebar nav.nav-grouped .nav-group-section:hover { color:#fff; background:rgba(255,255,255,.045); }
.nav-group-icon { display:inline-flex; width:18px; height:18px; flex:0 0 18px; }
.nav-group-icon .jags-icon { width:18px; height:18px; }
.nav-group-label { min-width:0; overflow:hidden; text-overflow:ellipsis; }
.nav-group-chevron { display:inline-flex; width:14px; height:14px; margin-left:auto; transition:transform .2s ease; }
.nav-group-chevron .jags-icon { width:14px; height:14px; }
.nav-group-section[aria-expanded="true"] .nav-group-chevron { transform:rotate(180deg); }
.nav-group[hidden] { display:none !important; }
.nav-workspace.is-active > .nav-group-section { color:#fff; background:rgba(255,255,255,.055); }
.nav-workspace.is-hidden { display:none; }
.nav-quick-access { margin:0 8px 8px; padding:8px; border:1px solid var(--sidebar-border); border-radius:10px; }
.nav-quick-access[hidden] { display:none; }
.nav-quick-title { color:var(--sidebar-muted); font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.08em; padding:0 4px 5px; }
.nav-quick-links { display:grid; gap:2px; }
.nav-quick-links a { margin:0 !important; min-height:36px !important; padding:7px 8px !important; }
.nav-item-row { display:grid; grid-template-columns:minmax(0,1fr) 30px; align-items:center; }
.nav-item-row > a { min-width:0; }
.nav-pin { width:28px; height:28px; padding:0; border:0; border-radius:7px; background:transparent; color:var(--sidebar-muted); cursor:pointer; opacity:0; }
.nav-item-row:hover .nav-pin, .nav-pin:focus-visible, .nav-pin.is-pinned { opacity:1; }
.nav-pin.is-pinned { color:#F4C96A; }
.nav-pin:hover { background:var(--sidebar-hover-bg); }

@media (min-width:901px) {
    body.jags-sidebar-collapsed .app-shell { grid-template-columns:72px minmax(0,1fr); }
    body.jags-sidebar-collapsed .sidebar { width:72px; padding-left:6px; padding-right:6px; overflow:visible; }
    body.jags-sidebar-collapsed .sidebar-brand { min-height:58px; padding:5px; }
    body.jags-sidebar-collapsed .sidebar-brand img { max-height:44px; }
    body.jags-sidebar-collapsed .sidebar-brand .brand-sub,
    body.jags-sidebar-collapsed .nav-label,
    body.jags-sidebar-collapsed .nav-shortcut,
    body.jags-sidebar-collapsed .nav-group-label,
    body.jags-sidebar-collapsed .nav-group-chevron,
    body.jags-sidebar-collapsed .nav-settings-toggle,
    body.jags-sidebar-collapsed .sidebar-account .who,
    body.jags-sidebar-collapsed .sidebar-account form,
    body.jags-sidebar-collapsed .sidebar > .sidebar-section,
    body.jags-sidebar-collapsed .jags-pwa-install-card { display:none !important; }
    body.jags-sidebar-collapsed .nav-quick-access { display:none !important; }
    body.jags-sidebar-collapsed .nav-utilities { padding:0 3px 8px; }
    body.jags-sidebar-collapsed .nav-search-trigger,
    body.jags-sidebar-collapsed .nav-rail-toggle { width:54px; min-width:54px; min-height:44px; flex:none; justify-content:center; padding:0; }
    body.jags-sidebar-collapsed .nav-utility-actions { display:block; }
    body.jags-sidebar-collapsed .nav-rail-toggle { margin-top:6px; }
    body.jags-sidebar-collapsed .nav-workspace { border:0; position:relative; }
    body.jags-sidebar-collapsed .sidebar nav.nav-grouped .nav-group-section { width:54px; min-height:46px; justify-content:center; padding:0; margin:2px 0; }
    body.jags-sidebar-collapsed .nav-workspace > .nav-group { display:none !important; }
    body.jags-sidebar-collapsed .nav-workspace:focus-within > .nav-group,
    body.jags-sidebar-collapsed .nav-workspace:hover > .nav-group {
        display:block !important; position:absolute; left:61px; top:0; width:238px; padding:8px;
        border:1px solid rgba(255,255,255,.12); border-radius:12px; background:#111735;
        box-shadow:0 18px 44px rgba(0,0,0,.38); z-index:9300;
    }
    body.jags-sidebar-collapsed .nav-workspace > .nav-group::before { content:attr(data-group-label); }
    body.jags-sidebar-collapsed .nav-workspace > .nav-group a { min-height:40px; }
    body.jags-sidebar-collapsed .sidebar-account { padding:6px; justify-content:center; }
}

@media (prefers-reduced-motion:reduce) {
    .nav-group-chevron, .app-shell, .sidebar { transition-duration:.01ms !important; }
}
/* ---------- End admin grouped workspace navigation ---------- */
.sidebar-account {
    margin-top: 12px;
    padding: 10px 11px;
    border-radius: var(--radius-sm);
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--sidebar-border);
    display: flex; align-items: center; gap: 10px;
}
.sidebar-account .who { min-width: 0; flex: 1; line-height: 1.2; }
.sidebar-account .who .name {
    font-weight: 600; font-size: var(--text-sm);
    color: var(--sidebar-text);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sidebar-account .who .role {
    font-size: var(--text-xs); color: var(--sidebar-muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sidebar-account form { margin: 0; }
.sidebar-account .btn-icon {
    width: 28px; height: 28px;
    padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 8px;
    border: 1px solid transparent;
    background: transparent;
    color: var(--sidebar-muted);
    cursor: pointer;
    transition: background var(--motion-fast) var(--ease-out), color var(--motion-fast) var(--ease-out);
}
.sidebar-account .btn-icon:hover { background: rgba(184,50,53,0.22); color: #F4A8AA; }
.sidebar-account .btn-icon:focus-visible {
    outline: none;
    box-shadow: var(--ring-focus);
}

.main { display: flex; flex-direction: column; min-width: 0; }
.topbar {
    background: rgba(var(--glass-rgb), 0.78);
    backdrop-filter: saturate(160%) blur(12px);
    -webkit-backdrop-filter: saturate(160%) blur(12px);
    border-bottom: 1px solid var(--border);
    padding: 14px 28px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: sticky;
    top: 0;
    z-index: 10;
}
.topbar h1 {
    margin: 0;
    font-size: var(--text-2xl);
    letter-spacing: var(--tracking-tight);
    font-weight: 700;
    color: var(--text-strong);
    line-height: 1.1;
}
.topbar-leading { display: flex; align-items: center; gap: 14px; min-width: 0; }
/* Role eyebrow + date — the quiet context lines around the page title.
   Visible at every size (the premium mobile layer re-tunes them <=900px)
   so the title block reads: eyebrow / strong title / subdued date. */
.mobile-page-context,
.mobile-page-meta { display: block; }
.mobile-page-context {
    color: var(--text-secondary);
    font-size: 12.5px;
    font-weight: 650;
    line-height: 1.2;
}
.mobile-page-meta {
    margin-top: 3px;
    color: var(--text-tertiary);
    font-size: 13px;
    line-height: 1.25;
}
/* Topbar search pill — visible affordance for the ⌘K command palette
   (the reference's "beautiful search bar"). Reuses the existing palette;
   no second search system. Full pill on wide desktop, icon-only on narrow
   desktop, hidden on phones (drawer/bottom-nav own navigation there). */
.topbar-search {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-left: 8px;
    padding: 7px 10px 7px 12px;
    min-width: 210px;
    max-width: 320px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--surface-low);
    color: var(--muted);
    font-size: var(--text-sm);
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    text-align: left;
    line-height: 1;
    transition:
        background var(--motion-fast) var(--ease-out),
        border-color var(--motion-fast) var(--ease-out),
        box-shadow var(--motion-fast) var(--ease-out);
}
.topbar-search:hover { background: var(--card); border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
.topbar-search:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.topbar-search-icon { display: inline-flex; align-items: center; color: var(--muted); flex: 0 0 auto; }
.topbar-search-text { flex: 1 1 auto; color: var(--muted); }
.topbar-search-kbd {
    flex: 0 0 auto;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--muted-strong);
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 3px 6px;
    line-height: 1;
}
/* Narrow desktop / tablet — collapse to a 36px circle that matches the
   bell / refresh controls so the topbar never crowds the page title. */
@media (max-width: 1180px) {
    .topbar-search {
        min-width: 0; max-width: none;
        width: 36px; height: 36px;
        padding: 0; gap: 0;
        justify-content: center;
        background: rgba(90,121,165,0.08);
    }
    .topbar-search-text, .topbar-search-kbd { display: none; }
}
@media (max-width: 900px) { .topbar-search { display: none; } }
.topbar-user { display: flex; align-items: center; gap: 12px; font-size: var(--text-sm); }
.topbar-user .who { line-height: 1.15; text-align: right; }
.topbar-user .who .name { font-weight: 600; color: var(--text-strong); }
.topbar-user .who .role { font-size: var(--text-xs); color: var(--muted); margin-top: 1px; letter-spacing: 0.01em; }

/* Notification bell — sits between Walkthrough and the user avatar. Quiet
   when there is nothing new (just the icon) and grows a small red badge with
   the unread count when there is. Clicking opens the notifications page. */
.topbar-bell {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center;
    width: 36px; height: 36px;
    border-radius: 999px;
    color: var(--text-strong);
    background: rgba(90,121,165,0.08);
    border: 1px solid var(--border);
    text-decoration: none;
    transition: background var(--motion-fast) var(--ease-out), color var(--motion-fast) var(--ease-out), box-shadow var(--motion-fast) var(--ease-out);
}
.topbar-bell:hover  { background: rgba(90,121,165,0.18); color: var(--primary); }
.topbar-bell:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.topbar-bell-icon { display: inline-flex; align-items: center; justify-content: center; }
.topbar-bell-badge {
    position: absolute;
    top: -4px; right: -4px;
    min-width: 18px; height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--danger);
    color: #fff;
    font-size: 10.5px; font-weight: 700;
    display: inline-flex; align-items: center; justify-content: center;
    box-shadow: 0 0 0 2px rgba(255,255,255,0.95);
    line-height: 1;
}
@media (max-width: 700px) {
    .topbar-bell { width: 32px; height: 32px; }
}

/* Discreet topbar refresh control — sits between Walkthrough and the
   bell. Clicking forces a fresh GET reload of the current URL so the
   user can pull updated data without using the browser refresh button
   (which can resubmit POSTs). Spinner state matches the existing
   submit-loading spinner so the page feels consistent. The "Last
   refreshed HH:MM" timestamp is exposed as a tooltip; no extra layout
   shift on the page. */
.topbar-refresh {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center;
    width: 36px; height: 36px;
    padding: 0;
    border-radius: 999px;
    color: var(--text-strong);
    background: rgba(90,121,165,0.08);
    border: 1px solid var(--border);
    cursor: pointer;
    transition: background var(--motion-fast) var(--ease-out), color var(--motion-fast) var(--ease-out), box-shadow var(--motion-fast) var(--ease-out);
}
.topbar-refresh:hover { background: rgba(90,121,165,0.18); color: var(--primary); }
.topbar-refresh:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.topbar-refresh .topbar-refresh-icon { display: inline-flex; align-items: center; justify-content: center; }
.topbar-refresh.is-refreshing { pointer-events: none; opacity: 0.65; cursor: wait; }
.topbar-refresh.is-refreshing .topbar-refresh-icon { animation: jagsSpin 700ms linear infinite; }
@media (prefers-reduced-motion: reduce) {
    .topbar-refresh.is-refreshing .topbar-refresh-icon { animation: none; }
}
@media (max-width: 700px) {
    .topbar-refresh { width: 32px; height: 32px; }
}

/* ---------------------------------------------------------------
   Inline SVG icons + avatars.
   --------------------------------------------------------------- */
.jags-icon { display: inline-block; vertical-align: middle; flex: 0 0 auto; }
.jags-icon-glyph { display: inline-block; line-height: 1; }
.jags-icon-missing { display: inline-block; width: 18px; height: 18px; }
.btn .jags-icon { width: 16px; height: 16px; }
.btn-sm .jags-icon { width: 14px; height: 14px; }

.jags-avatar {
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 999px;
    background: var(--grad-jags);
    color: #fff;
    font-weight: 600;
    letter-spacing: 0.02em;
    box-shadow: var(--shadow-sm);
    line-height: 1;
    flex-shrink: 0;
    overflow: hidden;
    user-select: none;
}
.jags-avatar-sm { width: 28px; height: 28px; font-size: 11px; }
.jags-avatar-md { width: 36px; height: 36px; font-size: 13px; }
.jags-avatar-lg { width: 56px; height: 56px; font-size: 18px; }
.jags-avatar-initials { display: block; }
.jags-avatar-glyph { color: #fff; opacity: 0.85; }
.jags-avatar-empty { background: linear-gradient(180deg, #5A79A5, #274270); }

/* Role-tinted thin ring around the avatar — purely decorative. */
.jags-avatar-ring { box-shadow: var(--shadow-sm), 0 0 0 2px rgba(255,255,255,0.85), 0 0 0 3.5px rgba(94,100,114,0.30); }
.jags-avatar-ring-admin       { box-shadow: var(--shadow-sm), 0 0 0 2px rgba(255,255,255,0.92), 0 0 0 3.5px rgba(184,50,53,0.55); }
.jags-avatar-ring-tr          { box-shadow: var(--shadow-sm), 0 0 0 2px rgba(255,255,255,0.92), 0 0 0 3.5px rgba(90,121,165,0.55); }
.jags-avatar-ring-operations  { box-shadow: var(--shadow-sm), 0 0 0 2px rgba(255,255,255,0.92), 0 0 0 3.5px rgba(216,181,109,0.65); }
.jags-avatar-ring-maintenance { box-shadow: var(--shadow-sm), 0 0 0 2px rgba(255,255,255,0.92), 0 0 0 3.5px rgba(216,181,109,0.65); }
.jags-avatar-ring-pilot       { box-shadow: var(--shadow-sm), 0 0 0 2px rgba(255,255,255,0.92), 0 0 0 3.5px rgba(74,103,51,0.55); }
.jags-avatar-ring-viewer      { box-shadow: var(--shadow-sm), 0 0 0 2px rgba(255,255,255,0.92), 0 0 0 3.5px rgba(94,100,114,0.40); }

/* Legacy .avatar — keep so any pre-existing markup outside layout.php
   still renders. New code should use user_avatar(). */
.avatar {
    width: 36px; height: 36px; border-radius: 999px;
    background: var(--grad-jags);
    color: #fff; font-weight: 600; font-size: 13px;
    display: inline-flex; align-items: center; justify-content: center;
    box-shadow: var(--shadow-sm);
}
.content { padding: 28px; }
.content-narrow { max-width: 720px; margin: 0 auto; }

/* Page entrance — every navigation fades content in with a 6px settle.
   Suppressed in print and under prefers-reduced-motion (see below). */
.main > .content {
    animation: jagsPageIn var(--motion-med) var(--ease-premium) both;
}
@keyframes jagsPageIn {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Cards */
.card {
    background: var(--surface-primary);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-card);
    padding: 22px;
    transition:
        box-shadow var(--motion-med) var(--ease-soft),
        border-color var(--motion-med) var(--ease-soft);
}
.card + .card { margin-top: 18px; }
.card-elevated { box-shadow: var(--shadow-md); }
/* Hero card — Apple-style premium dark panel. Top hairline highlight,
   ambient corner glow, refined typography hierarchy. Used by any page
   that wants a brand moment at the top of its content. */
.card-hero {
    position: relative;
    overflow: hidden;
    background: var(--grad-jags);
    color: #fff;
    border: none;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    padding: 28px 32px;
}
.card-hero::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 1px;
    background: linear-gradient(90deg,
        rgba(255,255,255,0) 0%,
        rgba(255,255,255,0.18) 30%,
        rgba(255,255,255,0.22) 50%,
        rgba(255,255,255,0.18) 70%,
        rgba(255,255,255,0) 100%);
    pointer-events: none;
    z-index: 1;
}
.card-hero::after {
    content: "";
    position: absolute;
    top: -120px; right: -120px;
    width: 380px; height: 380px;
    background: radial-gradient(circle, rgba(255,255,255,0.08) 0%, rgba(255,255,255,0) 65%);
    pointer-events: none;
    z-index: 0;
}
.card-hero > * { position: relative; z-index: 2; }
.card-hero h1, .card-hero h2, .card-hero h3, .card-hero h4 {
    margin: 0 0 6px;
    letter-spacing: -0.03em;
    color: #fff;
    font-weight: 700;
}
.card-hero p { margin: 0; opacity: 0.85; color: #fff; }
.card-glass {
    background: linear-gradient(180deg, rgba(var(--glass-rgb),0.85), rgba(var(--glass-rgb),0.65));
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255,255,255,0.5);
    box-shadow: var(--shadow-md);
}

.section-title {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; flex-wrap: wrap;
    margin: 0 0 14px;
}
.section-title h2 {
    margin: 0;
    font-size: var(--text-lg);
    letter-spacing: -0.02em;
    font-weight: 650;
    color: var(--text-strong);
}
.section-title .muted { font-size: var(--text-sm); }
.card-hero h2 {
    font-size: var(--text-3xl);
    letter-spacing: -0.04em;
    font-weight: 700;
    line-height: 1.1;
    color: #fff;
}
.card-hero p { font-size: var(--text-base); line-height: var(--line-relaxed); }

/* ----------------------------------------------------------------------
   Reusable polished primitives — work on any page.

   .hero-eyebrow      — small uppercase label inside dark hero cards
   .metadata-chips    — inline metadata row with thin vertical dividers
   .metadata-chips .chip
   .feature-value     — large lead number on a tinted band inside a card
   .row-list          — Apple Settings-style key/value list with dividers
   .modern-card-head  — card header with icon chip + title + corner meta
   ---------------------------------------------------------------------- */
.hero-eyebrow {
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: rgba(255,255,255,0.62);
    margin: 0 0 6px;
}
.hero-display {
    margin: 0 0 6px;
    font-size: clamp(28px, 4vw, 44px);
    font-weight: 700;
    letter-spacing: -0.04em;
    line-height: 1.05;
    color: #fff;
    font-feature-settings: 'tnum' 1, 'lnum' 1, 'ss01' 1;
}
.hero-sub {
    margin: 0 0 14px;
    font-size: 15px;
    font-weight: 400;
    line-height: 1.45;
    color: rgba(255,255,255,0.85);
    max-width: 720px;
}
.metadata-chips {
    display: flex; flex-wrap: wrap;
    gap: 4px 8px;
    align-items: center;
}
.metadata-chips .chip {
    display: inline-flex; align-items: baseline; gap: 5px;
    padding: 0;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: -0.005em;
    color: rgba(255,255,255,0.88);
    background: transparent;
    border: none;
    line-height: 1.4;
}
.metadata-chips .chip + .chip {
    border-left: 1px solid rgba(255,255,255,0.20);
    padding-left: 8px;
}
.metadata-chips .chip .lbl {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.10em;
    color: rgba(255,255,255,0.50);
    font-weight: 600;
}
/* Light-surface variant of metadata-chips for use outside hero cards */
.metadata-chips.on-light .chip { color: var(--text-strong); }
.metadata-chips.on-light .chip + .chip { border-left-color: var(--border); }
.metadata-chips.on-light .chip .lbl { color: var(--muted); }

.feature-value {
    margin: -22px -22px 14px;
    padding: 18px 22px 14px;
    border-bottom: 1px solid var(--border);
    background: var(--surface-low);
}
.feature-value .feat-lbl {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    font-weight: 600;
    margin-bottom: 4px;
}
.feature-value .feat-val {
    font-size: 28px;
    font-weight: 700;
    letter-spacing: -0.025em;
    line-height: 1.05;
    color: var(--text-strong);
    font-feature-settings: 'tnum' 1, 'lnum' 1;
    word-break: break-word;
}
.feature-value .feat-sub {
    font-size: 12.5px;
    color: var(--muted);
    margin-top: 4px;
    font-weight: 500;
}
.feature-value.warn   { background: rgba(216,181,109,0.10); }
.feature-value.warn .feat-val   { color: var(--status-warning-ink); }
.feature-value.danger { background: rgba(184,50,53,0.06); }
.feature-value.danger .feat-val { color: var(--status-danger-ink); }
.feature-value.success{ background: rgba(74,103,51,0.08); }
.feature-value.success .feat-val{ color: #2C4A1B; }

.row-list {
    list-style: none;
    margin: 0;
    padding: 0;
}
.row-list li {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 14px;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
    min-width: 0;
}
.row-list li:last-child { border-bottom: none; padding-bottom: 0; }
.row-list .k {
    font-size: 13px;
    color: var(--muted);
    font-weight: 500;
    flex-shrink: 0;
}
.row-list .v {
    font-size: 14px;
    color: var(--text-strong);
    font-weight: 600;
    text-align: right;
    min-width: 0;
    word-break: break-word;
}
.row-list .v.mono {
    font-family: var(--font-mono);
    font-feature-settings: 'tnum' 1, 'lnum' 1;
}
.row-list .v .sub {
    display: block;
    font-size: 11.5px;
    color: var(--muted);
    font-weight: 500;
    margin-top: 2px;
}

.modern-card-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px;
    margin: -4px -4px 14px;
}
.modern-card-head .ttl {
    display: flex; align-items: center; gap: 10px;
    min-width: 0;
}
.modern-card-head .ttl-icon {
    width: 36px; height: 36px;
    border-radius: 10px;
    background: linear-gradient(180deg, rgba(39,66,112,0.10), rgba(39,66,112,0.04));
    color: var(--secondary);
    display: inline-flex; align-items: center; justify-content: center;
    flex: 0 0 36px;
}
.modern-card-head .ttl-icon svg { width: 18px; height: 18px; }
.modern-card-head h3 {
    margin: 0;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: var(--text-strong);
}
.modern-card-head .meta {
    font-size: 12px;
    color: var(--muted);
    font-weight: 500;
    text-align: right;
    flex-shrink: 0;
}
/* Countdown chip — semantic-coloured pill for date countdowns, etc. */
.countdown-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.012em;
    line-height: 1.4;
}
.countdown-chip.success { background: rgba(74,103,51,0.12); color: var(--status-success-ink); }
.countdown-chip.info    { background: rgba(90,121,165,0.14); color: var(--status-info-ink); }
.countdown-chip.warn    { background: rgba(216,181,109,0.18); color: var(--status-warning-ink); }
.countdown-chip.danger  { background: rgba(184,50,53,0.14); color: var(--status-danger-ink); }
.countdown-chip.muted   { background: rgba(94,100,114,0.12); color: var(--muted); }

/* Card section title — drop-in replacement for the inline-styled
   `<h3 style="margin:0 0 10px; font-size:15px;">` pattern used inside
   .card blocks. Slightly tighter than .section-title h2. */
.card-section-title {
    margin: 0 0 12px;
    font-size: 15px;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: var(--text-strong);
}

/* ====================================================================
   Skip-to-content — first focusable element on the page. Hidden until
   focused so keyboard users can jump straight past the chrome.
   ==================================================================== */
.skip-to-content {
    position: fixed;
    top: -100px; left: 16px;
    z-index: 99999;
    background: var(--primary);
    color: #fff;
    padding: 10px 14px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
    box-shadow: var(--shadow-md);
    transition: top var(--motion-fast) var(--ease-out);
}
.skip-to-content:focus,
.skip-to-content:focus-visible {
    top: 16px;
    outline: none;
    box-shadow: 0 0 0 3px rgba(90,121,165,0.45), var(--shadow-md);
}

/* ====================================================================
   Toast notifications — replace the top-of-page flash strip with a
   slide-in stack in the bottom-right corner. Stacks up to 5 visible
   toasts; older ones auto-dismiss after 5s.
   ==================================================================== */
.jags-toast-region {
    position: fixed;
    bottom: 24px; right: 24px;
    z-index: 9500;
    display: flex; flex-direction: column-reverse;
    gap: 10px;
    pointer-events: none;
    max-width: min(420px, calc(100vw - 32px));
}
.jags-toast {
    pointer-events: auto;
    display: flex; align-items: flex-start; gap: 10px;
    padding: 12px 14px;
    border-radius: var(--radius);
    background: var(--card);
    border: 1px solid var(--border);
    box-shadow: 0 12px 32px rgba(11,11,47,0.18), 0 2px 6px rgba(11,11,47,0.06);
    font-size: 13.5px;
    line-height: 1.45;
    color: var(--text);
    animation: jagsToastIn 220ms var(--ease-premium);
    will-change: transform, opacity;
}
.jags-toast.is-leaving { animation: jagsToastOut 180ms var(--ease-out) forwards; }
.jags-toast .toast-icon {
    flex: 0 0 18px;
    width: 18px; height: 18px;
    display: inline-flex; align-items: center; justify-content: center;
    margin-top: 1px;
    color: var(--secondary);
}
.jags-toast .toast-body { flex: 1 1 auto; min-width: 0; word-break: break-word; }
.jags-toast .toast-close {
    flex: 0 0 auto;
    background: transparent; border: none;
    width: 24px; height: 24px;
    border-radius: 999px;
    color: var(--muted);
    font-size: 16px; line-height: 1;
    cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    padding: 0;
    transition: background var(--motion-fast) var(--ease-out), color var(--motion-fast) var(--ease-out);
}
.jags-toast .toast-close:hover { background: rgba(94,100,114,0.12); color: var(--text); }
.jags-toast .toast-close:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.jags-toast.success { border-color: rgba(74,103,51,0.36); background: linear-gradient(180deg, rgba(74,103,51,0.04), #fff); }
.jags-toast.success .toast-icon { color: var(--success); }
.jags-toast.warn    { border-color: rgba(216,181,109,0.50); background: linear-gradient(180deg, rgba(216,181,109,0.06), #fff); }
.jags-toast.warn    .toast-icon { color: #B6883A; }
.jags-toast.danger  { border-color: rgba(184,50,53,0.40); background: linear-gradient(180deg, rgba(184,50,53,0.04), #fff); }
.jags-toast.danger  .toast-icon { color: #B83235; }
.jags-toast.info    { border-color: rgba(90,121,165,0.36); background: linear-gradient(180deg, rgba(90,121,165,0.05), #fff); }
.jags-toast.info    .toast-icon { color: var(--info); }
@keyframes jagsToastIn  { from { opacity: 0; transform: translateY(12px) scale(0.98); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes jagsToastOut { to { opacity: 0; transform: translateY(8px) scale(0.98); } }
@media (max-width: 700px) {
    .jags-toast-region { left: 12px; right: 12px; bottom: var(--mobile-bottom-nav-clearance); max-width: none; }
}
@media (prefers-reduced-motion: reduce) {
    .jags-toast { animation: none !important; }
}
@media print {
    .jags-toast-region,
    .user-menu-popover,
    .bell-popover,
    .bell-wrap,
    .user-menu,
    .cmdk-modal,
    .skip-to-content { display: none !important; }
    .jags-flash-region { display: none !important; }
    /* Re-show flash messages on print via the noscript fallback. */

    /* ----------------------------------------------------------------
       Operational-document print overflow safety (2026-05-30 polish
       sprint). Long unbroken tokens — route strings, registration/code
       cells, consignor/consignee names, and free-text remarks/notes —
       must wrap to the page instead of clipping off the right edge of
       dispatch packs, radio logs, the Daily Report, and W&B records.
       `overflow-wrap: anywhere` only breaks a word when it would
       otherwise overflow its box, so normal prose, headings, and short
       codes are visually unchanged. Print-only: screen layout untouched.
       ---------------------------------------------------------------- */
    td, th { overflow-wrap: anywhere; }
    .pre-wrap, [style*="pre-wrap"] { overflow-wrap: anywhere; }

    /* ----------------------------------------------------------------
       Wide horizontal-scroll boards must collapse to fit the page on
       print instead of clipping at the scroll container's right edge.
       The Compliance whiteboard table is laid out at min-width:1100px
       inside an overflow-x:auto wrapper for the screen — neither survives
       an A4/Letter page. Unlock both for print only; the cell wrapping
       rule above keeps the content legible. Pilot Compliance already
       ships its own print parity, so it is intentionally not touched.
       ---------------------------------------------------------------- */
    .cb-board-scroll { overflow-x: visible !important; }
    .cb-board { min-width: 0 !important; }
}

/* ====================================================================
   User-menu dropdown — replaces the static .topbar-user block. Click
   the avatar/name to open a popover with profile/settings/logout.
   ==================================================================== */
.user-menu-button {
    display: flex; align-items: center; gap: 12px;
    padding: 4px 6px 4px 10px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 999px;
    cursor: pointer;
    font-family: inherit;
    font-size: var(--text-sm);
    color: var(--text-strong);
    transition: background var(--motion-fast) var(--ease-out), border-color var(--motion-fast) var(--ease-out), box-shadow var(--motion-fast) var(--ease-out);
}
.user-menu-button .who { line-height: 1.15; text-align: right; }
.user-menu-button .who .name { font-weight: 600; color: var(--text-strong); }
.user-menu-button .who .role { font-size: var(--text-xs); color: var(--muted); margin-top: 1px; letter-spacing: 0.01em; }
.user-menu-button:hover { background: rgba(90,121,165,0.06); border-color: var(--border); }
.user-menu-button:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.user-menu-button[aria-expanded="true"] { background: rgba(90,121,165,0.10); border-color: var(--border-strong); }

.user-menu {
    position: relative;
}
.user-menu-popover {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    min-width: 240px;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 16px 40px rgba(11,11,47,0.16), 0 2px 6px rgba(11,11,47,0.06);
    padding: 6px;
    display: none;
    z-index: 100;
    animation: jagsPopoverIn 160ms var(--ease-out);
}
.user-menu-popover.is-open { display: block; }
.user-menu-popover .menu-head {
    padding: 10px 12px 8px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 6px;
}
.user-menu-popover .menu-head .name { font-weight: 600; color: var(--text-strong); font-size: 13.5px; line-height: 1.25; }
.user-menu-popover .menu-head .email { font-size: 12px; color: var(--muted); margin-top: 2px; word-break: break-all; }
.user-menu-popover .menu-item {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    color: var(--text);
    font-size: 13px;
    font-weight: 500;
    text-decoration: none;
    cursor: pointer;
    background: transparent;
    border: none;
    width: 100%;
    text-align: left;
    font-family: inherit;
    line-height: 1.3;
}
.user-menu-popover .menu-item:hover { background: rgba(90,121,165,0.08); color: var(--primary); }
.user-menu-popover .menu-item:focus-visible { outline: none; background: rgba(90,121,165,0.12); box-shadow: 0 0 0 2px var(--secondary) inset; }
.user-menu-popover .menu-item .ico {
    width: 18px; height: 18px;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--muted);
    flex: 0 0 18px;
}
.user-menu-popover .menu-divider { height: 1px; background: var(--border); margin: 6px 4px; }
.user-menu-popover form { margin: 0; }
.user-menu-popover .menu-item.danger { color: var(--status-danger-ink); }
.user-menu-popover .menu-item.danger:hover { background: rgba(184,50,53,0.08); }
@keyframes jagsPopoverIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }

/* ====================================================================
   Bell popover — recent notifications inline.
   ==================================================================== */
.bell-popover {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    width: min(380px, calc(100vw - 32px));
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 16px 40px rgba(11,11,47,0.16), 0 2px 6px rgba(11,11,47,0.06);
    display: none;
    z-index: 100;
    animation: jagsPopoverIn 160ms var(--ease-out);
    overflow: hidden;
}
.bell-popover.is-open { display: block; }
.bell-wrap { position: relative; display: inline-block; }
.bell-popover .bell-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px;
    padding: 12px 14px 10px;
    border-bottom: 1px solid var(--border);
}
.bell-popover .bell-head .ttl { font-weight: 700; font-size: 14px; color: var(--text-strong); }
.bell-popover .bell-head .count { font-size: 11px; color: var(--muted); }
.bell-popover .bell-list {
    list-style: none; margin: 0; padding: 0;
    max-height: 360px; overflow-y: auto;
}
.bell-popover .bell-list li {
    border-bottom: 1px solid var(--border);
}
.bell-popover .bell-list li:last-child { border-bottom: none; }
.bell-popover .bell-list a {
    display: block;
    padding: 10px 14px;
    text-decoration: none;
    color: var(--text);
    transition: background var(--motion-fast) var(--ease-out);
}
.topbar-bell { min-width:44px;min-height:44px; }
.bell-popover .bell-list a { min-height:52px; }
.bell-popover .bell-foot form { margin:0; }
.bell-mark-all { border:0;background:transparent;color:var(--secondary);font:inherit;font-size:12.5px;font-weight:600;cursor:pointer;padding:8px; }
.bell-mark-all:hover,.bell-mark-all:focus-visible { text-decoration:underline; }
.bell-popover .bell-list a:hover { background: rgba(90,121,165,0.06); }
.bell-popover .bell-list a:focus-visible { outline: none; background: rgba(90,121,165,0.12); }
.bell-popover .bell-list .ttl-line {
    font-weight: 600;
    font-size: 13px;
    color: var(--text-strong);
    line-height: 1.35;
    word-break: break-word;
}
.bell-popover .bell-list .meta-line {
    font-size: 11.5px;
    color: var(--muted);
    margin-top: 2px;
}
.bell-popover .bell-list li.unread .ttl-line::before {
    content: "";
    display: inline-block;
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--info);
    margin-right: 6px;
    vertical-align: middle;
}
.bell-popover .bell-empty {
    padding: 28px 18px;
    text-align: center;
    color: var(--muted);
    font-size: 13px;
}
.bell-popover .bell-empty svg { color: var(--border-strong); margin-bottom: 6px; }
.bell-popover .bell-foot {
    border-top: 1px solid var(--border);
    padding: 8px 14px;
    display: flex; align-items: center; justify-content: space-between;
}
.bell-popover .bell-foot a { font-size: 12.5px; font-weight: 600; }
.bell-popover .bell-foot .small-link { font-size: 11.5px; color: var(--muted); }

/* ====================================================================
   Missing Risk Assessment departure escalation — authenticated bell and
   Notification Centre only. Ordinary notification rules remain unchanged.
   ==================================================================== */
.bell-popover .bell-list li.bell-item--departure-escalation {
    border-left: 4px solid var(--danger);
    background: color-mix(in srgb, var(--danger) 7%, var(--card));
}
.bell-popover .bell-list li.bell-item--departure-escalation a {
    padding-left: 12px;
    overflow-wrap: anywhere;
}
.bell-escalation-heading {
    display: flex;
    align-items: center;
    gap: 7px;
    color: var(--danger);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .055em;
    line-height: 1.25;
}
.bell-escalation-shield {
    display: inline-flex;
    flex: 0 0 auto;
}
.bell-escalation-statement {
    margin-top: 5px;
    color: var(--text-strong);
    font-size: 12.5px;
    font-weight: 650;
    line-height: 1.4;
    overflow-wrap: anywhere;
}
.notif-item--departure-escalation {
    margin: 10px 0;
    border: 2px solid color-mix(in srgb, var(--danger) 65%, var(--border));
    border-left-width: 6px;
    border-radius: 12px;
    background: color-mix(in srgb, var(--danger) 6%, var(--card));
    overflow: hidden;
}
.notif-item--departure-escalation:last-child { border-bottom: 2px solid color-mix(in srgb, var(--danger) 65%, var(--border)); }
.notif-item--departure-escalation .notif-escalation-link {
    grid-template-columns: 42px minmax(0, 1fr) max-content;
    gap: 14px;
    align-items: start;
    padding: 16px;
}
.notif-item--departure-escalation .notif-escalation-shield {
    width: 42px;
    height: 42px;
    color: var(--danger);
    background: color-mix(in srgb, var(--danger) 13%, var(--card));
}
.notif-item--departure-escalation .notif-escalation-body,
.notif-item--departure-escalation .notif-escalation-statement,
.notif-item--departure-escalation .notif-escalation-detail {
    min-width: 0;
    overflow-wrap: anywhere;
}
.notif-escalation-heading {
    display: flex;
    align-items: center;
    gap: 7px;
    color: var(--danger);
    font-size: 12px;
    font-weight: 850;
    letter-spacing: .065em;
    line-height: 1.3;
}
.notif-escalation-statement {
    margin-top: 7px;
    color: var(--text-strong);
    font-size: 14px;
    font-weight: 700;
    line-height: 1.45;
}
.notif-escalation-details {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 5px 16px;
    margin-top: 11px;
}
.notif-escalation-detail {
    color: var(--muted-strong);
    font-size: 12.5px;
    line-height: 1.4;
}
.notif-escalation-status {
    color: var(--danger);
    font-weight: 800;
}
.notif-escalation-action {
    align-self: center;
    color: var(--danger);
    font-size: 12.5px;
    font-weight: 750;
    white-space: nowrap;
}
@media (max-width: 700px) {
    .notif-item--departure-escalation .notif-escalation-link {
        grid-template-columns: 36px minmax(0, 1fr);
        gap: 10px;
        padding: 14px;
    }
    .notif-item--departure-escalation .notif-escalation-shield {
        width: 36px;
        height: 36px;
    }
    .notif-item--departure-escalation .notif-escalation-details {
        grid-template-columns: minmax(0, 1fr);
    }
    .notif-item--departure-escalation .notif-escalation-action {
        grid-column: 2;
        justify-self: start;
        white-space: normal;
    }
}

/* ====================================================================
   Cmd-K quick switcher — modal with search + categorised results.
   ==================================================================== */
.cmdk-modal {
    position: fixed;
    inset: 0;
    z-index: 9300;
    display: none;
    align-items: flex-start;
    justify-content: center;
    padding-top: clamp(60px, 12vh, 140px);
    padding-left: 16px; padding-right: 16px;
}
.cmdk-modal.is-open { display: flex; }
.cmdk-modal[hidden] {
    display: none !important;
    pointer-events: none !important;
}
.cmdk-backdrop {
    position: absolute; inset: 0;
    background: rgba(11,11,47,0.45);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    animation: jagsTourFade 180ms ease-out;
}
.cmdk-panel {
    position: relative;
    width: min(640px, 100%);
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: 0 24px 60px rgba(11,11,47,0.30), 0 4px 12px rgba(11,11,47,0.12);
    overflow: hidden;
    animation: jagsTourPop 200ms var(--ease-premium);
    display: flex; flex-direction: column;
    max-height: min(560px, calc(100vh - 120px));
}
.cmdk-input-wrap {
    display: flex; align-items: center; gap: 10px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border);
    background: var(--surface);
}
.cmdk-input-wrap svg { color: var(--muted); flex-shrink: 0; }
.cmdk-input {
    flex: 1 1 auto;
    border: none;
    background: transparent;
    font-size: 15px;
    color: var(--text);
    font-family: inherit;
    outline: none;
    line-height: 1.4;
}
.cmdk-input::placeholder { color: var(--muted); }
.cmdk-hint {
    font-size: 11px;
    color: var(--muted);
    background: rgba(90,121,165,0.08);
    border: 1px solid var(--border);
    padding: 2px 6px;
    border-radius: 4px;
    font-family: var(--font-mono);
    flex-shrink: 0;
}
.cmdk-results { flex: 1 1 auto; overflow-y: auto; padding: 6px 8px 10px; }
.cmdk-section-label {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    color: var(--muted);
    padding: 10px 10px 4px;
}
.cmdk-item {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    color: var(--text);
    text-decoration: none;
    cursor: pointer;
    border: 1px solid transparent;
    background: transparent;
    width: 100%; text-align: left;
    font-family: inherit;
    line-height: 1.3;
    font-size: 14px;
}
.cmdk-item .ico {
    width: 22px; height: 22px;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--muted);
    flex: 0 0 22px;
}
.cmdk-item .label { font-weight: 500; color: var(--text-strong); flex: 1 1 auto; min-width: 0; word-break: break-word; }
.cmdk-item .sub   { font-size: 12px; color: var(--muted); flex-shrink: 0; }
.cmdk-item.is-active,
.cmdk-item:hover {
    background: rgba(90,121,165,0.08);
    border-color: var(--border);
}
.cmdk-empty {
    padding: 32px 18px;
    text-align: center;
    color: var(--muted);
    font-size: 13.5px;
}
.cmdk-foot {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; flex-wrap: wrap;
    padding: 8px 14px;
    border-top: 1px solid var(--border);
    background: var(--surface);
    font-size: 11.5px;
    color: var(--muted);
}
.cmdk-foot kbd {
    background: rgba(94,100,114,0.10);
    border: 1px solid var(--border);
    padding: 1px 6px;
    border-radius: 4px;
    font-family: var(--font-mono);
    font-size: 10.5px;
}
@media (prefers-reduced-motion: reduce) {
    .cmdk-backdrop, .cmdk-panel, .user-menu-popover, .bell-popover, .jags-toast {
        animation: none !important;
    }
}

/* ====================================================================
   Breadcrumbs — used on detail pages (aircraft-view, defect-view, etc.)
   ==================================================================== */
.breadcrumbs {
    display: flex; align-items: center; flex-wrap: wrap;
    gap: 6px;
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    font-size: 13px;
    color: var(--muted);
    line-height: 1.4;
}
.breadcrumbs li { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.breadcrumbs li + li::before {
    content: "›";
    color: var(--border-strong);
    font-size: 14px;
    line-height: 1;
}
.breadcrumbs a {
    color: var(--secondary);
    text-decoration: none;
    font-weight: 500;
    border-radius: 4px;
    padding: 2px 4px;
    transition: background var(--motion-fast) var(--ease-out), color var(--motion-fast) var(--ease-out);
}
.breadcrumbs a:hover { color: var(--primary); background: rgba(90,121,165,0.08); }
.breadcrumbs li.current { color: var(--text-strong); font-weight: 600; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media print { .breadcrumbs { display: none; } }

/* ====================================================================
   Empty state — used inside .card or stand-alone for "no items yet"
   states. Icon block + title + description + optional CTA.
   ==================================================================== */
.empty-state {
    display: flex; flex-direction: column; align-items: center;
    text-align: center;
    padding: 42px 24px;
    color: var(--muted);
    font-size: 13.5px;
    line-height: 1.55;
}
.empty-state .empty-icon {
    width: 56px; height: 56px;
    border-radius: 16px;
    background: linear-gradient(180deg, rgba(39,66,112,0.08), rgba(39,66,112,0.03));
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--secondary);
    margin-bottom: 14px;
}
.empty-state .empty-icon svg { width: 28px; height: 28px; opacity: 0.85; }
.empty-state h3 {
    margin: 0 0 6px;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: var(--text-strong);
}
.empty-state p {
    margin: 0 0 16px;
    max-width: 360px;
    color: var(--muted);
}
.empty-state .empty-actions {
    display: flex; gap: 8px; flex-wrap: wrap; justify-content: center;
}
.empty-state.compact { padding: 26px 16px; }

/* ====================================================================
   Filter chip row — for active filters above lists.
   ==================================================================== */
.filter-chips {
    display: flex; align-items: center; flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 14px;
    font-size: 12.5px;
}
.filter-chips .lbl {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    font-weight: 700;
    margin-right: 4px;
}
.filter-chips .filter-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 6px 4px 10px;
    border-radius: 999px;
    background: rgba(90,121,165,0.10);
    border: 1px solid rgba(90,121,165,0.22);
    color: var(--secondary);
    font-weight: 600;
    line-height: 1.3;
}
.filter-chips .filter-chip .x {
    width: 18px; height: 18px;
    border-radius: 999px;
    background: rgba(90,121,165,0.16);
    border: none;
    color: var(--secondary);
    cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 13px; line-height: 1;
    padding: 0;
    text-decoration: none;
    transition: background var(--motion-fast) var(--ease-out), color var(--motion-fast) var(--ease-out);
}
.filter-chips .filter-chip .x:hover { background: var(--secondary); color: #fff; }
.filter-chips .clear-all {
    font-size: 12px;
    font-weight: 600;
    color: var(--muted);
    text-decoration: underline;
}
.filter-chips .clear-all:hover { color: var(--primary); }

/* ====================================================================
   List search — input inside a page-header that filters table rows.
   ==================================================================== */
.list-search {
    display: inline-flex; align-items: center; gap: 8px;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 6px 12px 6px 14px;
    width: 240px;
    transition: border-color var(--motion-fast) var(--ease-out), box-shadow var(--motion-fast) var(--ease-out);
}
.list-search:focus-within { border-color: var(--secondary); box-shadow: var(--ring-focus); }
.list-search svg { color: var(--muted); flex-shrink: 0; }
.list-search input {
    border: none; background: transparent;
    flex: 1 1 auto;
    font-size: 13.5px;
    font-family: inherit;
    color: var(--text);
    outline: none;
    line-height: 1.4;
    min-width: 0;
}
.list-search input::placeholder { color: var(--muted); }
@media (max-width: 700px) {
    .list-search { width: 100%; }
}

/* ====================================================================
   Skeleton loaders — shimmer placeholders for lazy or pending content.
   ==================================================================== */
.skeleton {
    display: block;
    background: linear-gradient(90deg, var(--surface-low) 0%, rgba(94,100,114,0.10) 50%, var(--surface-low) 100%);
    background-size: 200% 100%;
    animation: jagsShimmer 1.4s ease-in-out infinite;
    border-radius: var(--radius-sm);
    color: transparent;
    user-select: none;
}
.skeleton-line { height: 12px; margin: 8px 0; }
.skeleton-line.lg { height: 18px; }
.skeleton-block { height: 80px; }
.skeleton-row td .skeleton-line { margin: 4px 0; }
@keyframes jagsShimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
    .skeleton { animation: none; opacity: 0.6; }
}

/* ====================================================================
   Density toggle — reads [data-density] on body. Cookie-backed.
   ==================================================================== */
body[data-density="compact"] .card { padding: 14px 16px; }
body[data-density="compact"] .card + .card { margin-top: 12px; }
body[data-density="compact"] .stat { padding: 14px 16px; }
body[data-density="compact"] .stat .value { font-size: 26px; }
body[data-density="compact"] .stats-grid { gap: 10px; margin-bottom: 14px; }
body[data-density="compact"] table.tbl th,
body[data-density="compact"] table.tbl td { padding: 8px 10px; }
body[data-density="compact"] .field { margin-bottom: 10px; }
body[data-density="compact"] .row-list li { padding: 7px 0; }
body[data-density="compact"] .kv .k,
body[data-density="compact"] .kv .v { padding: 7px 0; }

body[data-density="spacious"] .card { padding: 28px 30px; }
body[data-density="spacious"] .card + .card { margin-top: 24px; }
body[data-density="spacious"] .stats-grid { gap: 22px; margin-bottom: 28px; }
body[data-density="spacious"] .stat { padding: 22px 24px; }
body[data-density="spacious"] table.tbl th,
body[data-density="spacious"] table.tbl td { padding: 14px 16px; }
body[data-density="spacious"] .field { margin-bottom: 18px; }
body[data-density="spacious"] .row-list li { padding: 13px 0; }

/* ====================================================================
   Table polish — sticky first column, row-link hover lift, zebra.
   ==================================================================== */
table.tbl-sticky-first thead th:first-child,
table.tbl-sticky-first tbody td:first-child {
    position: sticky;
    left: 0;
    background: var(--card);
    z-index: 1;
    box-shadow: 1px 0 0 0 var(--border);
}
table.tbl-sticky-first thead th:first-child { background: var(--surface-low); z-index: 3; }
table.tbl-sticky-first tbody tr:hover td:first-child,
table.tbl-sticky-first tbody tr:nth-child(even) td:first-child { background: var(--surface-high); }

table.tbl tbody tr.row-link {
    cursor: pointer;
    transition:
        background var(--motion-fast) var(--ease-out),
        transform var(--motion-fast) var(--ease-out),
        box-shadow var(--motion-fast) var(--ease-out);
}
table.tbl tbody tr.row-link:hover td {
    background: rgba(90,121,165,0.07);
}
table.tbl tbody tr.row-link:focus-within td {
    background: rgba(90,121,165,0.10);
    box-shadow: inset 0 0 0 2px var(--secondary);
}

/* ====================================================================
   Pulse-critical — subtle pulse on grounded/expired badges that should
   draw the eye without being noisy.
   ==================================================================== */
.pulse-critical {
    animation: jagsPulseCritical 2.8s ease-in-out infinite;
}
@keyframes jagsPulseCritical {
    0%, 100% { box-shadow: 0 0 0 0 rgba(184,50,53,0.0); }
    50%      { box-shadow: 0 0 0 4px rgba(184,50,53,0.18); }
}
@media (prefers-reduced-motion: reduce) {
    .pulse-critical { animation: none; }
}

/* ====================================================================
   Tabular numbers — applied to all numeric columns and mono spans
   so figures line up vertically.
   ==================================================================== */
.mono, .cell-mono, .cell-num,
.tbl .cell-mono, .tbl .cell-num,
.stat .value, .feat-val, .av2-kpi .val, .row-list .v.mono,
.kv .v.mono, .dr-preview .v {
    font-feature-settings: 'tnum' 1, 'lnum' 1;
    font-variant-numeric: tabular-nums lining-nums;
}

/* Page header — reusable strip used at the top of many pages. Eyebrow,
   title, subtitle, and right-aligned action buttons. Apple-style: tight
   tracking, generous spacing, no card border. */
.page-header {
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: 16px; flex-wrap: wrap;
    margin: 0 0 22px;
}
.page-header-text {
    min-width: 0;
    display: flex; flex-direction: column; gap: 2px;
}
.page-header-text .eyebrow {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.10em;
    color: var(--muted);
    font-weight: 700;
    margin-bottom: 2px;
}
.page-header-text h1,
.page-header-text h2 {
    margin: 0;
    font-size: 24px;
    font-weight: 700;
    letter-spacing: -0.025em;
    line-height: 1.15;
    color: var(--text-strong);
}
.page-header-text p {
    margin: 4px 0 0;
    font-size: 14px;
    line-height: 1.45;
}
.page-header-actions {
    display: flex; gap: 10px; flex-wrap: wrap;
    align-items: center;
}
@media (max-width: 700px) {
    .page-header-text h1, .page-header-text h2 { font-size: 21px; }
    .page-header-actions .btn { flex: 1 1 auto; justify-content: center; }
}
/* Desktop heading dedupe (2026-08 redesign). The topbar title block —
   role eyebrow / strong h1 / subdued date — is the page's single
   typographic anchor at every size. The premium mobile layer has hidden
   the duplicated in-content .page-header headings <=900px since 2026-07;
   this extends the same proven treatment to desktop, so pages never show
   "Dashboard" twice. Page-authored meta (p) and actions keep rendering. */
@media (min-width: 901px) {
    .content > .page-header .page-header-text .eyebrow,
    .content > .page-header .page-header-text h1,
    .content > .page-header .page-header-text h2 { display: none; }
    .content > .page-header { margin-bottom: 16px; }
}

/* Stat tiles */
.stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 16px;
    margin-bottom: 22px;
}
.stat {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 18px 20px;
    box-shadow: var(--shadow-sm);
    position: relative;
    overflow: hidden;
}
.stat::after {
    /* Subtle navy spotlight on each tile — hints at brand without
       competing with the value. */
    content: "";
    position: absolute; right: -30px; top: -30px;
    width: 120px; height: 120px;
    background: radial-gradient(circle, rgba(39,66,112,0.05), transparent 70%);
    pointer-events: none;
}
.stat .label { font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--muted); font-weight: 600; }
.stat .value { font-size: var(--text-3xl); font-weight: 700; letter-spacing: -0.04em; margin-top: 4px; line-height: 1.1; color: var(--text-strong); font-variant-numeric: tabular-nums; }
.stat .delta { font-size: var(--text-xs); color: var(--muted); margin-top: 4px; }
.stat-warn .value { color: var(--warning); }
.stat-danger .value { color: var(--danger); }
.stat-success .value { color: var(--success); }
/* Interactive tiles — when a .stat or .card is itself a link (e.g. KPI tiles
   that drill into a filtered list), give it clear hover/focus feedback so it
   reads as clickable. Static (non-anchor) tiles are untouched. */
a.stat, a.card {
    color: inherit;
    text-decoration: none;
    cursor: pointer;
    transition:
        box-shadow var(--motion-med) var(--ease-soft),
        border-color var(--motion-med) var(--ease-soft),
        transform var(--motion-med) var(--ease-soft);
}
a.stat:hover, a.card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-md); transform: translateY(-1px); }
a.stat:active, a.card:active { transform: translateY(0); }
a.stat:focus-visible, a.card:focus-visible { outline: none; box-shadow: var(--ring-focus), var(--shadow-md); }
@media (prefers-reduced-motion: reduce) {
    a.stat, a.card { transition: box-shadow var(--motion-med) var(--ease-soft), border-color var(--motion-med) var(--ease-soft); }
    a.stat:hover, a.card:hover { transform: none; }
}

/* Buttons */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 9px 16px;
    border-radius: var(--radius-control);
    font-weight: 600;
    font-size: var(--text-sm);
    letter-spacing: 0.005em;
    border: 1px solid transparent;
    cursor: pointer;
    transition:
        background var(--motion-fast) var(--ease-out),
        color      var(--motion-fast) var(--ease-out),
        transform  var(--motion-fast) var(--ease-out),
        box-shadow var(--motion-fast) var(--ease-out),
        border-color var(--motion-fast) var(--ease-out);
    text-decoration: none;
    line-height: 1;
    font-family: inherit;
}
.btn-primary {
    background: var(--primary);
    color: #fff;
}
/* Achromatic press feedback — subtle scale-down on click matches the
   "Vercel-inspired" interaction language without translating the lift. */
.btn-primary:hover { background: var(--primary-hover); color: #fff; box-shadow: var(--shadow-md); }
.btn-primary:active { transform: scale(0.98); }
.btn-secondary {
    background: var(--secondary);
    color: #fff;
}
.btn-secondary:hover { background: var(--secondary-hover); color: #fff; }
.btn-secondary:active { transform: scale(0.98); }
.btn-ghost {
    background: transparent;
    color: var(--secondary);
    border-color: var(--border);
}
.btn-ghost:hover { background: rgba(39,66,112,0.06); }
.btn-ghost:active { transform: scale(0.98); }
.btn-danger {
    background: var(--danger); color: #fff;
}
.btn-danger:hover { background: #8a1414; color: #fff; }
.btn-danger:active { transform: scale(0.98); }
.btn-sm, .btn-small { padding: 6px 11px; font-size: 13px; border-radius: 10px; }
.btn-block { width: 100%; justify-content: center; }
/* Tonal secondaries used by document/audit pages. Previously undefined
   (rendered as the bare .btn ghost-of-nothing) — given a real soft-tint
   treatment on the semantic tokens. */
.btn-light {
    background: var(--surface-secondary);
    color: var(--text-primary);
    border-color: var(--border-subtle);
}
.btn-light:hover { background: var(--surface-container-high); }
.btn-light:active { transform: scale(0.98); }
.btn-warn {
    background: var(--status-warning-soft);
    color: var(--status-warning);
    border-color: transparent;
}
.btn-warn:hover { background: var(--status-warning); color: var(--text-inverse); }

/* Forms — mobile-first. Defaults are tuned for thumb-tap (44px+ targets,
   16px font to suppress iOS auto-zoom, generous spacing). Desktop scales
   down via @media (min-width: 700px) further down. */
.field { margin-bottom: 16px; }
.field label {
    display: block;
    font-weight: 600;
    font-size: 13px;
    color: var(--text-strong);
    margin-bottom: 6px;
    letter-spacing: 0.005em;
}
.field .hint { font-size: 12px; color: var(--muted); margin-top: 6px; line-height: 1.5; }
.field input[type=text], .field input[type=email], .field input[type=password],
.field input[type=date], .field input[type=time], .field input[type=number], .field input[type=search],
.field input[type=tel], .field input[type=url], .field input[type=datetime-local],
.field select, .field textarea {
    width: 100%;
    padding: 12px 14px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--card);
    /* 16px on mobile suppresses iOS Safari's auto-zoom-on-focus; on desktop
       we drop back to 14.25px for a tighter feel (see media query below). */
    font-size: 16px;
    color: var(--text);
    font-family: inherit;
    line-height: 1.4;
    min-height: 44px;
    box-sizing: border-box;
    -webkit-appearance: none;
    appearance: none;
    transition:
        border-color var(--motion-fast) var(--ease-out),
        box-shadow   var(--motion-fast) var(--ease-out),
        background   var(--motion-fast) var(--ease-out),
        transform    var(--motion-fast) var(--ease-out);
}
/* Custom select chevron so the native control reads as styled rather than
   raw browser-default. Inline SVG keeps it asset-free. */
.field select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%235E6472' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 6 4 4 4-4'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 16px 16px;
    padding-right: 40px;
}
.field input::placeholder, .field textarea::placeholder { color: rgba(94,100,114,0.65); }
.field input:focus, .field select:focus, .field textarea:focus {
    outline: none;
    border-color: var(--secondary);
    box-shadow: var(--ring-focus);
}
.field input:focus-visible:not([readonly]),
.field textarea:focus-visible:not([readonly]) {
    /* Tiny lift — almost imperceptible but feels responsive on touch. */
    transform: translateY(-1px);
}
.field textarea { min-height: 100px; resize: vertical; }
.field input[readonly], .field textarea[readonly] { background: var(--surface-low); cursor: default; }
.field input[disabled], .field textarea[disabled], .field select[disabled] {
    background: var(--surface-low); color: var(--muted); cursor: not-allowed;
}
/* Range inputs and checkboxes/radios shouldn't get the 44px min-height. */
.field input[type=checkbox], .field input[type=radio], .field input[type=range] {
    min-height: 0;
    -webkit-appearance: auto;
    appearance: auto;
    width: auto;
    padding: 0;
}
/* ------------------------------------------------------------------ */
/* Shared 24-hour time control (.time24) — replaces the native time    */
/* scroll-wheel everywhere in Flights / Reservations / Radio. Numeric  */
/* text field + an anchored popover of 30-minute quick chips. The      */
/* popover is position:fixed so it never widens dense tables.          */
/* ------------------------------------------------------------------ */
.time24 { position: relative; display: inline-block; }
.field .time24 { display: block; }
.time24-input {
    padding: 12px 14px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--card);
    font-size: 16px;
    color: var(--text);
    font-family: inherit;
    line-height: 1.4;
    min-height: 44px;
    box-sizing: border-box;
    -webkit-appearance: none;
    appearance: none;
    letter-spacing: 0.02em;
    transition: border-color var(--motion-fast) var(--ease-out),
                box-shadow var(--motion-fast) var(--ease-out);
}
.field .time24-input { width: 100%; }
.time24-input::placeholder { color: rgba(94,100,114,0.6); letter-spacing: normal; }
.time24-input:focus {
    outline: none;
    border-color: var(--secondary);
    box-shadow: var(--ring-focus);
}
.time24-input.time24-input-invalid {
    border-color: var(--danger);
    box-shadow: 0 0 0 3px rgba(184,50,53,0.16);
}
.time24-input[disabled] {
    background: var(--surface-low);
    color: var(--muted);
    cursor: not-allowed;
}
.time24-preview { display: block; margin-top: 5px; min-height: 1em; }
.rsv-time-invalid, .time24-invalid { color: var(--danger) !important; }

.time24-pop {
    position: fixed;
    z-index: 1200;
    width: 248px;
    max-width: calc(100vw - 16px);
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 14px;
    box-shadow: 0 14px 38px rgba(6,6,11,0.18);
    padding: 10px;
    box-sizing: border-box;
}
.time24-pop-bar {
    display: flex;
    gap: 8px;
    margin-bottom: 8px;
}
.time24-pop-bar .time24-chip { flex: 1; }
.time24-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 6px;
    max-height: 232px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}
.time24-chip {
    appearance: none;
    -webkit-appearance: none;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-size: 14px;
    font-variant-numeric: tabular-nums;
    padding: 10px 0;
    min-height: 40px;
    border-radius: 9px;
    cursor: pointer;
    text-align: center;
    transition: background var(--motion-fast) var(--ease-out),
                border-color var(--motion-fast) var(--ease-out);
}
.time24-chip:hover { background: var(--surface-low); border-color: var(--secondary); }
.time24-chip:active { transform: translateY(1px); }
.time24-chip-on {
    background: var(--secondary);
    border-color: var(--secondary);
    color: #FFF;
    font-weight: 600;
}
.time24-chip-accent {
    background: var(--secondary);
    border-color: var(--secondary);
    color: #FFF;
    font-weight: 600;
}
.time24-chip-ghost { color: var(--muted); }
@media (max-width: 560px) {
    .time24-pop { width: 268px; }
    .time24-chip { font-size: 15px; min-height: 44px; }
}

/* Inline checkbox/radio rows — checkbox + label on one line, generous touch. */
.field-check {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    cursor: pointer;
    transition: border-color var(--motion-fast) var(--ease-out), background var(--motion-fast) var(--ease-out);
    min-height: 44px;
}
.field-check:hover { border-color: var(--border-strong); background: var(--surface-low); }
.field-check input[type=checkbox],
.field-check input[type=radio] {
    width: 18px; height: 18px; flex: 0 0 18px;
    accent-color: var(--secondary);
    margin: 0;
}
.field-check .label-text { flex: 1 1 auto; font-size: 14px; color: var(--text-strong); font-weight: 500; line-height: 1.4; }
.field-check .label-sub { display: block; font-size: 12px; color: var(--muted); margin-top: 2px; font-weight: 400; }
/* Desktop tweaks — slightly tighter font/padding once we know the user is
   on a pointer device, but keep the touch-friendly defaults intact below
   that threshold. */
@media (min-width: 700px) {
    .field input[type=text], .field input[type=email], .field input[type=password],
    .field input[type=date], .field input[type=time], .field input[type=number], .field input[type=search],
    .field input[type=tel], .field input[type=url], .field input[type=datetime-local],
    .field select, .field textarea {
        font-size: 14.25px;
        padding: 10px 12px;
        min-height: 40px;
    }
    .field { margin-bottom: 14px; }
    .field label { font-size: var(--text-sm); }
}
/* Validation states — apply via .field.has-error / .field.has-success
   classes set server-side, or via :invalid styling on user-blurred inputs.
   Keep gentle so the form doesn't feel angry. */
.field.has-error input,
.field.has-error select,
.field.has-error textarea {
    border-color: rgba(184,50,53,0.55);
    background: rgba(184,50,53,0.03);
}
.field.has-error input:focus,
.field.has-error select:focus,
.field.has-error textarea:focus {
    border-color: var(--danger);
    box-shadow: 0 0 0 3px rgba(184,50,53,0.18);
}
.field.has-error .hint { color: var(--danger); }
.field.has-success input:not(:focus) {
    border-color: rgba(74,103,51,0.45);
}
.field .hint.error { color: var(--danger); }
.field-row {
    display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap;
}
.field-row .field { flex: 1 1 200px; margin-bottom: 0; }
/* Required indicator — pages can opt in by adding .required to the label. */
.field label.required::after {
    content: " *";
    color: var(--danger);
    font-weight: 700;
}
/* Form grid — mobile-first single column, expanding to 2-up at tablet
   and using auto-fit at desktop for forms that pack many fields. */
.form-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 12px;
}
@media (min-width: 700px) {
    .form-grid { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; }
}
/* Span 2 columns inside a form-grid (on desktop). */
.form-grid .field.span-2 { grid-column: span 2; }
@media (max-width: 700px) {
    .form-grid .field.span-2 { grid-column: span 1; }
}

.form-actions {
    display: flex; gap: 10px; flex-wrap: wrap;
    margin-top: 18px;
}
.form-actions .btn { flex: 1 1 auto; justify-content: center; min-height: 44px; }
@media (min-width: 700px) {
    .form-actions .btn { flex: 0 0 auto; min-height: 0; }
}
/* Sticky form actions on long forms — wrap your action row in
   .form-actions.sticky to lock it to the bottom of the viewport. */
.form-actions.sticky {
    position: sticky;
    bottom: 0;
    margin: 16px -16px -16px;
    padding: 14px 16px max(14px, env(safe-area-inset-bottom, 0px));
    background: rgba(var(--glass-rgb), 0.96);
    backdrop-filter: blur(8px) saturate(160%);
    -webkit-backdrop-filter: blur(8px) saturate(160%);
    border-top: 1px solid var(--border);
    z-index: 5;
}
@media (min-width: 700px) {
    .form-actions.sticky { margin: 16px -22px -22px; padding: 14px 22px; }
}
/* On mobile, lift sticky-actions above the bottom-nav bar so the submit
   button is always reachable but never under the bottom-nav. */
@media (max-width: 900px) {
    .form-actions.sticky { bottom: calc(var(--mobile-bottom-nav-footprint) + 8px); border-radius: var(--radius); border: 1px solid var(--border); margin: 16px 0 0; box-shadow: var(--shadow-md); }
}
@media print {
    .form-actions.sticky { position: static; background: none; backdrop-filter: none; box-shadow: none; }
}

/* Form-card — wraps related .field blocks in a consistent surface so a
   long form reads as grouped sections. Combine with .form-section-head
   for an Apple-Settings-style segmented form. Cards stack vertically
   with consistent gaps. */
.form-stack { display: flex; flex-direction: column; gap: 16px; }
.form-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 18px;
    box-shadow: var(--shadow-sm);
}
@media (min-width: 700px) {
    .form-card { padding: 22px 24px; }
}
.form-card > .form-section-head:first-child { margin-top: 0; }

/* Floating-style label hint — small caps badge above a key field. */
.field-hint-pill {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--surface-low);
    border: 1px solid var(--border);
    color: var(--muted);
    font-size: 10.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-left: 6px;
    vertical-align: middle;
}

/* Form-section header — a.k.a. a fieldset divider inside a long form. */
.form-section-head {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 12px;
    margin: 22px 0 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border);
    flex-wrap: wrap;
}
.form-section-head:first-child { margin-top: 0; }
.form-section-head h3 {
    margin: 0;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--text-strong);
}
.form-section-head .muted { font-size: 12.5px; }

/* Badges */
.badge {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.012em;
    line-height: 1.4;
    white-space: nowrap;
    border: 1px solid transparent;
}
.badge-success { background: var(--status-success-soft); color: var(--status-success-ink); }
.badge-warn    { background: var(--status-warning-soft); color: var(--status-warning-ink); }
.badge-danger  { background: var(--status-danger-soft); color: var(--status-danger-ink); }
.badge-info    { background: var(--status-info-soft); color: var(--status-info-ink); }
.badge-neutral { background: rgba(94, 100, 114, 0.12); color: var(--muted); }

/* ---------------------------------------------------------------
   Senior title badges (Accountable Manager, Chief Pilot, Chief
   Engineer, Safety Officer, Admin, System Admin).

   These chips display authority / responsibility next to the role
   badge. They never grant access — they're a visual cue only. Senior
   chips lean on a quiet amber/gold for "authority", admin chips
   borrow the danger tone to match the role badge, and non-senior
   titles fall through to the standard `badge-info` look.
   --------------------------------------------------------------- */
.jags-title-badges {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
}
.jags-title-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.012em;
    line-height: 1.4;
    white-space: nowrap;
    border: 1px solid transparent;
    text-decoration: none;
}
.jags-title-badge-ico {
    display: inline-block;
    flex: 0 0 auto;
    vertical-align: middle;
}
.jags-title-badge-label { display: inline-block; }
.jags-title-badge-compact { padding: 3px 6px; }
.jags-title-badge-info {
    background: rgba(90, 121, 165, 0.14);
    color: var(--status-info-ink);
    border-color: rgba(90, 121, 165, 0.22);
}
.jags-title-badge-admin {
    background: rgba(184, 50, 53, 0.10);
    color: var(--status-danger-ink);
    border-color: rgba(184, 50, 53, 0.28);
}
.jags-title-badge-senior {
    background: rgba(182, 136, 58, 0.13);
    color: var(--status-warning-ink);
    border-color: rgba(182, 136, 58, 0.32);
}
.jags-title-badge-safety {
    background: rgba(216, 181, 109, 0.18);
    color: var(--status-warning-ink);
    border-color: rgba(216, 181, 109, 0.40);
}
a.jags-title-badge:hover { filter: brightness(0.97); }
a.jags-title-badge:focus-visible {
    outline: none;
    box-shadow: var(--ring-focus);
}
.jags-title-badge-more {
    font-size: var(--text-xs);
    padding: 3px 9px;
}

/* Visually-hidden helper for compact chips that keep the label
   accessible to screen readers without showing it on screen. */
.jags-visually-hidden {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Topbar / user-menu title chip — sits to the left of the avatar and
   is a quiet visual reinforcement of senior authority. Hidden on
   narrow widths so the topbar doesn't crowd. */
.user-menu-button .jags-title-badge,
.topbar .jags-title-badge {
    padding: 2px 8px;
    font-size: 11px;
}
@media (max-width: 900px) {
    .user-menu-button .jags-title-badge-label { display: none; }
    .user-menu-button .jags-title-badge { padding: 3px 6px; }
}
@media (max-width: 700px) {
    .topbar .user-menu-button .jags-title-badge { display: none; }
}

/* ----- Feature 09 — Daily Report verification / publish / amendment.
   Subtle 4px left-border accent on the status banner so the saved
   Daily Report makes its workflow state visible without painting a
   loud full-card background. The banner reuses the existing alert
   colours; this rule only adds the feature-specific accent. */
.dr-workflow-banner { border-left: 4px solid currentColor; }

/* Hero-friendly status badges — readable on the dark JAGS gradient hero.
   The standard badge variants above are designed for light surfaces and
   become unreadable on .card-hero. Use these inside hero cards instead. */
.hero-status-badge {
    display: inline-flex; align-items: center;
    padding: 5px 12px;
    border-radius: 999px;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    border: 1px solid rgba(255, 255, 255, 0.22);
    background: rgba(255, 255, 255, 0.10);
    color: #fff;
    line-height: 1.4;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}
.hero-status-serviceable {
    background: rgba(122, 198, 96, 0.22);
    color: #DCF3CB;
    border-color: rgba(122, 198, 96, 0.55);
}
.hero-status-grounded {
    background: rgba(231, 95, 95, 0.25);
    color: #FFD3D3;
    border-color: rgba(231, 95, 95, 0.55);
}
.hero-status-maintenance,
.hero-status-inspection_required {
    background: rgba(216, 181, 109, 0.28);
    color: #FAE5B5;
    border-color: rgba(216, 181, 109, 0.55);
}
.hero-status-inactive {
    background: rgba(255, 255, 255, 0.10);
    color: rgba(255, 255, 255, 0.85);
    border-color: rgba(255, 255, 255, 0.25);
}

/* Hero-friendly warning chips — for the small contextual flags shown in the
   aircraft profile hero (insp due soon, CofA expired, etc.). */
.hero-warning-chip {
    display: inline-flex; align-items: center;
    padding: 4px 10px;
    border-radius: 999px;
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: 0.04em;
    background: rgba(255, 255, 255, 0.14);
    border: 1px solid rgba(255, 255, 255, 0.22);
    color: #fff;
}
.hero-warning-chip.success {
    background: rgba(122, 198, 96, 0.22);
    color: #DCF3CB;
    border-color: rgba(122, 198, 96, 0.50);
}
.hero-warning-chip.warn {
    background: rgba(216, 181, 109, 0.28);
    color: #FAE5B5;
    border-color: rgba(216, 181, 109, 0.50);
}
.hero-warning-chip.danger {
    background: rgba(231, 95, 95, 0.28);
    color: #FFD3D3;
    border-color: rgba(231, 95, 95, 0.50);
}
.hero-warning-chip.info {
    background: rgba(255, 255, 255, 0.18);
    color: #FFFFFF;
    border-color: rgba(255, 255, 255, 0.30);
}
.hero-warning-chip.neutral {
    background: rgba(255, 255, 255, 0.10);
    color: rgba(255, 255, 255, 0.85);
    border-color: rgba(255, 255, 255, 0.22);
}

/* Tables */
.table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: var(--card);
    box-shadow: var(--shadow-sm);
    scrollbar-width: thin;
    scrollbar-color: rgba(39,66,112,0.30) transparent;
}
.table-wrap::-webkit-scrollbar { height: 8px; }
.table-wrap::-webkit-scrollbar-track { background: transparent; }
.table-wrap::-webkit-scrollbar-thumb { background: rgba(39,66,112,0.25); border-radius: 8px; }
.table-wrap::-webkit-scrollbar-thumb:hover { background: rgba(39,66,112,0.45); }

table.tbl { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
table.tbl th, table.tbl td {
    padding: 12px 14px;
    text-align: left;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
    line-height: 1.42;
}
table.tbl th {
    background: linear-gradient(180deg, #F8FAFD 0%, #F1F4FA 100%);
    font-weight: 600;
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
    color: var(--muted-strong);
    position: sticky; top: 0;
    white-space: nowrap;
    border-bottom: 1px solid var(--border);
}
table.tbl tr:last-child td { border-bottom: none; }
table.tbl tr:hover td { background: var(--surface-high); }

/* Denser variant for fleet-style tables that already pack a lot of columns. */
table.tbl-compact { font-size: 13px; }
table.tbl-compact th, table.tbl-compact td { padding: 9px 10px; }
table.tbl-compact th { font-size: 11px; }

/* Reusable cell helper classes — keep cells from blowing up rows. */
.tbl td.cell-mono   { font-family: "SF Mono", ui-monospace, Menlo, Consolas, monospace; white-space: nowrap; }
.tbl td.cell-num    { white-space: nowrap; text-align: right; }
.tbl td.cell-date   { white-space: nowrap; }
.tbl td.cell-narrow { width: 1%; white-space: nowrap; }
.tbl td.cell-actions {
    text-align: right;
    white-space: nowrap;
    width: 1%;
}
.tbl td.cell-actions .btn + .btn { margin-left: 4px; }
.tbl td.cell-remarks {
    max-width: 220px;
    color: var(--muted);
    font-size: 12.5px;
    line-height: 1.45;
}
.tbl td.cell-remarks .truncate {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
    word-break: break-word;
}

/* Reusable date pill — replaces inline padding/radius styling on date spans. */
.date-chip {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 6px;
    white-space: nowrap;
    font-size: 12.5px;
    line-height: 1.5;
}
.date-chip.muted { color: var(--muted); }

/* Sub-line text under primary table cell content. */
.tbl .sub-line { font-size: 11.5px; color: var(--muted); margin-top: 2px; line-height: 1.35; }
.tbl .sub-line.tight { margin-top: 1px; }

/* Grounded indicator pip shown next to the registration. */
.reg-pip { display:inline-block; width:8px; height:8px; border-radius:50%; background:var(--danger); flex:0 0 8px; }

/* Daily report table */
.dr-wrap { background: var(--card); color: var(--text); border-radius: var(--radius); border: 1px solid var(--border); box-shadow: var(--shadow-md); overflow: hidden; }
.dr-header {
    background: var(--grad-jags);
    color: #fff;
    padding: 28px 32px;
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: 16px;
}
.dr-header .title { display: flex; align-items: center; gap: 18px; }
.dr-header .title img { width: 84px; height: 84px; border-radius: 12px; background: #FFFFFF; padding: 8px; box-shadow: 0 6px 18px rgba(0,0,0,0.18); }
.dr-header h1 { margin: 0; font-size: 24px; letter-spacing: -0.03em; color: #fff; font-weight: 700; }
.dr-header .subtitle { opacity: 0.85; margin-top: 2px; font-size: 13px; }
.dr-header .meta { font-size: 14px; text-align: right; }
.dr-header .meta strong { display: block; font-size: 16px; }
.dr-toolbar { padding: 14px 24px; border-bottom: 1px solid var(--border); background: var(--surface-low); display: flex; gap: 12px; flex-wrap: wrap; align-items: center; justify-content: space-between; }

.dr-scroll { overflow-x: auto; }
table.dr {
    width: 100%; min-width: 1400px;
    border-collapse: collapse; font-size: 12.5px;
    background: var(--card); color: var(--text);
}
table.dr th, table.dr td {
    padding: 8px 10px;
    border: 1px solid var(--border);
    vertical-align: top;
    line-height: 1.35;
}
table.dr th {
    background: linear-gradient(180deg, var(--surface-container) 0%, var(--surface-container-high) 100%);
    text-transform: uppercase;
    font-size: 11px;
    letter-spacing: 0.04em;
    color: var(--muted-strong);
    text-align: center;
}
table.dr tbody td.reg-cell {
    background: var(--surface-low);
    font-weight: 600;
}
table.dr tbody td.reg-cell .reg { font-size: 14px; color: var(--primary); display: block; margin-bottom: 2px; }
table.dr tbody td.reg-cell .meta-line { font-size: 11px; color: var(--muted); font-weight: 500; }

.cell-list { list-style: none; margin: 0; padding: 0; }
.cell-list li { padding: 5px 8px; border-radius: 6px; margin-bottom: 4px; background: var(--surface-low); }
.cell-list li:last-child { margin-bottom: 0; }
.cell-tags { font-size: 10.5px; color: var(--muted); margin-top: 2px; }
.cell-line { padding: 3px 0; }
.hr-label { display: inline-block; min-width: 50px; font-size: 10px; text-transform: uppercase; color: var(--muted); letter-spacing: 0.05em; }

/* Cell color states */
.cell-warn      { background: rgba(90,121,165,0.16) !important; color: #1F3F73; font-weight: 600; }
.cell-green     { background: rgba(74,103,51,0.18) !important; color: #2C4A1B; font-weight: 600; }
.cell-major     { background: rgba(216,181,109,0.20) !important; color: var(--status-warning-ink); font-weight: 600; }
.cell-outstanding{ background: rgba(184,50,53,0.13) !important; color: var(--status-danger-ink); font-weight: 600; }
.cell-coa-soon  { background: rgba(80,180,90,0.20) !important; color: #245C28; font-weight: 600; }
.cell-cmr-soon  { background: rgba(155,90,200,0.18) !important; color: #5C2880; font-weight: 600; }
.cell-expired   { background: rgba(184,50,53,0.20) !important; color: var(--status-danger-ink); font-weight: 700; }

/* Daily Report — inline keyword emphasis applied by dr_snapshot_format_inline().
   Used inside snapshot rows where row_json colour classes are absent and to
   match the visual hierarchy of the paper Daily Report. Subtle: bold colour
   only, no background, so the cell-level tints stay readable. */
.dr-kw          { font-weight: 700; letter-spacing: 0.01em; }
.dr-kw-critical { color: var(--status-danger-ink); }
.dr-kw-warn     { color: var(--status-warning-ink); }
.dr-kw-info     { color: #1F3F73; }

/* Legend / key */
.legend { display: flex; flex-wrap: wrap; gap: 10px; padding: 12px 24px; background: var(--surface-low); border-top: 1px solid var(--border); }
.legend .swatch { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; border-radius: 999px; font-size: 12px; }
.legend .dot { width: 12px; height: 12px; border-radius: 4px; display: inline-block; }

/* ----------------------------------------------------------------------
 * Daily Report scoped layout — keeps cells compact so Combined Board /
 * Compliance Board detail can never spill into the printed Daily Report.
 * Scoped to .daily-report-table so other tables (Compliance Board,
 * Aircraft profile) are unaffected.
 * -------------------------------------------------------------------- */
.daily-report-table { table-layout: fixed; width: 100%; }
.daily-report-table th,
.daily-report-table td {
    vertical-align: top;
    line-height: 1.25;
    overflow-wrap: break-word;
    word-break: normal;
}
.daily-report-table .dr-cell-list { margin: 0; padding: 0; list-style: none; }
.daily-report-table .dr-cell-list li {
    padding: 3px 6px;
    margin-bottom: 3px;
    border-radius: 5px;
    background: var(--surface-low);
    font-size: 11.5px;
    line-height: 1.25;
}
.daily-report-table .dr-cell-list li:last-child { margin-bottom: 0; }
.daily-report-table .dr-cell-list li strong { font-weight: 600; }
.daily-report-table .cell-tags { font-size: 10px; color: var(--muted); margin-top: 1px; }
.daily-report-table .cell-line { padding: 2px 0; font-size: 11.5px; line-height: 1.25; }

/* On screen, cap each list-type cell to a few visible lines so a single
 * row can never blow the table out vertically. Print restores full height
 * so the +N overflow note is hidden but every visible row still prints. */
.daily-report-table td .dr-cell-list,
.daily-report-table td .cell-list { max-height: 9em; overflow: hidden; }
.daily-report-table .daily-report-extra-note {
    font-size: 10.5px;
    margin-top: 2px;
    font-style: italic;
}

@media print {
    .daily-report-table { font-size: 9pt; }
    .daily-report-table td .dr-cell-list,
    .daily-report-table td .cell-list { max-height: none; overflow: visible; }
    .daily-report-table .daily-report-extra-note { display: none; }
}

/* Auth screens */
.auth-page {
    min-height: 100vh;
    display: grid;
    grid-template-columns: 1fr 1fr;
}
.auth-side {
    background: var(--grad-jags);
    color: #fff;
    padding: 52px 48px;
    display: flex; flex-direction: column; justify-content: space-between;
    position: relative; overflow: hidden;
}
.auth-side::before {
    content: ""; position: absolute; right: -120px; top: -120px;
    width: 400px; height: 400px; border-radius: 50%;
    background: radial-gradient(circle, rgba(255,255,255,0.18), transparent 65%);
}
.auth-side::after {
    content: ""; position: absolute; left: -100px; bottom: -100px;
    width: 350px; height: 350px; border-radius: 50%;
    background: radial-gradient(circle, rgba(255,255,255,0.10), transparent 65%);
}
.auth-side .brand { display: flex; flex-direction: column; gap: 10px; position: relative; z-index: 1; max-width: 220px; }
.auth-side .brand img { display: block; width: 100%; max-width: 200px; height: 120px; object-fit: contain; border-radius: 14px; background: #FFFFFF; padding: 14px; box-shadow: 0 8px 24px rgba(0,0,0,0.18); }
.auth-side .brand-sub { font-size: 11px; opacity: 0.75; text-transform: uppercase; letter-spacing: 0.12em; text-align: center; }
.auth-side .pitch h1 { font-size: 38px; letter-spacing: -0.04em; line-height: 1.1; margin: 0 0 14px; color: #fff; font-weight: 700; }
.auth-side .pitch p { font-size: 16px; opacity: 0.85; max-width: 380px; margin: 0; color: #fff; }
.auth-side .footnote { font-size: 12px; opacity: 0.7; position: relative; z-index: 1; }
.auth-form-wrap {
    display: flex; align-items: center; justify-content: center; padding: 40px;
    background: var(--bg);
}
.auth-card {
    width: 100%; max-width: 420px;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 36px 32px;
    box-shadow: var(--shadow-lg);
}
.auth-card h2 { margin: 0 0 4px; font-size: 24px; letter-spacing: -0.01em; }
.auth-card .lede { color: var(--muted); margin: 0 0 22px; font-size: 14px; }

/* Department portal layer — branding chips, hero accents, chooser cards. */
.auth-eyebrow {
    display: inline-block;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    font-size: 11px;
    font-weight: 600;
    background: rgba(255,255,255,0.16);
    padding: 4px 10px;
    border-radius: 999px;
    margin-bottom: 14px;
    position: relative; z-index: 1;
}
.auth-portal-chip {
    display: inline-block;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    font-size: 11px;
    font-weight: 700;
    color: var(--secondary);
    background: rgba(39, 66, 112, 0.10);
    border: 1px solid rgba(39, 66, 112, 0.18);
    padding: 4px 10px;
    border-radius: 999px;
    margin-bottom: 12px;
}
/* Brand fallback — visible only when the <img> onerror fires. Keeps the
   auth side panel from ever showing an empty white rounded card. Renders a
   JAGS Aviation textmark via ::before / ::after so the fallback is a real
   brand mark, not a blank box, even on the rare hosts where neither the
   portal hero nor assets/jags-logo.png can be loaded. Layout uses padding +
   block pseudo-elements (not flex) so existing onerror handlers that set
   display:block continue to render correctly without per-page changes. */
.auth-side .brand-fallback {
    width: 100%; max-width: 200px;
    min-height: 120px;
    box-sizing: border-box;
    border-radius: 14px;
    background: var(--card);
    border: 1px solid rgba(255,255,255,0.18);
    box-shadow: 0 8px 24px rgba(0,0,0,0.18);
    padding: 30px 14px;
    text-align: center;
    color: var(--primary);
    font-family: var(--font-display);
    line-height: 1.05;
}
.auth-side .brand-fallback::before {
    content: "JAGS";
    display: block;
    font-size: 30px;
    font-weight: 800;
    letter-spacing: 0.04em;
    color: var(--primary);
}
.auth-side .brand-fallback::after {
    content: "AVIATION";
    display: block;
    margin-top: 6px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.32em;
    color: var(--secondary);
}
.auth-portal-switch {
    margin-top: 18px;
    text-align: center;
    font-size: 13px;
    color: var(--muted);
}
.auth-portal-switch a { font-weight: 600; }

/* Pills shown on the generic login screen — quick jump to a department. */
.auth-portal-grid {
    display: flex; flex-wrap: wrap; justify-content: center;
    gap: 6px; margin-top: 10px;
}
.auth-portal-pill {
    display: inline-block;
    padding: 6px 12px;
    font-size: 12.5px;
    font-weight: 600;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--card);
    color: var(--secondary);
    text-decoration: none;
    transition: transform .15s ease, box-shadow .15s ease, background .15s ease, border-color .15s ease;
}
.auth-portal-pill:hover {
    background: var(--secondary);
    color: #fff;
    border-color: var(--secondary);
    transform: translateY(-1px);
    box-shadow: var(--shadow-sm);
}

/* Cards shown on the generic register screen — pick a department first. */
.auth-portal-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 10px;
    margin: 6px 0 18px;
}
.auth-portal-card {
    display: flex; flex-direction: column; gap: 4px;
    padding: 14px 16px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: var(--card);
    color: var(--text-strong, #0E0E12);
    text-decoration: none;
    transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.auth-portal-card:hover {
    transform: translateY(-2px);
    border-color: var(--secondary);
    box-shadow: var(--shadow-md);
}
.auth-portal-card-label { font-weight: 700; font-size: 14px; color: var(--primary); }
.auth-portal-card-sub   { font-size: 12px; color: var(--muted); line-height: 1.45; }

/* Per-department hero tints — subtle accent bands layered above the gradient. */
.auth-page.auth-portal-tr          .auth-side { background: linear-gradient(135deg, #0F2A4F 0%, #274270 55%, #5A79A5 100%); }
.auth-page.auth-portal-operations  .auth-side { background: linear-gradient(135deg, #142A55 0%, #1F4D8F 60%, #4F86C5 100%); }
.auth-page.auth-portal-radio       .auth-side { background: linear-gradient(135deg, #1A2848 0%, #3D2E66 60%, #6F5BA5 100%); }
.auth-page.auth-portal-maintenance .auth-side { background: linear-gradient(135deg, #1F2A2E 0%, #2C5560 60%, #5C97A5 100%); }
.auth-page.auth-portal-pilot       .auth-side { background: linear-gradient(135deg, #112447 0%, #1F3F75 55%, #4670B0 100%); }
.auth-page.auth-portal-viewer      .auth-side { background: linear-gradient(135deg, #1B1F2A 0%, #3A3F55 60%, #6E7799 100%); }
.auth-page.auth-portal-admin       .auth-side { background: linear-gradient(135deg, #150F2E 0%, #2C1F55 60%, #5C4FA5 100%); }

/* Mobile hero — image hides on very small screens, copy stays. */
@media (max-width: 680px) {
    .auth-side {
        padding: 28px 22px;
        min-height: 220px;
    }
    .auth-side .brand img,
    .auth-side .brand-fallback { max-width: 140px; }
    .auth-side .pitch h1 { font-size: 24px; }
    .auth-side .pitch p  { font-size: 14px; }
    .auth-form-wrap { padding: 22px 16px; }
    .auth-card { padding: 24px 20px; border-radius: var(--radius); }
    .auth-portal-cards { grid-template-columns: 1fr; }
}
@media (max-width: 420px) {
    .auth-side .footnote { display: none; }
    .auth-side { padding: 22px 18px; min-height: 180px; }
    .auth-side .brand img,
    .auth-side .brand-fallback { max-width: 110px; }
}

/* Alerts / flash */
.alert {
    padding: 12px 14px;
    border-radius: var(--radius-sm);
    margin-bottom: 16px;
    font-size: var(--text-sm);
    line-height: var(--line-relaxed);
    border: 1px solid transparent;
    display: flex; align-items: flex-start; gap: 10px;
}
.alert > .jags-icon { margin-top: 2px; flex: 0 0 18px; }
.alert-info    { background: rgba(90,121,165,0.10); color: var(--status-info-ink); border-color: rgba(90,121,165,0.22); }
.alert-success { background: rgba(74,103,51,0.10);  color: var(--status-success-ink); border-color: rgba(74,103,51,0.22); }
.alert-warn    { background: rgba(216,181,109,0.16); color: var(--status-warning-ink); border-color: rgba(216,181,109,0.32); }
.alert-danger  { background: rgba(184,50,53,0.10);  color: var(--status-danger-ink); border-color: rgba(184,50,53,0.22); }

/* Aircraft status card */
.ac-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; }
.ac-card {
    background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
    padding: 18px; box-shadow: var(--shadow-sm); position: relative; overflow: hidden;
}
.ac-card .reg {
    font-size: 22px; font-weight: 700; letter-spacing: -0.02em;
    color: var(--primary); margin: 0 0 4px;
}
.ac-card .model { color: var(--muted); margin: 0 0 12px; font-size: 13px; }
.ac-card .meta-row { display: flex; justify-content: space-between; padding: 4px 0; font-size: 13px; }
.ac-card .meta-row .lbl { color: var(--muted); }
.ac-card .actions { display: flex; gap: 8px; margin-top: 14px; }

/* Profile readout — Apple Settings rhythm. Pairs of .k / .v render as
   rows with a thin divider between them. Default layout is two-column
   (label left, value right). When .kv is wrapped in a card it picks up
   tabular-nums + edge-to-edge dividers automatically. */
.kv {
    display: grid;
    grid-template-columns: minmax(120px, 200px) 1fr;
    gap: 0 18px;
    font-size: var(--text-base);
}
.kv .k {
    color: var(--muted);
    font-size: var(--text-sm);
    padding: 10px 0;
    border-top: 1px solid var(--border);
    align-self: center;
}
.kv .v {
    font-weight: 500;
    color: var(--text-strong);
    padding: 10px 0;
    border-top: 1px solid var(--border);
    align-self: center;
    word-break: break-word;
}
.kv > .k:first-of-type, .kv > .v:nth-of-type(1) { border-top: none; padding-top: 0; }
/* If .kv is the first thing inside a card, drop the lead spacing. */
.card > .kv:first-child > .k:first-of-type,
.card > .kv:first-child > .v:nth-of-type(1) { padding-top: 4px; }

/* Aircraft profile hero image — small framed rectangle that sits inside
   the dark .card-hero gradient on aircraft_view.php. Scoped to that one
   surface; do not reuse on lighter cards. */
.av-hero-img {
    position: relative;
    flex: 0 0 auto;
    width: 280px;
    aspect-ratio: 16 / 9;
    border-radius: 12px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.18);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
}
.av-hero-img img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: center;
}
.av-hero-img-fallback {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    text-align: center;
    color: rgba(255, 255, 255, 0.85);
    font-size: 13px;
    padding: 14px;
}
.av-hero-img-fallback .av-hero-img-link {
    color: #fff;
    text-decoration: underline;
    font-size: 12.5px;
    opacity: 0.9;
}
.av-hero-img-fallback .av-hero-img-link:hover { opacity: 1; }
@media (max-width: 700px) {
    .av-hero-img { width: 100%; }
}
@media print {
    .av-hero-img { display: none !important; }
}

/* ----------------------------------------------------------------------
   Aircraft view hero polish
   Layout, type and image-frame refinement for the aircraft profile hero.
   Every selector is scoped under .av-hero-card (added to the existing
   .card.card-hero on aircraft_view.php) or prefixed .av-, so nothing
   leaks to other pages. Print parity is preserved by the @media print
   rule at the end of this block. Reuses .hero-warning-chip and
   .hero-status-badge for chips and the serviceability badge unchanged.
   ---------------------------------------------------------------------- */
.av-hero-card {
    /* Locally-scoped tokens. Kept on the hero card so the dark gradient
       parent gets a stable inner-frame stage that does not change with
       the gradient stops.

       The frame background is a layered radial: a soft centre spotlight
       over a vignetted dark base. White-background cutouts read as
       intentional because the corners are visibly darker than the white;
       photos sit framed without the wash competing with the subject. */
    --av-hero-frame-bg:
        radial-gradient(
            ellipse 78% 62% at 50% 44%,
            rgba(255, 255, 255, 0.08) 0%,
            rgba(255, 255, 255, 0.02) 38%,
            transparent 72%
        ),
        radial-gradient(
            ellipse at center,
            rgba(13, 17, 38, 0.55) 0%,
            rgba(6, 8, 22, 0.78) 100%
        );
    --av-hero-frame-border:   rgba(255, 255, 255, 0.14);
    --av-hero-frame-pad:      clamp(6px, 1vw, 12px);
    --av-hero-frame-vignette: inset 0 0 36px rgba(0, 0, 0, 0.28);
    --av-hero-frame-max:      560px;

    /* Image zoom: scales the rendered image inside the frame so cutouts
       with lots of white canvas around the aircraft look closer in.
       overflow:hidden on the frame clips the excess whitespace. Tune up
       (1.4-1.5) if most uploads are white-padded cutouts; tune down
       (1.1-1.15) if most uploads are tight natural photos. */
    --av-hero-image-zoom: 1.35;

    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, auto) minmax(0, auto);
    grid-template-areas: "title image actions";
    align-items: start;
    column-gap: 24px;
    row-gap: 16px;
}
.av-hero-card .av-hero-title              { grid-area: title;   min-width: 0; }
.av-hero-card .av-hero-img,
.av-hero-card .av-hero-image-frame        { grid-area: image; }
.av-hero-card .av-hero-actions            { grid-area: actions; display: flex; flex-direction: column; align-items: flex-end; gap: 12px; min-width: 0; }

/* Title block typography */
.av-hero-card .av-hero-eyebrow {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.65);
    margin: 0 0 4px;
}
.av-hero-card .av-hero-title-text {
    margin: 0 0 6px;
    font-size: clamp(24px, 4vw, 36px);
    font-weight: 700;
    letter-spacing: -0.01em;
    line-height: 1.1;
    color: #fff;
    font-feature-settings: 'tnum' 1, 'lnum' 1;
    overflow-wrap: break-word;
    word-break: break-word;
}
.av-hero-card .av-hero-subtype {
    margin: 0 0 12px;
    font-size: 16px;
    font-weight: 400;
    line-height: 1.4;
    color: rgba(255, 255, 255, 0.85);
    overflow-wrap: break-word;
}
.av-hero-card .av-hero-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.av-hero-card .av-hero-inactive { margin-top: 8px; }

/* Image frame: 16:10 aspect, layered radial stage, hairline border,
   inset corner vignette. Padding scales with viewport so the aircraft
   takes more of the frame on larger screens. Overrides the 16:9 /
   280px / glass treatment of the older .av-hero-img rules above for
   this region only. */
.av-hero-card .av-hero-image-frame {
    width: 100%;
    max-width: var(--av-hero-frame-max);
    aspect-ratio: 16 / 10;
    padding: var(--av-hero-frame-pad);
    background: var(--av-hero-frame-bg);
    border: 1px solid var(--av-hero-frame-border);
    border-radius: var(--radius);
    box-shadow: var(--av-hero-frame-vignette);
    overflow: hidden;
    position: relative;
}
.av-hero-card .av-hero-image,
.av-hero-card .av-hero-image-frame > img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: center;
    transform: scale(var(--av-hero-image-zoom));
    transform-origin: center;
    will-change: transform;
}
/* Fallback fills the content area inside the frame padding so the
   placeholder occupies the same space as a real image. Quiet aircraft
   glyph + label, no broken-image affordance. */
.av-hero-card .av-hero-img-fallback {
    inset: var(--av-hero-frame-pad);
    padding: 0;
    gap: 8px;
    color: rgba(255, 255, 255, 0.78);
}
.av-hero-card .av-hero-img-fallback::before {
    content: "\2708"; /* ✈ */
    display: block;
    font-size: 40px;
    line-height: 1;
    color: rgba(255, 255, 255, 0.42);
    transform: rotate(-12deg);
    margin-bottom: 2px;
}
.av-hero-card .av-hero-img-fallback span {
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.01em;
}

/* Actions column: badge above buttons, right-aligned, 12px gap. Buttons
   stack vertically on desktop with 8px between them. Button styles are
   not changed here; only the layout. */
.av-hero-card .av-hero-actions-badge {
    display: flex;
    justify-content: flex-end;
}
.av-hero-card .av-hero-actions-buttons {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    min-width: 220px;
}
.av-hero-card .av-hero-actions-buttons .btn { white-space: normal; }

/* Tablet: title and actions share the top row, image spans full width
   below. Reuses the project's existing 900px breakpoint. */
@media (max-width: 900px) {
    .av-hero-card {
        grid-template-columns: minmax(0, 1fr) minmax(0, auto);
        grid-template-areas:
            "title  actions"
            "image  image";
        column-gap: 20px;
        row-gap: 18px;
    }
    .av-hero-card .av-hero-image-frame { max-width: none; }
    .av-hero-card .av-hero-actions-buttons { min-width: 0; }
}

/* Mobile: full vertical stack. Title, then image, then actions (badge
   followed by buttons). Reuses the project's existing 700px breakpoint
   already in this file. */
@media (max-width: 700px) {
    .av-hero-card {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "title"
            "image"
            "actions";
        row-gap: 14px;
    }
    .av-hero-card .av-hero-actions { align-items: stretch; }
    .av-hero-card .av-hero-actions-badge { justify-content: flex-start; }
    .av-hero-card .av-hero-actions-buttons {
        flex-direction: row;
        flex-wrap: wrap;
        gap: 8px;
    }
}

/* Print parity: hide the image frame on print, mirroring the existing
   .av-hero-img rule above so the new class names are also hidden. */
@media print {
    .av-hero-card .av-hero-image-frame { display: none !important; }
}

/* ====================================================================
   Aircraft view — Apple-style hero + info cards (av2-).
   New design layer for /index.php?page=aircraft-view&id=...
   Scoped under .av2-* so it never bleeds to other pages. The legacy
   .av-hero-card rules above remain for any caller that still uses them.
   ==================================================================== */

/* ----- Hero ----- */
.av2-hero {
    position: relative;
    overflow: hidden;
    margin-bottom: 22px;
    padding: 36px 36px 28px;
    border-radius: var(--radius-lg);
    background: var(--grad-jags);
    color: #fff;
    border: none;
    box-shadow: 0 30px 60px rgba(11, 11, 47, 0.18), 0 1px 2px rgba(11, 11, 47, 0.08);
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 380px);
    grid-template-areas:
        "head    image"
        "title   image"
        "tags    image"
        "kpis    kpis"
        "actions actions";
    column-gap: 36px;
    row-gap: 18px;
}
/* Soft top highlight — Apple's hairline at the top of dark cards. */
.av2-hero::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 1px;
    background: linear-gradient(90deg,
        rgba(255,255,255,0) 0%,
        rgba(255,255,255,0.18) 30%,
        rgba(255,255,255,0.22) 50%,
        rgba(255,255,255,0.18) 70%,
        rgba(255,255,255,0) 100%);
    pointer-events: none;
    z-index: 1;
}
/* Subtle ambient glow in the upper-right corner. */
.av2-hero::after {
    content: "";
    position: absolute;
    top: -120px; right: -120px;
    width: 380px; height: 380px;
    background: radial-gradient(circle, rgba(255,255,255,0.10) 0%, rgba(255,255,255,0) 65%);
    pointer-events: none;
    z-index: 0;
}
.av2-hero > * { position: relative; z-index: 2; }
.av2-hero-head {
    grid-area: head;
    display: flex; align-items: center; justify-content: space-between;
    gap: 16px; flex-wrap: wrap;
}
.av2-hero-eyebrow {
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: rgba(255,255,255,0.62);
}
.av2-hero-title { grid-area: title; min-width: 0; }
.av2-hero-reg {
    margin: 0;
    font-size: clamp(40px, 6vw, 64px);
    font-weight: 700;
    letter-spacing: -0.045em;
    line-height: 1;
    color: #fff;
    font-feature-settings: 'tnum' 1, 'lnum' 1, 'ss01' 1;
    overflow-wrap: break-word;
    word-break: break-word;
}
/* Tags: compact Apple-style metadata chips under the registration */
.av2-hero-tags {
    grid-area: tags;
    display: flex; flex-wrap: wrap; gap: 4px 8px;
    align-items: center;
}
.av2-tag {
    display: inline-flex; align-items: baseline; gap: 5px;
    padding: 0;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: -0.005em;
    color: rgba(255,255,255,0.88);
    background: transparent;
    border: none;
    line-height: 1.4;
}
.av2-tag + .av2-tag {
    border-left: 1px solid rgba(255,255,255,0.20);
    padding-left: 8px;
}
.av2-tag .lbl {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.10em;
    color: rgba(255,255,255,0.50);
    font-weight: 600;
}
/* KPI strip — at-a-glance summary inside the hero */
.av2-hero-kpis {
    grid-area: kpis;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 10px;
    margin-top: 6px;
}
.av2-kpi {
    background: rgba(255,255,255,0.07);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 12px;
    padding: 12px 14px;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    min-width: 0;
}
.av2-kpi .lbl {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    color: rgba(255,255,255,0.62);
    margin-bottom: 4px;
}
.av2-kpi .val {
    font-size: 18px;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: #fff;
    font-feature-settings: 'tnum' 1, 'lnum' 1;
    line-height: 1.15;
    word-break: break-word;
}
.av2-kpi .sub {
    font-size: 11px;
    color: rgba(255,255,255,0.62);
    margin-top: 2px;
    font-weight: 500;
}
.av2-kpi.warn  { background: rgba(216,181,109,0.20); border-color: rgba(216,181,109,0.40); }
.av2-kpi.warn .val { color: #FAE5B5; }
.av2-kpi.danger{ background: rgba(231,95,95,0.22); border-color: rgba(231,95,95,0.45); }
.av2-kpi.danger .val { color: #FFD3D3; }
.av2-kpi.success { background: rgba(122,198,96,0.22); border-color: rgba(122,198,96,0.45); }
.av2-kpi.success .val { color: #DCF3CB; }
/* Image — clean white card so cutouts on white backgrounds blend
   naturally (Apple product-card treatment over a dark hero). Soft outer
   shadow lifts the card off the navy gradient. */
.av2-hero-image {
    grid-area: image;
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 10;
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--card);
    border: 1px solid rgba(255,255,255,0.18);
    box-shadow:
        0 16px 40px rgba(0,0,0,0.22),
        0 2px 4px rgba(0,0,0,0.10);
    align-self: stretch;
}
.av2-hero-image > img {
    display: block;
    width: 100%; height: 100%;
    object-fit: contain;
    object-position: center;
    /* Tight zoom so the aircraft fills the white card with minimal margin.
       Tune down to 1.0 for tightly-cropped photos; current 1.15 reads well
       for typical white-background marketing cutouts. */
    transform: scale(1.15);
    transform-origin: center;
}
/* Fallback uses a gentle off-white tint and shows the airplane SVG plus
   helper copy. No hard contrast on the white card. */
.av2-hero-image .av2-hero-image-fallback {
    position: absolute; inset: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 8px;
    background: linear-gradient(180deg, #fbfcfe 0%, #eef1f7 100%);
    color: var(--muted);
}
.av2-hero-image .av2-hero-image-fallback svg {
    width: 56px; height: 56px;
    color: rgba(39,66,112,0.42);
}
.av2-hero-image .av2-hero-image-fallback span {
    font-size: 13px;
    font-weight: 500;
    color: var(--muted);
}
.av2-hero-image .av2-hero-image-fallback a {
    color: var(--secondary);
    text-decoration: underline;
    font-size: 12.5px;
    font-weight: 500;
}
/* Status badge — sits in the head row, presence pill */
.av2-status {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 6px 14px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #fff;
    background: rgba(255,255,255,0.10);
    border: 1px solid rgba(255,255,255,0.22);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.av2-status::before {
    content: "";
    width: 7px; height: 7px;
    border-radius: 50%;
    background: rgba(255,255,255,0.85);
    box-shadow: 0 0 0 3px rgba(255,255,255,0.18);
}
.av2-status.serviceable { background: rgba(122,198,96,0.22); border-color: rgba(122,198,96,0.55); color: #E2F4D6; }
.av2-status.serviceable::before { background: #B3E89A; box-shadow: 0 0 0 3px rgba(122,198,96,0.30); }
.av2-status.grounded { background: rgba(231,95,95,0.25); border-color: rgba(231,95,95,0.55); color: #FFE2E2; }
.av2-status.grounded::before { background: #F89A9A; box-shadow: 0 0 0 3px rgba(231,95,95,0.32); }
.av2-status.maintenance,
.av2-status.inspection_required { background: rgba(216,181,109,0.28); border-color: rgba(216,181,109,0.55); color: #FAE5B5; }
.av2-status.maintenance::before,
.av2-status.inspection_required::before { background: #E8C783; box-shadow: 0 0 0 3px rgba(216,181,109,0.32); }
/* Actions row */
.av2-hero-actions {
    grid-area: actions;
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 6px;
    padding-top: 18px;
    border-top: 1px solid rgba(255,255,255,0.12);
}
.av2-hero-actions .btn-primary {
    background: var(--card);
    color: var(--primary);
    border-color: #fff;
    font-weight: 700;
    box-shadow: 0 6px 18px rgba(0,0,0,0.18);
}
.av2-hero-actions .btn-primary:hover {
    background: rgba(255,255,255,0.92);
    color: var(--primary);
    box-shadow: 0 8px 22px rgba(0,0,0,0.22);
}
.av2-hero-actions .btn-ghost {
    background: rgba(255,255,255,0.10);
    color: #fff;
    border-color: rgba(255,255,255,0.22);
}
.av2-hero-actions .btn-ghost:hover {
    background: rgba(255,255,255,0.18);
    border-color: rgba(255,255,255,0.32);
    color: #fff;
}
/* Inactive overlay — Apple's frosted overlay treatment */
.av2-hero.is-inactive::before { background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.10) 50%, rgba(255,255,255,0) 100%); }
.av2-hero-inactive {
    position: absolute;
    top: 36px; right: 36px;
    z-index: 3;
}
/* Tablet: image goes below the title block */
@media (max-width: 1100px) {
    .av2-hero {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "head"
            "title"
            "tags"
            "image"
            "kpis"
            "actions";
    }
    .av2-hero-image { aspect-ratio: 16 / 9; max-height: 320px; }
}
@media (max-width: 700px) {
    .av2-hero {
        padding: 24px 20px 20px;
        border-radius: var(--radius);
    }
    .av2-hero-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .av2-hero-actions .btn { flex: 1 1 140px; justify-content: center; }
    .av2-hero-reg { font-size: 36px; }
    .av2-hero-image { aspect-ratio: 4 / 3; max-height: 240px; }
}

/* ----- Info cards grid ----- */
.av2-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 18px;
    margin-bottom: 22px;
}
@media (max-width: 900px) {
    .av2-grid { grid-template-columns: minmax(0, 1fr); }
}
.av2-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 0;
    box-shadow: var(--shadow-sm);
    transition:
        box-shadow var(--motion-med) var(--ease-soft),
        border-color var(--motion-med) var(--ease-soft);
    overflow: hidden;
    display: flex; flex-direction: column;
}
.av2-card:hover {
    box-shadow: var(--shadow-md);
    border-color: var(--border-strong);
}
.av2-card-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px;
    padding: 18px 22px 14px;
    border-bottom: 1px solid var(--border);
}
.av2-card-head .ttl {
    display: flex; align-items: center; gap: 10px;
    min-width: 0;
}
.av2-card-head .ttl-icon {
    width: 36px; height: 36px;
    border-radius: 10px;
    background: linear-gradient(180deg, rgba(39,66,112,0.10), rgba(39,66,112,0.04));
    color: var(--secondary);
    display: inline-flex; align-items: center; justify-content: center;
    flex: 0 0 36px;
}
.av2-card-head .ttl-icon svg { width: 18px; height: 18px; }
.av2-card-head h3 {
    margin: 0;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: var(--text-strong);
}
.av2-card-head .meta {
    font-size: 12px;
    color: var(--muted);
    font-weight: 500;
    text-align: right;
    flex-shrink: 0;
}
/* Feature value — the lead number on each info card */
.av2-feature {
    padding: 18px 22px 14px;
    border-bottom: 1px solid var(--border);
    background: var(--surface-low);
}
.av2-feature .feat-lbl {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    font-weight: 600;
    margin-bottom: 4px;
}
.av2-feature .feat-val {
    font-size: 28px;
    font-weight: 700;
    letter-spacing: -0.025em;
    line-height: 1.05;
    color: var(--text-strong);
    font-feature-settings: 'tnum' 1, 'lnum' 1;
    word-break: break-word;
}
.av2-feature .feat-sub {
    font-size: 12.5px;
    color: var(--muted);
    margin-top: 4px;
    font-weight: 500;
}
.av2-feature.warn .feat-val   { color: var(--status-warning-ink); }
.av2-feature.warn             { background: rgba(216,181,109,0.10); }
.av2-feature.danger .feat-val { color: var(--status-danger-ink); }
.av2-feature.danger           { background: rgba(184,50,53,0.06); }
.av2-feature.success .feat-val{ color: #2C4A1B; }
.av2-feature.success          { background: rgba(74,103,51,0.08); }
/* Row list inside a card — Apple Settings rhythm */
.av2-rows {
    list-style: none;
    margin: 0;
    padding: 4px 22px 14px;
    flex: 1;
}
.av2-rows li {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 14px;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
    min-width: 0;
}
.av2-rows li:last-child { border-bottom: none; }
.av2-rows .k {
    font-size: 13px;
    color: var(--muted);
    font-weight: 500;
    flex-shrink: 0;
}
.av2-rows .v {
    font-size: 14px;
    color: var(--text-strong);
    font-weight: 600;
    text-align: right;
    min-width: 0;
    word-break: break-word;
}
.av2-rows .v.mono { font-family: var(--font-mono); font-feature-settings: 'tnum' 1, 'lnum' 1; }
.av2-rows .v .sub {
    display: block;
    font-size: 11.5px;
    color: var(--muted);
    font-weight: 500;
    margin-top: 2px;
}
/* Countdown chip — for date rows where the urgency matters */
.av2-countdown {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.012em;
    line-height: 1.4;
}
.av2-countdown.success { background: rgba(74,103,51,0.12); color: var(--status-success-ink); }
.av2-countdown.info    { background: rgba(90,121,165,0.14); color: var(--status-info-ink); }
.av2-countdown.warn    { background: rgba(216,181,109,0.18); color: var(--status-warning-ink); }
.av2-countdown.danger  { background: rgba(184,50,53,0.14); color: var(--status-danger-ink); }
.av2-countdown.muted   { background: rgba(94,100,114,0.12); color: var(--muted); }

/* Aircraft images — hero card + gallery thumbs.
   Folder convention only; no DB. See assets/aircraft/<REG>/. */
.ac-images-hero {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius);
    background: linear-gradient(180deg, #F8FAFD 0%, #F1F4FA 100%);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-sm);
    aspect-ratio: 16 / 9;
    display: block;
}
.ac-images-hero a, .ac-images-hero img { display: block; width: 100%; height: 100%; }
.ac-images-hero img { object-fit: cover; }
.ac-images-hero.empty {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    text-align: center;
    color: var(--muted);
    aspect-ratio: auto;
    padding: 36px 24px;
}
.ac-images-hero.empty .placeholder-glyph {
    font-size: 38px; line-height: 1;
    color: var(--secondary);
    opacity: 0.55;
    margin-bottom: 10px;
}
.ac-images-hero.empty code {
    background: var(--card);
    border: 1px solid var(--border);
    color: var(--secondary);
    padding: 1px 6px; border-radius: 6px; font-size: 12.5px;
}
.ac-images-gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 10px;
    margin-top: 12px;
}
.ac-images-gallery a {
    display: block;
    aspect-ratio: 4 / 3;
    border-radius: var(--radius-sm);
    overflow: hidden;
    border: 1px solid var(--border);
    background: var(--surface-low);
    box-shadow: var(--shadow-sm);
    transition: transform 140ms ease, box-shadow 140ms ease, border-color 140ms ease;
}
.ac-images-gallery a:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
    border-color: var(--secondary);
}
.ac-images-gallery img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}
@media (max-width: 700px) {
    .ac-images-hero { aspect-ratio: 4 / 3; }
    .ac-images-gallery { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 8px; }
}
@media print {
    .ac-images-hero, .ac-images-gallery { display: none !important; }
}

/* Tabs */
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 18px; }
.tabs a { padding: 10px 14px; border-radius: 8px 8px 0 0; color: var(--muted); font-weight: 500; }
.tabs a.active { color: var(--primary); border-bottom: 2px solid var(--primary); }

/* ====================================================================
   Operations / Dispatch board — digital whiteboard
   Shared CSS for the schedule board (default) and table view fallback.
   Stays inside the existing card / btn / badge system so the rest of
   the portal continues to feel coherent.
   ==================================================================== */
.ops-board-wrap { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-sm); overflow: hidden; }
.ops-board-toolbar {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding: 14px 18px; border-bottom: 1px solid var(--border);
    background: linear-gradient(180deg, #FBFCFE, #F4F7FB);
    position: sticky; top: 0; z-index: 4;
}
.ops-board-toolbar .ops-board-date { font-weight: 700; letter-spacing: -0.02em; font-size: 17px; color: var(--primary); }
.ops-board-toolbar .ops-board-meta { color: var(--muted); font-size: 13px; }
.ops-board-toolbar .grow { flex: 1 1 auto; }
.ops-board-toolbar .ops-board-tabs { display: inline-flex; border: 1px solid var(--border); border-radius: 999px; overflow: hidden; background: var(--card); }
.ops-board-toolbar .ops-board-tabs a { padding: 6px 12px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
.ops-board-toolbar .ops-board-tabs a.active { background: var(--primary); color: #fff; }

.ops-board-scroll { overflow-x: auto; }
table.ops-board {
    width: 100%; border-collapse: separate; border-spacing: 0;
    font-size: 13.5px; min-width: 1180px;
}
table.ops-board thead th {
    position: sticky; top: 0; z-index: 2;
    background: #F1F4F9; color: var(--status-info-ink);
    font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    padding: 10px 12px; text-align: left; border-bottom: 1px solid var(--border);
    white-space: nowrap;
}
table.ops-board tbody td {
    padding: 12px;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
}
table.ops-board tbody tr {
    background: var(--card);
    transition: background var(--motion-fast) var(--ease-out);
}
table.ops-board tbody tr:hover { background: #FAFBFD; }
table.ops-board tbody tr.ops-row-priority {
    background: linear-gradient(90deg, rgba(184,50,53,0.05) 0%, rgba(184,50,53,0.02) 30%, #fff 65%);
}
table.ops-board tbody tr.ops-row-priority td:first-child {
    box-shadow: inset 4px 0 0 0 #B83235;
}
table.ops-board tbody tr.ops-row-vip td:first-child   { box-shadow: inset 4px 0 0 0 #B83235; }
table.ops-board tbody tr.ops-row-gt td:first-child    { box-shadow: inset 4px 0 0 0 #C18931; }
table.ops-board tbody tr.ops-row-moh td:first-child,
table.ops-board tbody tr.ops-row-moe td:first-child   { box-shadow: inset 4px 0 0 0 #5A79A5; }

/* Departed / Arrived / Completed rows stay fully readable — these are
   operationally important and shouldn't look "cancelled". Subtle muted
   tone differentiates them from active flights; the status chip in the
   Remarks column carries the explicit Departed/Arrived/Completed label.
   The explicit text-decoration: none on every descendant is defence in
   depth — it overrides any stale cached rule or upstream selector that
   might try to strike through completed flights. */
table.ops-board tbody tr.ops-row-departed {
    color: #5E6472;
    background: repeating-linear-gradient(0deg, transparent 0, transparent 22px, rgba(94,100,114,0.05) 22px, rgba(94,100,114,0.05) 23px);
}
table.ops-board tbody tr.ops-row-departed,
table.ops-board tbody tr.ops-row-departed td,
table.ops-board tbody tr.ops-row-departed td *,
table.ops-board tbody tr.ops-row-arrived,
table.ops-board tbody tr.ops-row-arrived td,
table.ops-board tbody tr.ops-row-arrived td *,
table.ops-board tbody tr.ops-row-completed,
table.ops-board tbody tr.ops-row-completed td,
table.ops-board tbody tr.ops-row-completed td *,
table.ops-board tbody tr.ops-row-airborne,
table.ops-board tbody tr.ops-row-airborne td,
table.ops-board tbody tr.ops-row-airborne td *,
table.ops-board tbody tr.ops-row-processed,
table.ops-board tbody tr.ops-row-processed td,
table.ops-board tbody tr.ops-row-processed td * {
    text-decoration: none !important;
    text-decoration-line: none !important;
}
table.ops-board tbody tr.ops-row-departed .reg,
table.ops-board tbody tr.ops-row-departed .ops-cell-time {
    color: #5E6472;
}

/* Cancelled flights keep the strike — the flight is not happening, so
   the visual cue is meaningful. Archived rows fade but stay readable. */
table.ops-board tbody tr.ops-row-cancelled td { opacity: 0.5; text-decoration: line-through; text-decoration-color: rgba(184,50,53,0.55); }
table.ops-board tbody tr.ops-row-archived td  { opacity: 0.55; }

table.ops-board td.ops-cell-time { font-family: "SF Mono", ui-monospace, Menlo, Consolas, monospace; font-weight: 600; color: var(--primary); white-space: nowrap; }
table.ops-board td .reg { font-weight: 700; color: var(--primary); letter-spacing: 0.01em; }
table.ops-board td .sub { color: var(--muted); font-size: 12px; }
table.ops-board td .charter { font-weight: 600; }
table.ops-board td .followup { font-weight: 700; letter-spacing: 0.04em; color: var(--status-info-ink); }

/* A/C column — registration and model/type stack as one intentional, tight
   block. The registration must never break mid-token (e.g. 8R-KTB splitting
   at the hyphen into "8R-" / "KTB"). Scoped to .ops-aircraft so the shared
   .reg/.sub tone + the departed-row muting above still cascade through. */
table.ops-board td .ops-aircraft {
    display: flex; flex-direction: column; gap: 1px;
    line-height: 1.3; min-width: max-content;
}
table.ops-board td .ops-aircraft .ops-ac-reg {
    white-space: nowrap; word-break: keep-all; overflow-wrap: normal;
    font-variant-numeric: tabular-nums;
}
table.ops-board td .ops-aircraft .ops-ac-type {
    white-space: nowrap; word-break: keep-all;
    font-size: 11.5px; line-height: 1.25;
}

.ops-board-empty { padding: 36px; text-align: center; color: var(--muted); }
.ops-board-meta-row { padding: 10px 18px; border-top: 1px solid var(--border); background: var(--surface-high); color: var(--muted); font-size: 12.5px; display: flex; gap: 16px; flex-wrap: wrap; }

.ops-priority-pip { display: inline-flex; align-items: center; gap: 4px; }
.ops-priority-pip::before { content: "★"; color: #B83235; font-size: 11px; }

/* Sweep panel + bulk-add table */
.ops-bulk-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.ops-bulk-table th, .ops-bulk-table td { padding: 6px 8px; border-bottom: 1px solid var(--border); vertical-align: top; }
.ops-bulk-table thead th { background: #F1F4F9; color: var(--primary); font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.05em; }
.ops-bulk-table tbody tr.ops-bulk-row-error { background: rgba(184,50,53,0.05); }
.ops-bulk-table input[type=text], .ops-bulk-table input[type=time], .ops-bulk-table input[type=date], .ops-bulk-table input[type=number], .ops-bulk-table select {
    width: 100%; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px; font-size: 13px; background: var(--card);
}
.ops-bulk-table .field-narrow input, .ops-bulk-table .field-narrow select { font-size: 12.5px; padding: 5px 6px; }

.ops-metar-strip {
    display: flex; gap: 18px; flex-wrap: wrap;
    padding: 10px 18px; border-bottom: 1px solid var(--border);
    background: var(--card);
    font-family: "SF Mono", ui-monospace, Menlo, Consolas, monospace; font-size: 12px; color: var(--status-info-ink);
}
.ops-metar-strip .lbl { color: var(--muted); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; font-size: 10.5px; }

@media (max-width: 1100px) {
    table.ops-board { font-size: 12.75px; min-width: 1080px; }
    table.ops-board tbody td { padding: 10px; }
}
@media print {
    .ops-board-toolbar, .ops-board-meta-row, .ops-metar-strip { display: none !important; }
    .ops-board-wrap { box-shadow: none; border: none; }
    table.ops-board { min-width: 0; font-size: 9pt; }
    table.ops-board thead th { background: #E8ECF5 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    table.ops-board tbody tr.ops-row-priority { background: rgba(184,50,53,0.06) !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* ====================================================================
   Operations mobile flight schedule — compact table-first board
   --------------------------------------------------------------------
   Phones retain the real schedule table rather than switching to card
   modules. Aircraft and route stay frozen on the left, while the row
   action remains available on the right; times, fuel, crew and remarks
   scroll naturally between them. Desktop and all print views keep the
   established board unchanged.
   ==================================================================== */
.ops-mobile-status { display: none; }
@media (max-width: 700px) {
    .ops-board-wrap {
        border-radius: 12px;
        box-shadow: 0 6px 18px rgba(18, 44, 78, 0.08);
    }
    .ops-board-scroll {
        overflow-x: auto;
        overscroll-behavior-x: contain;
        background: var(--surface-low);
    }
    table.ops-board.ops-mobile-schedule {
        width: max-content;
        min-width: 1020px;
        font-size: 12px;
        line-height: 1.25;
    }
    table.ops-board.ops-mobile-schedule thead th {
        padding: 8px 7px;
        font-size: 9.5px;
        letter-spacing: 0.055em;
        background: #EAF0F7;
    }
    table.ops-board.ops-mobile-schedule tbody td {
        padding: 8px 7px;
        vertical-align: middle;
        background: var(--card);
    }
    table.ops-board.ops-mobile-schedule tbody tr:nth-child(even) td {
        background: var(--surface-low);
    }
    table.ops-board.ops-mobile-schedule tbody tr.ops-row-editing td {
        background: #F3F8FF;
        border-bottom-color: rgba(36, 74, 120, 0.28);
    }
    /* The board date is already present in the compact toolbar. Flight
       follower, crew and charter remain available in the desktop board and
       mobile cards, but do not displace route and ETD in the first phone
       viewport. */
    table.ops-board.ops-mobile-schedule th:nth-child(1),
    table.ops-board.ops-mobile-schedule td:nth-child(1),
    table.ops-board.ops-mobile-schedule th:nth-child(3),
    table.ops-board.ops-mobile-schedule td:nth-child(3),
    table.ops-board.ops-mobile-schedule th:nth-child(4),
    table.ops-board.ops-mobile-schedule td:nth-child(4),
    table.ops-board.ops-mobile-schedule th:nth-child(5),
    table.ops-board.ops-mobile-schedule td:nth-child(5) {
        display: none;
    }
    /* Keep one compact identity column fixed; route is the first scrolling
       column so a 390px phone still has useful rail space. */
    table.ops-board.ops-mobile-schedule th:nth-child(2),
    table.ops-board.ops-mobile-schedule td:nth-child(2) {
        position: sticky;
        left: 0;
        z-index: 3;
        min-width: 88px;
        max-width: 88px;
        box-shadow: 2px 0 0 #DCE5F0, 5px 0 10px rgba(24, 52, 84, 0.06);
    }
    table.ops-board.ops-mobile-schedule th:nth-child(2) { z-index: 6; }
    table.ops-board.ops-mobile-schedule td:nth-child(6) {
        width: 150px;
        min-width: 150px;
        max-width: 150px;
        font-weight: 650;
        color: #183B63;
        white-space: normal;
        overflow-wrap: anywhere;
    }
    table.ops-board.ops-mobile-schedule th:nth-child(7),
    table.ops-board.ops-mobile-schedule td:nth-child(7) {
        min-width: 72px;
        font-weight: 750;
    }
    /* Fuel, crew, every movement time and the full remarks/status column
       stay in the native table; the dedicated action column is frozen so
       an Operations user never has to pan to begin a quick edit. */
    table.ops-board.ops-mobile-schedule th:nth-child(14),
    table.ops-board.ops-mobile-schedule td.ops-board-actions {
        position: sticky;
        right: 0;
        z-index: 4;
        min-width: 124px;
        max-width: 124px;
        padding: 6px;
        text-align: center !important;
        white-space: normal !important;
        box-shadow: -3px 0 10px rgba(24, 52, 84, 0.12);
    }
    table.ops-board.ops-mobile-schedule th:nth-child(14) {
        z-index: 7;
        background: #EAF0F7;
    }
    table.ops-board.ops-mobile-schedule td.ops-board-actions .btn {
        display: inline-flex !important;
        width: calc(50% - 3px);
        min-height: 44px;
        margin: 2px 0;
        padding: 6px 3px;
        font-size: 11px;
        line-height: 1.1;
        white-space: normal;
        justify-content: center;
    }
    table.ops-board.ops-mobile-schedule td.ops-board-actions form {
        display: inline !important;
    }
    table.ops-board.ops-mobile-schedule td.ops-board-actions form .btn {
        width: calc(50% - 3px);
    }
    table.ops-board.ops-mobile-schedule .ops-inline-input,
    table.ops-board.ops-mobile-schedule .ops-inline-aircraft {
        min-height: 38px;
        font-size: 16px !important;
    }
    .ops-mobile-status {
        display: block;
        margin-top: 4px;
        white-space: nowrap;
    }
    .ops-mobile-status .badge {
        font-size: 9px;
        padding: 2px 5px;
    }
    .ops-board-meta-row {
        gap: 9px;
        padding: 9px 12px;
        font-size: 11.5px;
    }
    .ops-board-meta-row span { white-space: nowrap; }
}
@media print {
    .ops-mobile-status { display: none !important; }
}

/* Print */
@media print {
    body { background: #fff; font-size: 10pt; }
    .sidebar, .topbar, .dr-toolbar, .no-print { display: none !important; }
    .app-shell { grid-template-columns: minmax(0, 1fr); }
    .content { padding: 0; }
    .dr-wrap { box-shadow: none; border: none; border-radius: 0; }
    .dr-header { background: #171756 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    table.dr { font-size: 9pt; min-width: 0; }
    table.dr th { background: #E8ECF5 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    .cell-warn, .cell-green, .cell-major, .cell-outstanding,
    .cell-coa-soon, .cell-cmr-soon, .cell-expired {
        -webkit-print-color-adjust: exact !important;
        print-color-adjust: exact !important;
    }
    .dr-kw-critical { color: #8E2226 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    .dr-kw-warn     { color: #5C3F0E !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    .dr-kw-info     { color: #1F3F73 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    .legend { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    @page { size: A3 landscape; margin: 10mm; }
}

/* Responsive
   Tiered breakpoints:
   - >=1280px : default (desktop)
   - 1100px   : laptop  — slightly tighter sidebar + table
   - 900px    : tablet  — sidebar stacks above content; tables scroll inside their card
   - 700px    : mobile  — stat grid two-up, denser typography, topbar collapses */
@media (max-width: 1280px) {
    .app-shell { grid-template-columns: 220px minmax(0, 1fr); }
    .content { padding: 24px 22px; }
    table.tbl { font-size: 13.25px; }
    table.tbl th, table.tbl td { padding: 9px 11px; }
    .tbl td.cell-remarks { max-width: 200px; }
}
@media (max-width: 1100px) {
    .app-shell { grid-template-columns: 200px minmax(0, 1fr); }
    .content { padding: 22px 20px; }
    .topbar { padding: 12px 22px; }
    table.tbl { font-size: 13px; }
    table.tbl th, table.tbl td { padding: 8px 10px; }
    table.tbl-compact th, table.tbl-compact td { padding: 7px 9px; }
    .tbl td.cell-remarks { max-width: 180px; font-size: 12px; }
    .tbl td.cell-actions .btn-sm { padding: 5px 9px; font-size: 12px; }
    .stats-grid { gap: 14px; }
    .stat .value { font-size: 26px; }
}
@media (max-width: 900px) {
    .app-shell { grid-template-columns: minmax(0, 1fr); }
    .sidebar {
        position: static;
        height: auto;
        border-right: none;
        border-bottom: 1px solid var(--border);
        padding: 14px 16px;
    }
    .sidebar-brand { padding: 6px; margin-bottom: 12px; }
    .sidebar-brand img { max-height: 56px; }
    .sidebar-section { margin: 12px 4px 6px; }
    .sidebar nav {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
        gap: 4px;
    }
    .sidebar nav a { padding: 8px 11px; font-size: var(--text-sm); margin-bottom: 0; }
    .sidebar nav a.active::before { display: none; }
    .sidebar-account { margin-top: 10px; }
    .topbar h1 { font-size: 17px; }
    .content { padding: 18px 16px; }
    .auth-page { grid-template-columns: 1fr; }
    .auth-side { padding: 32px 28px; }
    .auth-side .pitch h1 { font-size: 28px; }
}
@media (max-width: 700px) {
    .topbar { padding: 10px 14px; }
    .topbar h1 { font-size: 16px; max-width: 60%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .topbar-user .who,
    .user-menu-button .who { display: none; }
    .user-menu-button { padding: 4px; border-radius: 999px; }
    .user-menu-popover { right: -4px; min-width: 220px; }
    .bell-popover { right: -4px; width: min(320px, calc(100vw - 24px)); }
    .stats-grid { grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 18px; }
    .stat { padding: 14px 16px; }
    .stat .value { font-size: 22px; }
    .stat .label { font-size: 11px; }
    .content { padding: 16px 12px; }
    .card { padding: 16px; }
    table.tbl { font-size: 12.75px; }
    table.tbl th, table.tbl td { padding: 7px 9px; }
    table.tbl th { font-size: 10.5px; letter-spacing: 0.04em; }
    .tbl td.cell-remarks { max-width: 140px; font-size: 11.75px; }
    .badge { font-size: 11px; padding: 2px 8px; }
    .date-chip { font-size: 11.5px; padding: 2px 7px; }
    .tbl td.cell-actions { padding-right: 8px; }
    .tbl td.cell-actions .btn-sm { padding: 5px 8px; font-size: 11.5px; }
    .form-grid { grid-template-columns: 1fr !important; gap: 10px; }
    .section-title { flex-wrap: wrap; gap: 4px; }
}

/* ====================================================
   Premium polish layer.
   Adds focus-visible rings, refined transitions, hover lift on
   *interactive* cards (a.card-glass, gallery thumbs), and the
   form-submit loading state. All sit on top of existing styles —
   nothing here removes prior behaviour.
   ==================================================== */

/* Smooth body-scroll on anchored navigation. */
html { scroll-behavior: smooth; }

/* Buttons — active press, focus ring, disabled, loading. */
.btn { transition:
    background var(--motion-fast) var(--ease-out),
    color      var(--motion-fast) var(--ease-out),
    transform  var(--motion-fast) var(--ease-out),
    box-shadow var(--motion-fast) var(--ease-out),
    border-color var(--motion-fast) var(--ease-out),
    opacity    var(--motion-fast) var(--ease-out);
}
.btn:active { transform: translateY(0) scale(0.985); transition-duration: 80ms; }
.btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(90, 121, 165, 0.45), var(--shadow-sm);
}
.btn-primary:focus-visible {
    box-shadow: 0 0 0 3px rgba(23, 23, 86, 0.42), var(--shadow-md);
}
.btn-danger:focus-visible {
    box-shadow: 0 0 0 3px rgba(184, 50, 53, 0.40), var(--shadow-md);
}
.btn:disabled, .btn[aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
    transform: none !important;
    box-shadow: none !important;
}

/* Submit-loading state — driven by jags_polish_script() in layout_footer.
   The button text is swapped to "Saving…" with a leading spinner; the
   button stays the same width as before (no jump). */
.btn.is-loading {
    pointer-events: none;
    cursor: wait;
    opacity: 0.92;
}
.jags-spinner {
    display: inline-block;
    width: 12px; height: 12px;
    margin: 0 6px -1px 0;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: jagsSpin 700ms linear infinite;
    vertical-align: middle;
    opacity: 0.75;
}
@keyframes jagsSpin { to { transform: rotate(360deg); } }

/* Form fields — refined transition timing. The :focus ring already exists
   above; here we just align timings to the motion tokens. */
.field input, .field select, .field textarea {
    transition:
        border-color var(--motion-fast) var(--ease-out),
        box-shadow   var(--motion-fast) var(--ease-out),
        background   var(--motion-fast) var(--ease-out);
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
    outline: none;
}

/* Sidebar nav — focus + smoother hover. Active state already uses the
   JAGS gradient; we just cushion the transition. */
.sidebar nav a {
    transition:
        background var(--motion-fast) var(--ease-out),
        color      var(--motion-fast) var(--ease-out),
        box-shadow var(--motion-fast) var(--ease-out),
        transform  var(--motion-fast) var(--ease-out);
}
.sidebar nav a:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(90, 121, 165, 0.45) inset;
}
.sidebar nav a.active { transform: translateZ(0); }

/* Topbar walkthrough launcher — lift + focus ring. Existing hover already
   nudges; we just give it a real focus state. */
#jags-tour-launcher:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(90, 121, 165, 0.45);
}

/* Stat cards — content tiles, NOT clickable. Subtle shadow grow on hover so
   they feel responsive without implying interactivity. No transform. */
.stat {
    transition:
        box-shadow   var(--motion-med) var(--ease-soft),
        border-color var(--motion-med) var(--ease-soft);
}
.stat:hover {
    box-shadow: var(--shadow-md);
    border-color: rgba(39, 66, 112, 0.16);
}

/* Glass quick-action cards — lift on hover when used as a link/button.
   Targets the a/button form so plain decorative .card-glass doesn't lift. */
a.card-glass, button.card-glass {
    cursor: pointer;
    transition:
        transform   var(--motion-med) var(--ease-soft),
        box-shadow  var(--motion-med) var(--ease-soft),
        border-color var(--motion-med) var(--ease-soft);
}
a.card-glass:hover, button.card-glass:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
    border-color: rgba(39, 66, 112, 0.22);
}
a.card-glass:focus-visible, button.card-glass:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(90, 121, 165, 0.40), var(--shadow-md);
}

/* Aircraft summary cards on dashboards (.ac-card) — soft hover. */
.ac-card { transition:
    box-shadow   var(--motion-med) var(--ease-soft),
    border-color var(--motion-med) var(--ease-soft),
    transform    var(--motion-med) var(--ease-soft);
}
.ac-card:hover {
    box-shadow: var(--shadow-md);
    border-color: rgba(39, 66, 112, 0.16);
    transform: translateY(-1px);
}

/* Table rows — smooth row-hover background fade (already triggered by
   tr:hover td above — this just transitions the change). */
table.tbl tbody td {
    transition: background var(--motion-fast) var(--ease-out);
}

/* Badges + date chips — gentle when state changes (e.g. JS toggles). */
.badge, .date-chip {
    transition:
        background var(--motion-fast) var(--ease-out),
        color      var(--motion-fast) var(--ease-out),
        box-shadow var(--motion-fast) var(--ease-out);
}

/* Aircraft images — load fade-in. Modern browsers also respect the
   loading="lazy" attribute on the gallery thumbs. */
.ac-images-hero img,
.ac-images-gallery img {
    opacity: 0;
    animation: jagsImgIn var(--motion-slow) var(--ease-soft) both;
}
@keyframes jagsImgIn { from { opacity: 0; } to { opacity: 1; } }

/* Walkthrough modal — already animated. Touch-up only: align buttons +
   progress fill to the motion tokens; existing keyframes stay unchanged. */
.jags-tour-card .btn { transition-duration: var(--motion-fast); }
.jags-tour-progress .fill { transition-duration: var(--motion-med); }

/* Generic link focus ring — applied to any unstyled <a> the user can tab to. */
a:focus-visible {
    outline: 2px solid rgba(90, 121, 165, 0.55);
    outline-offset: 2px;
    border-radius: 4px;
}
.btn:focus-visible, a.card-glass:focus-visible { outline: none; }

/* ====================================================
   Reduced-motion preference — respect the OS setting.
   ==================================================== */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
    .main > .content,
    .ac-images-hero img,
    .ac-images-gallery img {
        animation: none !important;
        opacity: 1 !important;
        transform: none !important;
    }
    .jags-tour-target { animation: none !important; }
    html { scroll-behavior: auto; }
}

/* ====================================================
   Print safety — disable polish animations + hover transforms in print.
   ==================================================== */
@media print {
    .main > .content { animation: none !important; }
    .ac-images-hero img, .ac-images-gallery img { animation: none !important; opacity: 1 !important; }
    .stat, a.card-glass, .ac-card, .btn { transition: none !important; transform: none !important; box-shadow: none !important; }
}

/* ====================================================
   Walkthrough / guided tour — overlay, card, target glow.
   All scoped under #jags-tour or .jags-tour-* so it can never bleed
   into the rest of the app.
   ==================================================== */
#jags-tour-launcher {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 7px 13px;
    border-radius: 999px;
    border: 1px solid rgba(39,66,112,0.18);
    background: linear-gradient(180deg, rgba(var(--glass-rgb),0.96) 0%, rgba(var(--glass-rgb),0.90) 100%);
    -webkit-backdrop-filter: saturate(140%) blur(8px);
    backdrop-filter: saturate(140%) blur(8px);
    color: var(--secondary);
    font-weight: 600; font-size: 12.5px; letter-spacing: 0.005em;
    cursor: pointer;
    box-shadow: 0 1px 0 rgba(255,255,255,0.6) inset, 0 1px 2px rgba(11,11,47,0.04);
    transition: background 160ms var(--ease-out), transform 160ms var(--ease-out),
                box-shadow 160ms var(--ease-out), border-color 160ms var(--ease-out);
}
#jags-tour-launcher:hover {
    border-color: rgba(39,66,112,0.36);
    box-shadow: 0 1px 0 rgba(255,255,255,0.7) inset, 0 6px 16px rgba(11,11,47,0.08);
    transform: translateY(-1px);
}
#jags-tour-launcher .spark { color: var(--info); display: inline-flex; align-items: center; line-height: 1; }
#jags-tour-launcher .spark svg { width: 14px; height: 14px; display: block; }
@media (max-width: 700px) {
    #jags-tour-launcher .label { display: none; }
    #jags-tour-launcher { padding: 7px 9px; }
}

#jags-tour { position: fixed; inset: 0; z-index: 9000; }
#jags-tour[hidden] { display: none !important; }
.jags-tour-backdrop {
    position: absolute; inset: 0;
    background:
      radial-gradient(120% 80% at 50% 0%, rgba(11,11,47,0.42) 0%, rgba(11,11,47,0.62) 60%, rgba(11,11,47,0.74) 100%);
    backdrop-filter: blur(6px) saturate(120%);
    -webkit-backdrop-filter: blur(6px) saturate(120%);
    animation: jagsTourFade 220ms var(--ease-out);
}
@keyframes jagsTourFade { from { opacity: 0; } to { opacity: 1; } }
.jags-tour-card {
    position: absolute;
    z-index: 1;
    width: min(440px, calc(100vw - 32px));
    background: linear-gradient(180deg, rgba(var(--glass-rgb),0.94) 0%, rgba(var(--glass-rgb),0.88) 100%);
    -webkit-backdrop-filter: blur(20px) saturate(160%);
    backdrop-filter: blur(20px) saturate(160%);
    border: 1px solid rgba(255,255,255,0.6);
    border-radius: 22px;
    box-shadow:
      0 1px 0 rgba(255,255,255,0.9) inset,
      0 0 0 1px rgba(39,66,112,0.06),
      0 28px 60px -12px rgba(11,11,47,0.34),
      0 8px 18px -8px rgba(11,11,47,0.16);
    overflow: hidden;
    animation: jagsTourPop 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
    /* Smooth re-centre when one step's body is taller than another's.
       Without this, the card would snap to its new top/left when text
       changes; with it, the card glides into place. */
    transition:
        top    220ms cubic-bezier(0.22, 1, 0.36, 1),
        left   220ms cubic-bezier(0.22, 1, 0.36, 1),
        width  220ms cubic-bezier(0.22, 1, 0.36, 1);
}
@media (prefers-reduced-motion: reduce) {
    .jags-tour-card { transition: none; animation: none; }
}
@keyframes jagsTourPop {
    from { opacity: 0; transform: translateY(10px) scale(0.985); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
.jags-tour-accent {
    height: 2px;
    background: linear-gradient(90deg,
        rgba(23,23,86,0)   0%,
        rgba(23,23,86,0.55) 18%,
        rgba(90,121,165,0.95) 50%,
        rgba(23,23,86,0.55) 82%,
        rgba(23,23,86,0)   100%);
    opacity: 0.85;
}
.jags-tour-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 16px 20px 6px;
    gap: 12px;
}
.jags-tour-head .meta {
    display: flex; align-items: center; gap: 10px; min-width: 0;
}
.jags-tour-head .badge-step {
    display: inline-flex; align-items: center; gap: 5px;
    background: rgba(39,66,112,0.06);
    border: 1px solid rgba(39,66,112,0.10);
    color: var(--secondary);
    padding: 3px 9px 3px 8px; border-radius: 999px;
    font-size: 10.5px; font-weight: 700;
    letter-spacing: 0.06em; text-transform: uppercase;
}
.jags-tour-head .badge-step::before {
    content: ""; width: 5px; height: 5px; border-radius: 999px;
    background: var(--info);
    box-shadow: 0 0 0 3px rgba(90,121,165,0.18);
}
.jags-tour-head .progress-text {
    color: var(--muted); font-size: 11.5px;
    font-variant-numeric: tabular-nums; letter-spacing: 0.02em;
}
.jags-tour-head .close-btn {
    background: transparent; border: none; cursor: pointer;
    color: var(--muted); font-size: 22px; line-height: 1;
    padding: 0; width: 28px; height: 28px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 999px;
    transition: background 140ms var(--ease-out), color 140ms var(--ease-out);
}
.jags-tour-head .close-btn:hover { background: rgba(94,100,114,0.10); color: var(--text); }
.jags-tour-head .close-btn:focus-visible {
    outline: 2px solid var(--info); outline-offset: 2px;
}

.jags-tour-progress {
    height: 3px; background: rgba(39,66,112,0.08); margin: 0 20px;
    border-radius: 999px; overflow: hidden;
}
.jags-tour-progress .fill {
    height: 100%; width: 0%;
    background: linear-gradient(90deg, var(--secondary) 0%, var(--info) 100%);
    transition: width 320ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.jags-tour-dots {
    display: flex; gap: 5px; padding: 10px 20px 0; flex-wrap: wrap;
}
.jags-tour-dots span {
    width: 5px; height: 5px; border-radius: 999px;
    background: rgba(39,66,112,0.14);
    transition: background 200ms var(--ease-out), transform 200ms var(--ease-out), width 200ms var(--ease-out);
}
.jags-tour-dots span.done { background: rgba(39,66,112,0.55); }
.jags-tour-dots span.current {
    background: var(--primary);
    width: 16px;
}

.jags-tour-body {
    padding: 10px 20px 4px;
    /* Buttery step transitions — fade + tiny rise as the text swaps.
       JS toggles .is-stepping for one frame, then removes it after a
       requestAnimationFrame to fade the new content back in. */
    transition: opacity 180ms cubic-bezier(0.22, 1, 0.36, 1),
                transform 180ms cubic-bezier(0.22, 1, 0.36, 1);
    will-change: opacity, transform;
}
.jags-tour-body.is-stepping {
    opacity: 0;
    transform: translateY(4px);
}
.jags-tour-body h3 {
    margin: 0 0 6px;
    font-size: 18px; line-height: 1.3;
    letter-spacing: -0.012em;
    color: var(--text);
    font-weight: 600;
}
.jags-tour-body p {
    margin: 0;
    color: var(--muted);
    font-size: 14px; line-height: 1.55;
    letter-spacing: -0.002em;
}
/* Reduced-motion users get an instant swap, no fade. */
@media (prefers-reduced-motion: reduce) {
    .jags-tour-body { transition: none; }
    .jags-tour-body.is-stepping { opacity: 1; transform: none; }
}
.jags-tour-actions {
    display: flex; align-items: center; justify-content: space-between;
    padding: 16px 20px 18px;
    gap: 10px;
}
.jags-tour-actions .nav-group { display: flex; gap: 8px; }
.jags-tour-actions .btn {
    padding: 8px 14px; font-size: 13px;
    border-radius: 10px;
}
.jags-tour-actions .btn-primary {
    box-shadow: 0 4px 14px rgba(23,23,86,0.22);
}
.jags-tour-actions .btn-primary:focus-visible,
.jags-tour-actions .btn-ghost:focus-visible {
    outline: 2px solid var(--info); outline-offset: 2px;
}

/* While a tour is open, dim/de-saturate the rest of the app so the user's
   eye is drawn to the highlighted target. The target itself sits at a
   higher z-index and is exempt from the dim. */
body.jags-tour-active .app-shell {
    filter: saturate(0.82) brightness(0.9);
    transition: filter var(--motion-med) var(--ease-soft);
}
body.jags-tour-active .jags-tour-target,
body.jags-tour-active .jags-tour-target * {
    filter: none !important;
}

/* Spotlight target highlight — calmer ring, refined glow. */
.jags-tour-target {
    position: relative;
    z-index: 9001;
    border-radius: 12px;
    box-shadow:
      0 0 0 3px rgba(255,255,255,0.96),
      0 0 0 5px rgba(90,121,165,0.65),
      0 0 0 9px rgba(90,121,165,0.18),
      0 18px 40px -8px rgba(11,11,47,0.28);
    animation: jagsTargetPulse 2.6s ease-in-out infinite;
    transition: box-shadow 240ms var(--ease-out);
}
@keyframes jagsTargetPulse {
    0%, 100% {
        box-shadow:
          0 0 0 3px rgba(255,255,255,0.96),
          0 0 0 5px rgba(90,121,165,0.55),
          0 0 0 9px rgba(90,121,165,0.14),
          0 18px 40px -8px rgba(11,11,47,0.26);
    }
    50% {
        box-shadow:
          0 0 0 3px rgba(255,255,255,0.96),
          0 0 0 5px rgba(90,121,165,0.85),
          0 0 0 12px rgba(90,121,165,0.22),
          0 18px 44px -8px rgba(11,11,47,0.30);
    }
}

@media (max-width: 700px) {
    .jags-tour-card { width: calc(100vw - 24px); }
    .jags-tour-actions { flex-direction: column-reverse; align-items: stretch; }
    .jags-tour-actions .nav-group { width: 100%; justify-content: space-between; }
    .jags-tour-actions .btn { flex: 1; justify-content: center; }
}

/* Fully hide the tour during print so it never lands on paper */
@media print {
    #jags-tour, #jags-tour-launcher { display: none !important; }
    .jags-tour-target { box-shadow: none !important; animation: none !important; }
}

/* Broad print guard — final catch-all so no animation, transition, spinner,
   tour glow, or smooth-scroll polish leaks into printed output. Sits AFTER
   the existing print rules so it overrides anything the polish layer might
   have introduced. The earlier @media print blocks (Daily Report A3/landscape,
   colour preservation, sidebar/topbar/walkthrough/aircraft-images hide,
   print-color-adjust) keep their own !important rules and remain authoritative
   for layout. */
@media print {
    *, *::before, *::after {
        animation: none !important;
        transition: none !important;
        scroll-behavior: auto !important;
    }
}

/* ---------------------------------------------------------------
   Final polish pass — calmer hovers, tighter buttons, sharper focus
   rings, restraint on shadows. Loaded last so these rules win for
   the small set of selectors below without rewriting the rest of
   the system. Apple/Vercel/Linear-style restraint.
   --------------------------------------------------------------- */

/* Calmer button hovers — drop the +1px float so the UI doesn't feel
   fidgety. Keep the colour shift and a softer shadow lift. */
.btn-primary:hover  { transform: none; box-shadow: 0 2px 8px rgba(11, 11, 47, 0.18); }
.btn-secondary:hover { transform: none; }
.btn-ghost:hover    { transform: none; }
.btn-danger:hover   { transform: none; }

/* Consistent focus ring across buttons + nav. Replaces the various
   ad-hoc :focus-visible boxes scattered across the file. */
.btn:focus-visible,
.sidebar nav a:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(23, 23, 86, 0.22);
}

/* Hairline divider on the topbar so it floats over scrolled content
   instead of sitting on a hard line. */
.topbar { box-shadow: 0 1px 0 rgba(14, 14, 18, 0.04); }

/* Slightly tighter, calmer badge spacing — less "tag", more "chip". */
.badge { padding: 2px 8px; font-weight: 600; }

/* Tone the radial highlight inside .stat tiles so they don't read as
   "every card has a glow corner." */
.stat::after { background: radial-gradient(circle, rgba(39,66,112,0.05), transparent 70%); }

/* Section titles read as proper headings — slightly tighter tracking,
   slightly more weight. */
.section-title h2 { font-weight: 650; letter-spacing: -0.02em; }

/* Card-hero: airy shadow with a slight navy tint so the brand moment
   feels lifted without competing with the page content. */
.card-hero { box-shadow: 0 30px 60px rgba(11, 11, 47, 0.10), 0 1px 2px rgba(14, 14, 18, 0.04); }

/* (Removed 2026-08) A later `.empty-state` redefinition here used to
   collapse the real component's 42px padding to 4px — the icon/title/CTA
   empty state is owned by its primary block earlier in this sheet. */

/* Quick-link rows (Pilot Portal, Maintenance, Display Center) —
   left-aligned ghost buttons read as a navigation list, not as a
   row of five identical CTAs. */
.btn-ghost.btn-quicklink {
    justify-content: flex-start;
    gap: 10px;
    padding: 10px 12px;
    font-weight: 500;
}
.btn-ghost.btn-quicklink .jags-icon {
    color: var(--secondary); opacity: 0.85;
    width: 16px; height: 16px;
}
.btn-ghost.btn-quicklink:hover .jags-icon { color: var(--primary); opacity: 1; }

/* Tighter alert padding so flash messages don't dominate the page
   heading row. */
.alert { padding: 10px 14px; }

/* Tables — calm zebra rows + subtle navy hover. */
table.tbl tbody tr:nth-child(even) td { background: var(--surface-low); }
table.tbl tbody tr:hover td { background: rgba(90, 121, 165, 0.06); }

/* Brand-sub in the sidebar — give the new "Aviation Management System"
   text a hair more breathing room than the old subtitle. */
.sidebar-brand .brand-sub { font-size: 10.5px; padding: 4px 6px 2px; }

/* ====================================================================
   Mobile UX layer — hamburger drawer, bottom nav, page helpers.
   Final mobile-refinement pass. Sits last so its rules win for
   sub-900px breakpoints without rewriting earlier responsive blocks.
   ==================================================================== */

/* Generic mobile/desktop visibility helpers (opt-in classes for pages). */
.mobile-only { display: none !important; }
@media (max-width: 900px) {
    .mobile-only { display: revert !important; }
    .desktop-only { display: none !important; }
}

/* Hamburger toggle in the topbar — hidden on desktop, visible on mobile. */
.mobile-nav-toggle {
    display: none;
    background: rgba(90,121,165,0.08);
    border: 1px solid var(--border);
    border-radius: 10px;
    color: var(--primary);
    width: 40px; height: 40px;
    align-items: center; justify-content: center;
    cursor: pointer; padding: 0;
    transition:
        background var(--motion-fast) var(--ease-out),
        color var(--motion-fast) var(--ease-out),
        box-shadow var(--motion-fast) var(--ease-out);
}
.mobile-nav-toggle:hover { background: rgba(90,121,165,0.18); }
.mobile-nav-toggle:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(90,121,165,0.40);
}
.mobile-nav-toggle .bars {
    display: inline-flex; flex-direction: column; gap: 4px;
    pointer-events: none;
}
.mobile-nav-toggle .bars span {
    display: block; width: 18px; height: 2px;
    background: currentColor; border-radius: 2px;
    transition: transform var(--motion-fast) var(--ease-out), opacity var(--motion-fast) var(--ease-out);
}
@media (max-width: 900px) {
    .mobile-nav-toggle { display: inline-flex; }
}
body.mobile-nav-open .mobile-nav-toggle .bars span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
body.mobile-nav-open .mobile-nav-toggle .bars span:nth-child(2) { opacity: 0; }
body.mobile-nav-open .mobile-nav-toggle .bars span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* Drawer backdrop — covers the page while the slide-in nav is open. */
.mobile-drawer-backdrop {
    position: fixed;
    inset: 0;
    z-index: 9090;
    background: rgba(11,11,47,0.46);
    -webkit-backdrop-filter: blur(3px);
    backdrop-filter: blur(3px);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--motion-med) var(--ease-out);
}
body.mobile-nav-open .mobile-drawer-backdrop {
    opacity: 1;
    pointer-events: auto;
}
.mobile-drawer-backdrop[aria-hidden="true"] {
    opacity: 0 !important;
    pointer-events: none !important;
}
@media (min-width: 901px) {
    .mobile-drawer-backdrop { display: none; }
    body.mobile-nav-open { overflow: visible !important; }
}

/* Lock body scroll while drawer is open. */
body.mobile-nav-open { overflow: hidden; }

/* Mobile drawer reuses the existing .sidebar element. Slide-in panel,
   role-aware nav, branding, account block. Desktop sidebar layout is
   untouched above 900px. */
@media (max-width: 900px) {
    .app-shell { grid-template-columns: minmax(0, 1fr); }
    .sidebar {
        position: fixed;
        top: 0; left: 0;
        width: min(286px, 84vw);
        height: 100vh;
        height: 100dvh;
        max-height: 100vh;
        max-height: 100dvh;
        z-index: 9100;
        background: var(--grad-sidebar);
        border-right: 1px solid var(--sidebar-border);
        border-bottom: none;
        box-shadow: 18px 0 40px rgba(5,7,22,0.42);
        padding: 18px 14px calc(20px + var(--safe-area-bottom));
        transform: translateX(-105%);
        visibility: hidden;
        pointer-events: none;
        transition:
            transform var(--motion-med) var(--ease-premium),
            visibility 0s linear var(--motion-med);
        overflow-y: auto;
        overflow-x: hidden;
        overscroll-behavior-y: contain;
        -webkit-overflow-scrolling: touch;
        will-change: transform;
    }
    body.mobile-nav-open .sidebar {
        transform: translateX(0);
        visibility: visible;
        pointer-events: auto;
        transition:
            transform var(--motion-med) var(--ease-premium),
            visibility 0s linear 0s;
    }
    .sidebar-brand { padding: 8px; margin-bottom: 14px; }
    .sidebar-brand img { max-height: 48px; }
    .sidebar-section { margin: 14px 6px 8px; }
    .sidebar nav {
        display: block;
        gap: 0;
    }
    .sidebar nav a {
        padding: 11px 12px;
        font-size: var(--text-base);
        margin-bottom: 2px;
    }
    .sidebar nav a.active::before { display: none; }
    .sidebar-account {
        position: sticky;
        bottom: 0;
        background: rgba(11, 14, 38, 0.96);
        -webkit-backdrop-filter: blur(8px);
        backdrop-filter: blur(8px);
        margin: 12px -4px -4px;
        padding: 12px;
        z-index: 1;
    }
}

/* Mobile bottom navigation — 5 thumb-friendly destinations on phones. */
.mobile-bottom-nav { display: none; }
@media (max-width: 900px) {
    .mobile-bottom-nav {
        position: fixed;
        bottom: 0; left: 0; right: 0;
        z-index: 8000;
        background: rgba(var(--glass-rgb), 0.96);
        -webkit-backdrop-filter: blur(14px) saturate(160%);
        backdrop-filter: blur(14px) saturate(160%);
        border-top: 1px solid var(--border);
        display: grid;
        grid-auto-flow: column;
        grid-auto-columns: 1fr;
        align-items: stretch;
        padding: 4px max(8px, env(safe-area-inset-left, 0px)) max(6px, env(safe-area-inset-bottom, 0px)) max(8px, env(safe-area-inset-right, 0px));
        box-shadow: 0 -4px 18px rgba(11,11,47,0.07);
    }
    .mobile-bottom-nav a,
    .mobile-bottom-nav button {
        position: relative;
        background: transparent;
        border: none;
        cursor: pointer;
        text-decoration: none;
        color: var(--muted);
        font-family: inherit;
        font-size: 10.5px;
        font-weight: 600;
        letter-spacing: 0.005em;
        line-height: 1.05;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 3px;
        padding: 8px 4px 6px;
        border-radius: 10px;
        min-width: 0;
        transition:
            color var(--motion-fast) var(--ease-out),
            background var(--motion-fast) var(--ease-out);
    }
    .mobile-bottom-nav a .jags-icon,
    .mobile-bottom-nav button .jags-icon { width: 22px; height: 22px; opacity: 0.85; }
    .mobile-bottom-nav a .label,
    .mobile-bottom-nav button .label {
        max-width: 100%;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .mobile-bottom-nav a:hover,
    .mobile-bottom-nav button:hover {
        color: var(--primary);
        background: rgba(90,121,165,0.06);
    }
    .mobile-bottom-nav a:hover .jags-icon,
    .mobile-bottom-nav button:hover .jags-icon { opacity: 1; }
    .mobile-bottom-nav a.active { color: var(--primary); }
    .mobile-bottom-nav a.active .jags-icon { opacity: 1; }
    /* The "More" button opens the drawer; reflect that open state so the
       active destination in the bar is never ambiguous. aria-expanded is
       toggled in JS (see #jags-mobile-more handlers). */
    .mobile-bottom-nav #jags-mobile-more[aria-expanded="true"] { color: var(--primary); }
    .mobile-bottom-nav #jags-mobile-more[aria-expanded="true"] .jags-icon { opacity: 1; }
    .mobile-bottom-nav a.active::before {
        content: "";
        position: absolute;
        top: 0; left: 22%; right: 22%;
        height: 3px; border-radius: 0 0 3px 3px;
        background: var(--grad-jags);
    }
    .mobile-bottom-nav a:focus-visible,
    .mobile-bottom-nav button:focus-visible {
        outline: none;
        box-shadow: 0 0 0 3px rgba(90,121,165,0.40);
    }
    /* Reserve space below content so the bottom bar never covers actions. */
    .main > .content { padding-bottom: var(--mobile-bottom-nav-clearance); }
}

/* Hide mobile chrome on print and on wallboard / display pages. */
@media print {
    .mobile-bottom-nav,
    .mobile-drawer-backdrop,
    .mobile-nav-toggle { display: none !important; }
    body.mobile-nav-open .sidebar { transform: none !important; box-shadow: none !important; }
    body.mobile-nav-open { overflow: visible !important; }
}
.display-shell .mobile-bottom-nav,
.display-shell .mobile-drawer-backdrop,
.display-shell .mobile-nav-toggle { display: none !important; }

/* Tighter card/grid rhythm on phones. */
@media (max-width: 700px) {
    .stats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-bottom: 14px; }
    .stat { padding: 12px 14px; border-radius: 12px; }
    .stat .value { font-size: 21px; }
    .stat .label { font-size: 10.5px; }
    .stat .delta { font-size: 11px; }
    .card { padding: 14px; border-radius: 12px; }
    .card + .card { margin-top: 14px; }
    .card-hero { padding: 18px 16px 20px; border-radius: 14px; }
    .card-hero h2 { font-size: 22px; line-height: 1.2; }
    .card-hero p { font-size: 13.5px; }
    .ac-grid { grid-template-columns: 1fr; gap: 12px; }
    .ac-card { padding: 14px; }
    .ac-card .reg { font-size: 19px; }
    .ac-card .actions { flex-wrap: wrap; gap: 6px; }
    .ac-card .actions .btn { flex: 1 1 110px; justify-content: center; }
    .form-actions { flex-wrap: wrap; gap: 8px; }
    .form-actions .btn { flex: 1 1 140px; justify-content: center; }
    .form-actions .btn-block { flex-basis: 100%; }
    .topbar { padding: 8px 12px; gap: 8px; }
    .topbar h1 {
        font-size: 15.5px;
        max-width: 100%;
        overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
        flex: 1 1 auto; min-width: 0;
    }
    .topbar-user { gap: 8px; }
    .dr-toolbar { padding: 12px 14px; gap: 8px; }
    .dr-toolbar .btn,
    .dr-toolbar a.btn { flex: 1 1 140px; justify-content: center; }
    .dr-toolbar > form { flex: 1 1 100%; }
    .dr-header { padding: 18px 16px; gap: 10px; }
    .dr-header .title { gap: 12px; }
    .dr-header .title img { width: 60px; height: 60px; }
    .dr-header h1 { font-size: 19px; }
    .dr-header .meta { text-align: left; font-size: 12.5px; }
    .dr-header .meta strong { font-size: 14px; }
    .ops-board-toolbar { padding: 10px 12px; gap: 6px; }
    .ops-board-toolbar .btn { flex: 1 1 130px; justify-content: center; }
    /* Single-column on phones: the label reads as a compact eyebrow directly
       above its value, with ONE dashed hairline between pairs. The base
       per-cell solid border-top is cleared here — in a stacked single column
       it would otherwise draw a stray rule between a label and its own value
       (the heavy "ladder" look). Desktop keeps its row rules; this is scoped
       to the phone breakpoint only. */
    .kv { grid-template-columns: 1fr; gap: 0; }
    .kv .k { font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; border-top: none; padding: 9px 0 1px; }
    .kv .v { border-top: none; padding: 0 0 9px; border-bottom: 1px dashed var(--border); }
    .kv .k:last-of-type + .v { border-bottom: none; padding-bottom: 0; }
    .tabs { overflow-x: auto; flex-wrap: nowrap; }
    .tabs a { white-space: nowrap; padding: 9px 12px; font-size: 13px; }
}

/* Horizontal scroll hint chip for tables / boards that intentionally
   stay wide on mobile (Daily Report, Operations board, etc.). */
.mobile-scroll-hint { display: none; }
@media (max-width: 700px) {
    .mobile-scroll-hint {
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 8px 12px;
        background: rgba(90,121,165,0.08);
        border: 1px solid rgba(90,121,165,0.20);
        border-radius: 10px;
        color: var(--secondary);
        font-size: 12px;
        line-height: 1.4;
        margin-bottom: 10px;
    }
    .mobile-scroll-hint::before {
        content: "↔";
        font-size: 14px;
        font-weight: 700;
        color: var(--primary);
        flex: 0 0 auto;
    }
}
@media print {
    .mobile-scroll-hint { display: none !important; }
}

/* Sticky thumb-anchored action bar — opt-in, used by form pages
   (Update Flight Hours etc.) so the primary CTA is always reachable. */
.sticky-mobile-actions { display: contents; }
@media (max-width: 700px) {
    .sticky-mobile-actions {
        position: sticky;
        bottom: calc(var(--mobile-bottom-nav-footprint) + 16px);
        z-index: 100;
        background: rgba(var(--glass-rgb), 0.96);
        -webkit-backdrop-filter: blur(14px) saturate(160%);
        backdrop-filter: blur(14px) saturate(160%);
        margin: 14px -14px -14px;
        padding: 12px 14px max(12px, env(safe-area-inset-bottom, 0px));
        border-top: 1px solid var(--border);
        border-bottom-left-radius: 12px;
        border-bottom-right-radius: 12px;
        display: flex; gap: 8px; flex-wrap: wrap;
    }
    .sticky-mobile-actions .btn { flex: 1 1 auto; justify-content: center; }
}
@media print {
    .sticky-mobile-actions { position: static !important; padding: 0 !important; margin: 0 !important; background: none !important; border: none !important; }
}

/* Mobile card list — pages that opt in render a desktop .table-wrap.desktop-only
   plus a parallel .mobile-card-list.mobile-only built from the same data. */
.mobile-card-list { display: none; }
@media (max-width: 700px) {
    .mobile-card-list { display: grid; gap: 10px; }
    .mobile-card-list-item {
        background: var(--card);
        border: 1px solid var(--border);
        border-radius: 12px;
        padding: 12px 14px;
        box-shadow: var(--shadow-sm);
    }
    .mobile-card-list-item .head {
        display: flex; align-items: baseline; justify-content: space-between;
        gap: 10px; margin-bottom: 6px;
    }
    .mobile-card-list-item .head .reg {
        font-size: 17px; font-weight: 700;
        color: var(--primary); letter-spacing: -0.02em;
    }
    .mobile-card-list-item .row {
        display: flex; justify-content: space-between; gap: 12px;
        font-size: 12.75px;
        padding: 4px 0;
    }
    .mobile-card-list-item .row + .row { border-top: 1px dashed var(--border); padding-top: 6px; }
    .mobile-card-list-item .row .k { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; }
    .mobile-card-list-item .row .v { font-weight: 600; text-align: right; min-width: 0; }
    .mobile-card-list-item .actions {
        display: flex; gap: 6px; margin-top: 10px; flex-wrap: wrap;
    }
    .mobile-card-list-item .actions .btn { flex: 1 1 auto; justify-content: center; padding: 8px 10px; }
}

/* Cascade fix: .mobile-only sets `display: revert !important;` below 900px,
   which would otherwise revert .mobile-card-list back to its default block
   layout (since !important on a shorthand-equivalent declaration wins).
   Re-pin grid + spacing for the combined selector so card lists keep the
   intended grid rhythm on phones and small tablets. */
@media (max-width: 900px) {
    .mobile-card-list.mobile-only {
        display: grid !important;
        gap: 10px;
    }
}

/* Walkthrough as a bottom sheet on phones — ensures the highlighted target
   is visible above the card and tap targets are large. */
@media (max-width: 700px) {
    .jags-tour-card.is-mobile-bottom {
        position: fixed !important;
        left: 12px !important;
        right: 12px !important;
        bottom: calc(12px + var(--safe-area-bottom)) !important;
        top: auto !important;
        width: auto !important;
        max-width: none !important;
        max-height: 70vh !important;
        overflow-y: auto !important;
        border-radius: 18px;
    }
    .jags-tour-card.is-mobile-bottom .jags-tour-actions {
        flex-direction: row;
        flex-wrap: wrap;
        gap: 8px;
        padding: 14px 16px 16px;
    }
    .jags-tour-card.is-mobile-bottom .jags-tour-actions .nav-group { width: 100%; gap: 8px; }
    .jags-tour-card.is-mobile-bottom .jags-tour-actions .nav-group .btn { flex: 1; }
    .jags-tour-card.is-mobile-bottom .jags-tour-actions .btn { padding: 11px 14px; font-size: 13.5px; min-height: 42px; }
    .jags-tour-card.is-mobile-bottom .jags-tour-body { padding: 14px 16px 4px; }
    .jags-tour-card.is-mobile-bottom .jags-tour-body h3 { font-size: 17px; }
    .jags-tour-card.is-mobile-bottom .jags-tour-body p { font-size: 13.5px; }
    .jags-tour-card.is-mobile-bottom .jags-tour-head { padding: 14px 16px 8px; }
    .jags-tour-card.is-mobile-bottom .jags-tour-progress { margin: 0 16px; }
    .jags-tour-card.is-mobile-bottom .jags-tour-dots { padding: 8px 16px 0; }
}

/* ====================================================================
   Navigation polish — page-leave fade + thin top progress bar.
   The progress bar element is rendered by layout_footer() and toggled
   via the .visible class. Browser navigation does the heavy lifting;
   this layer just gives instant click feedback and a subtle "loading"
   hint on slower transitions.
   ==================================================================== */
.jags-nav-progress {
    position: fixed;
    top: 0; left: 0; right: 0;
    height: 2px;
    z-index: 9999;
    pointer-events: none;
    background: rgba(23,23,86,0.06);
    opacity: 0;
    transition: opacity var(--motion-fast) var(--ease-out);
    overflow: hidden;
}
.jags-nav-progress::before {
    content: "";
    position: absolute;
    top: 0; bottom: 0; left: 0;
    width: 38%;
    background: linear-gradient(90deg, transparent 0%, var(--secondary) 25%, var(--primary) 50%, var(--secondary) 75%, transparent 100%);
    box-shadow: 0 0 8px rgba(23, 23, 86, 0.32);
    transform: translateX(-110%);
    will-change: transform;
}
.jags-nav-progress.visible { opacity: 1; }
.jags-nav-progress.visible::before {
    animation: jagsNavSlide 1100ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
@keyframes jagsNavSlide {
    0%   { transform: translateX(-110%); }
    100% { transform: translateX(360%); }
}

/* Page-leave fade — kept very gentle so navigation never feels slower.
   Only the page content fades; topbar / sidebar / drawer / bottom nav
   stay fully opaque so the user keeps their bearings. The arrival side
   is handled by the existing .jagsPageIn entrance animation.
   `animation: none` is required because .main > .content has the entrance
   animation in `fill-mode: both`, whose held final-frame opacity:1 would
   otherwise win the cascade against this declaration. */
body.is-navigating .main > .content {
    animation: none;
    opacity: 0.62;
    transition: opacity 140ms var(--ease-out);
}

/* Print + display board safety — never animate, never show the bar. */
@media print {
    .jags-nav-progress { display: none !important; }
    body.is-navigating .main > .content { opacity: 1 !important; transition: none !important; }
}
.display-shell .jags-nav-progress { display: none !important; }

/* Reduced motion — keep the bar visible (so users still see *something*
   on slow loads) but stop the animation. Skip the leave fade entirely. */
@media (prefers-reduced-motion: reduce) {
    .jags-nav-progress.visible::before {
        animation: none !important;
        transform: translateX(0) !important;
        width: 100% !important;
        opacity: 0.55;
    }
    body.is-navigating .main > .content {
        opacity: 1 !important;
        transition: none !important;
    }
}

/* ------------------------------------------------------------------
   PWA install affordance.
   The trigger elements are always in the DOM but hidden by default.
   pwa-install.js sets one of these classes on <html>:
     .pwa-installable  beforeinstallprompt fired (Android, Desktop)
     .pwa-ios          iOS Safari (use Add-to-Home-Screen modal)
     .pwa-installed    already running standalone — hide everything
   ------------------------------------------------------------------ */
.jags-pwa-install-pill,
.jags-pwa-install-card { display: none; }

html.pwa-installable .jags-pwa-install-pill,
html.pwa-ios         .jags-pwa-install-pill { display: inline-flex; }

html.pwa-installable .jags-pwa-install-card,
html.pwa-ios         .jags-pwa-install-card { display: flex; }

html.pwa-installed .jags-pwa-install-pill,
html.pwa-installed .jags-pwa-install-card,
html.pwa-installed #jags-pwa-ios-modal { display: none !important; }

/* Instruction-modal copy is platform-aware: the default/iOS list shows the
   Safari Share-sheet steps; html.pwa-android (set by pwa-install.js on any
   non-iOS device) swaps in the Chrome ⋮-menu steps. Only the FALLBACK path
   ever opens this modal on Android — when beforeinstallprompt fired, the
   Install button triggers the native prompt instead. */
.jags-pwa-steps-android { display: none; }
html.pwa-android .jags-pwa-steps-ios { display: none; }
html.pwa-android .jags-pwa-steps-android { display: block; }

/* ------------------------------------------------------------------
   Public auth-shell install banner (login / register / pending …).
   The signed-in shell has a topbar pill + drawer card, but a brand-new
   staff member on the sign-up page had NO install affordance at all in
   Chrome on Android — Samsung Internet / Firefox surface their own
   install UI for any site with a manifest, which is why staff were told
   to "use a different browser to download the app". This banner gives
   Chrome (and iOS Safari) users the same one-tap install path before
   they ever sign in.
   Hidden by default; shown only when pwa-install.js marks the page
   installable (or iOS), never once installed, dismissible (14 days,
   body.jags-pwa-banner-dismissed via localStorage), and phone/tablet
   only — desktop keeps the uncluttered auth card.
   ------------------------------------------------------------------ */
.jags-pwa-auth-banner { display: none; }
html.pwa-installable body:not(.jags-pwa-banner-dismissed) .jags-pwa-auth-banner,
html.pwa-ios         body:not(.jags-pwa-banner-dismissed) .jags-pwa-auth-banner { display: flex; }
html.pwa-installed .jags-pwa-auth-banner { display: none !important; }
/* While the fixed banner is visible, reserve scroll room at the page bottom
   so it can never sit over the last tappable element (e.g. the final
   department card or the page footer links). */
@media (max-width: 900.98px) {
    html.pwa-installable body:not(.jags-pwa-banner-dismissed),
    html.pwa-ios         body:not(.jags-pwa-banner-dismissed) {
        padding-bottom: calc(110px + env(safe-area-inset-bottom, 0px));
    }
    html.pwa-installed body { padding-bottom: 0; }
}
.jags-pwa-auth-banner {
    position: fixed;
    left: 12px; right: 12px;
    bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    z-index: 8500; /* above page content, below the install modal (9000) */
    max-width: 480px;
    margin: 0 auto;
    align-items: center;
    gap: 12px;
    background: var(--card);
    border: 1px solid rgba(23, 23, 86, 0.14);
    border-radius: 14px;
    box-shadow: 0 12px 32px rgba(8, 10, 24, 0.18);
    padding: 10px 12px;
}
.jags-pwa-auth-banner__icon {
    flex: 0 0 auto;
    width: 38px; height: 38px;
    border-radius: 10px;
    background: var(--primary, #171756);
    color: #fff;
    display: inline-flex; align-items: center; justify-content: center;
}
.jags-pwa-auth-banner__text { flex: 1 1 auto; min-width: 0; }
.jags-pwa-auth-banner__title {
    display: block;
    font-size: 13.5px; font-weight: 700; color: var(--primary, #171756);
    line-height: 1.25;
}
.jags-pwa-auth-banner__sub {
    display: block;
    font-size: 12px; color: #5E6472; line-height: 1.3; margin-top: 1px;
}
.jags-pwa-auth-banner__btn {
    flex: 0 0 auto;
    border: 0;
    border-radius: 999px;
    background: var(--primary, #171756);
    color: #fff;
    font-size: 12.5px; font-weight: 700;
    padding: 9px 16px;
    cursor: pointer;
    line-height: 1;
}
.jags-pwa-auth-banner__btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(23, 23, 86, 0.30);
}
.jags-pwa-auth-banner__dismiss {
    flex: 0 0 auto;
    border: 0; background: none;
    color: #8A90A0;
    font-size: 18px; line-height: 1;
    padding: 6px;
    margin-left: -4px;
    cursor: pointer;
}
@media (min-width: 901px) {
    /* Desktop keeps the clean auth card; the signed-in topbar pill covers
       desktop installs. */
    .jags-pwa-auth-banner { display: none !important; }
}

/* Topbar pill — desktop and tablet only. The drawer card replaces it on
   small screens so the topbar stays uncluttered on phones. */
.jags-pwa-install-pill {
    align-items: center;
    gap: 6px;
    padding: 6px 12px 6px 10px;
    border: 1px solid rgba(23, 23, 86, 0.18);
    border-radius: 999px;
    background: rgba(23, 23, 86, 0.04);
    color: var(--primary, #171756);
    font-size: 12.5px;
    font-weight: 600;
    letter-spacing: 0.005em;
    cursor: pointer;
    line-height: 1;
    transition: background-color 120ms ease, border-color 120ms ease, transform 120ms ease, box-shadow 120ms ease;
}
.jags-pwa-install-pill:hover {
    background: rgba(23, 23, 86, 0.10);
    border-color: rgba(23, 23, 86, 0.32);
    transform: translateY(-1px);
    box-shadow: 0 2px 6px rgba(23, 23, 86, 0.12);
}
.jags-pwa-install-pill:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(23, 23, 86, 0.30);
}
.jags-pwa-install-pill__icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 16px; height: 16px;
}
.jags-pwa-install-pill__label { white-space: nowrap; }

/* Below 900px the topbar gets crowded; the drawer card carries the action. */
@media (max-width: 900px) {
    html.pwa-installable .jags-pwa-install-pill,
    html.pwa-ios         .jags-pwa-install-pill { display: none; }
}

/* Drawer card — sits between Workspace nav and Account, inside the slide-in
   drawer on mobile and the static sidebar on desktop. */
.jags-pwa-install-card {
    align-items: center;
    gap: 10px;
    margin: 14px 14px 6px;
    padding: 10px 12px;
    background: linear-gradient(180deg, rgba(23, 23, 86, 0.06), rgba(23, 23, 86, 0.02));
    border: 1px solid rgba(23, 23, 86, 0.14);
    border-radius: 12px;
    color: var(--text, #1a1a1a);
}
.jags-pwa-install-card__icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px;
    border-radius: 8px;
    background: var(--primary, #171756);
    color: #fff;
    flex: 0 0 auto;
}
.jags-pwa-install-card__body { min-width: 0; flex: 1 1 auto; }
.jags-pwa-install-card__title {
    font-size: 13px; font-weight: 700;
    color: var(--text-strong, #0e0e22);
    line-height: 1.2;
}
.jags-pwa-install-card__sub {
    font-size: 11.5px; color: var(--muted, #6b6b7a);
    line-height: 1.3; margin-top: 2px;
}
.jags-pwa-install-card__btn {
    flex: 0 0 auto;
    padding: 6px 12px;
    border: 0;
    border-radius: 8px;
    background: var(--primary, #171756);
    color: #fff;
    font-size: 12px; font-weight: 600;
    cursor: pointer;
    transition: background-color 120ms ease, transform 120ms ease;
}
.jags-pwa-install-card__btn:hover { background: #0f0f3f; transform: translateY(-1px); }
.jags-pwa-install-card__btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(23, 23, 86, 0.35);
}
/* Dark-rail context — the install card lives inside the navy .sidebar, so
   its light gradient + dark title would vanish/clash. Re-tone it for dark.
   Scoped to .sidebar so the card stays light if ever reused on a light
   surface. The install PILL (.jags-pwa-install-pill) lives in the light
   topbar and is intentionally untouched. */
.sidebar .jags-pwa-install-card {
    background: rgba(255, 255, 255, 0.05);
    border-color: var(--sidebar-border);
    color: var(--sidebar-text);
}
.sidebar .jags-pwa-install-card__icon {
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
}
.sidebar .jags-pwa-install-card__title { color: #fff; }
.sidebar .jags-pwa-install-card__sub { color: var(--sidebar-muted); }
.sidebar .jags-pwa-install-card__btn {
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
}
.sidebar .jags-pwa-install-card__btn:hover { background: rgba(255, 255, 255, 0.22); }

/* iOS instruction modal — shown only when the user taps the install
   trigger on iOS. */
#jags-pwa-ios-modal[hidden] { display: none; }
#jags-pwa-ios-modal {
    position: fixed; inset: 0;
    z-index: 9000;
    display: flex; align-items: center; justify-content: center;
    padding: 16px;
}
.jags-pwa-modal-backdrop {
    position: absolute; inset: 0;
    background: rgba(8, 10, 24, 0.55);
    backdrop-filter: blur(2px);
}
.jags-pwa-modal-dialog {
    position: relative;
    max-width: 380px; width: 100%;
    background: var(--card);
    border-radius: 16px;
    box-shadow: 0 24px 60px rgba(8, 10, 24, 0.35);
    padding: 22px 22px 18px;
    color: var(--text, #1a1a1a);
}
.jags-pwa-modal-dialog__header {
    display: flex; align-items: center; gap: 12px; margin-bottom: 10px;
}
.jags-pwa-modal-dialog__logo {
    width: 40px; height: 40px;
    border-radius: 10px;
    background: var(--primary, #171756);
    color: #fff;
    display: inline-flex; align-items: center; justify-content: center;
    flex: 0 0 auto;
}
.jags-pwa-modal-dialog__title {
    font-size: 16px; font-weight: 700;
    color: var(--text-strong, #0e0e22);
    line-height: 1.25;
}
.jags-pwa-modal-dialog__steps {
    margin: 8px 0 14px;
    padding: 0; list-style: none;
    font-size: 13.5px; line-height: 1.45;
    color: var(--text, #1a1a1a);
}
.jags-pwa-modal-dialog__steps li {
    padding: 6px 0;
    border-top: 1px dashed rgba(23, 23, 86, 0.18);
    display: flex; align-items: center; gap: 10px;
}
.jags-pwa-modal-dialog__steps li:first-child { border-top: 0; }
.jags-pwa-modal-dialog__steps .glyph {
    flex: 0 0 auto;
    width: 26px; height: 26px;
    border-radius: 6px;
    background: rgba(23, 23, 86, 0.08);
    color: var(--primary, #171756);
    display: inline-flex; align-items: center; justify-content: center;
}
.jags-pwa-modal-dialog__hint {
    font-size: 11.5px; color: var(--muted, #6b6b7a);
    margin-bottom: 14px;
}
.jags-pwa-modal-dialog__actions {
    display: flex; justify-content: flex-end;
}
.jags-pwa-modal-dialog__close {
    padding: 8px 16px;
    border: 0;
    border-radius: 8px;
    background: var(--primary, #171756);
    color: #fff;
    font-size: 13px; font-weight: 600;
    cursor: pointer;
}
.jags-pwa-modal-dialog__close:hover { background: #0f0f3f; }
.jags-pwa-modal-dialog__close:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(23, 23, 86, 0.35);
}
body.jags-pwa-modal-lock { overflow: hidden; }

/* Crew display lines (Captain / Co-pilot) */
.crew-line { line-height: 1.4; white-space: nowrap; }
.crew-role { font-weight: 600; color: var(--muted); font-size: 0.92em; }

/* Grounding info block on aircraft profile */
.grounding-info { padding: 12px 14px; border-left: 4px solid var(--danger); background: rgba(142,34,38,0.04); border-radius: 8px; margin-bottom: 14px; }
.grounding-info-badge { display: inline-block; margin-bottom: 6px; }
.grounding-info-reason { font-weight: 600; margin-bottom: 4px; }
.grounding-info-note { margin-bottom: 4px; white-space: pre-wrap; }
.grounding-info-meta { font-size: 12px; color: var(--muted); }
.grounding-info-override { margin-top: 8px; padding: 8px 10px; background: rgba(210,160,40,0.08); border-radius: 6px; font-size: 13px; }
.grounding-reason-link { color: var(--primary); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.grounding-reason-link:hover { color: var(--accent, #3367d6); }

/* =====================================================================
   Feature 08 — Special Request Type badges + subtle row/card highlights
   --------------------------------------------------------------------
   "Subtle" per spec means a small badge OR a 4px left-border accent.
   No loud full-card colour tints. Scoped to .rsv-srt-* and .rsv-card-hl-*
   so these rules cannot bleed into existing card / table styles.
   Accent colours reuse the existing palette (var(--danger), var(--info),
   var(--warning), var(--success)).
   ===================================================================== */
.rsv-srt-badge {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 6px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.4;
    white-space: nowrap;
    border: 1px solid transparent;
    background: rgba(94, 100, 114, 0.10);
    color: var(--muted-strong);
}
.rsv-srt-medevac    { background: rgba(184,50,53,0.10); color: var(--status-danger-ink); border-color: rgba(184,50,53,0.30); }
.rsv-srt-vip        { background: rgba(216,181,109,0.18); color: var(--status-warning-ink); border-color: rgba(216,181,109,0.42); }
.rsv-srt-government { background: rgba(90,121,165,0.14); color: var(--status-info-ink); border-color: rgba(90,121,165,0.35); }
.rsv-srt-cargo      { background: rgba(74,103,51,0.12); color: var(--status-success-ink); border-color: rgba(74,103,51,0.35); }
.rsv-srt-default    { background: rgba(94,100,114,0.10); color: var(--muted-strong); }

/* 4px left-border accent for cards that carry a highlighted special-request
   type. Sits on the card; never paints the whole background.  */
.rsv-card-hl                   { border-left: 4px solid var(--muted); }
.rsv-card-hl-medevac           { border-left-color: var(--danger); }
.rsv-card-hl-vip               { border-left-color: var(--warning); }
.rsv-card-hl-government        { border-left-color: var(--info); }
.rsv-card-hl-cargo             { border-left-color: var(--success); }

/* Same accent for table rows on the Reservations / Operations Intake
   lists. Uses an inset box-shadow so the table's own borders stay intact. */
.rsv-row-hl > td:first-child            { box-shadow: inset 4px 0 0 0 var(--muted); }
.rsv-row-hl-medevac > td:first-child    { box-shadow: inset 4px 0 0 0 var(--danger); }
.rsv-row-hl-vip > td:first-child        { box-shadow: inset 4px 0 0 0 var(--warning); }
.rsv-row-hl-government > td:first-child { box-shadow: inset 4px 0 0 0 var(--info); }
.rsv-row-hl-cargo > td:first-child      { box-shadow: inset 4px 0 0 0 var(--success); }

/* Mobile collapse for the new fieldset on the reservation form. */
@media (max-width: 700px) {
    .rsv-pax-cargo-group [style*="grid-template-columns:1fr 1fr 1fr"] { grid-template-columns: 1fr !important; }
    .rsv-pax-cargo-group [style*="grid-column:span 2"]               { grid-column: 1 / -1 !important; }
}

/* =====================================================================
   Feature 04 — Reservation lifecycle status badges
   --------------------------------------------------------------------
   Canonical reservation statuses each get their own muted badge. Scoped
   to .rsv-status-* so the rules cannot leak into other badges. Emphasis
   is "subtle" per the canonical CSS rule — small badges, no loud full
   card colour tints.
   Color mapping per Feature 04 spec:
     Draft                  : neutral / grey
     Pending Review         : info blue
     Customer Confirmed     : success green
     Sent to Operations     : indigo / operations blue
     Returned to Reservations: amber
     Scheduled              : darker success green
     Unavailable            : amber / warning
     Cancelled              : danger
     Completed              : slate / neutral
   ===================================================================== */
.rsv-status-badge {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 6px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.4;
    white-space: nowrap;
    border: 1px solid transparent;
    background: rgba(94, 100, 114, 0.10);
    color: var(--muted-strong);
}
.rsv-status-default            { background: rgba(94,100,114,0.10); color: var(--muted-strong); }
.rsv-status-draft              { background: rgba(94,100,114,0.10); color: var(--muted-strong); }
.rsv-status-pending-review     { background: rgba(90,121,165,0.14); color: var(--status-info-ink); border-color: rgba(90,121,165,0.30); }
.rsv-status-customer-confirmed { background: rgba(74,103,51,0.12);  color: var(--status-success-ink); border-color: rgba(74,103,51,0.30); }
.rsv-status-sent-to-operations { background: rgba(72,82,135,0.14);  color: var(--muted-strong); border-color: rgba(72,82,135,0.32); }
.rsv-status-returned           { background: rgba(216,181,109,0.18);color: var(--status-warning-ink); border-color: rgba(216,181,109,0.42); }
.rsv-status-scheduled          { background: rgba(48,80,38,0.14);   color: #294019; border-color: rgba(48,80,38,0.32); }
.rsv-status-unavailable        { background: rgba(216,181,109,0.18);color: var(--status-warning-ink); border-color: rgba(216,181,109,0.42); }
.rsv-status-cancelled          { background: rgba(184,50,53,0.10);  color: var(--danger); border-color: rgba(184,50,53,0.30); }
.rsv-status-completed          { background: rgba(94,100,114,0.14); color: var(--muted-strong); border-color: rgba(94,100,114,0.30); }

/* "Needs Operations Review" pill — only used inside the Unavailable
   review card on the reservation view + Operations Intake. */
.rsv-status-needs-review {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 6px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.02em;
    background: rgba(182,136,58,0.18);
    color: var(--status-warning-ink);
    border: 1px solid rgba(182,136,58,0.42);
}

/* =====================================================================
   Feature 02 — Requested Aircraft Type + Advisory Availability Preview
   --------------------------------------------------------------------
   Subtle pill for the requested aircraft type plus a read-only card
   grid for the advisory preview. Rules are scoped to .rsv-acft-* and
   .rsv-availability-* so they cannot bleed into existing card / table
   styles. No loud full-card colour tints — see the canonical CSS rule
   in CANONICAL_NAMING_AND_SHARED_CONTRACTS.md §9.
   ===================================================================== */
.rsv-acft-type-pill {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 6px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.4;
    white-space: nowrap;
    border: 1px solid rgba(72,82,135,0.32);
    background: rgba(72,82,135,0.10);
    color: var(--muted-strong);
}
.rsv-acft-type-pill-backup {
    background: rgba(94,100,114,0.10);
    color: var(--muted-strong);
    border-color: rgba(94,100,114,0.30);
}
.rsv-acft-type-pill-prominent {
    /* Used in the Operations intake hero so the requested type catches
       the eye without overpowering the special-request-type badge. */
    background: rgba(48,80,38,0.12);
    color: #294019;
    border-color: rgba(48,80,38,0.34);
}

/* Advisory availability preview frame on the reservation form. */
.rsv-availability {
    background: rgba(247, 249, 252, 0.6);
    border-radius: 8px;
    padding: 12px;
}
.rsv-availability-warning {
    margin: 10px 0 0 0;
    padding: 8px 10px;
    background: rgba(182,136,58,0.10);
    border: 1px solid rgba(182,136,58,0.35);
    border-radius: 6px;
    font-size: 13px;
    color: var(--status-warning-ink);
}

/* Card grid for individual aircraft. */
.rsv-availability-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 10px;
}
.rsv-acft-card {
    display: flex;
    align-items: stretch;
    gap: 10px;
    padding: 10px;
    border: 1px solid rgba(0,0,0,0.08);
    border-radius: 8px;
    background: var(--card);
}
.rsv-acft-card-available    { border-left: 4px solid var(--success, #4A7B33); }
.rsv-acft-card-unavailable  {
    border-left: 4px solid rgba(184,50,53,0.55);
    /* Subtle dim — never paint the whole card. */
    opacity: 0.78;
    background: rgba(247, 249, 252, 0.85);
}
.rsv-acft-thumb {
    flex: 0 0 56px;
    width: 56px;
    height: 56px;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(94,100,114,0.08);
    display: flex;
    align-items: center;
    justify-content: center;
}
.rsv-acft-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.rsv-acft-card-body {
    flex: 1 1 auto;
    min-width: 0;
}
.rsv-acft-card-head {
    display: flex;
    align-items: baseline;
    gap: 6px;
    flex-wrap: wrap;
}
.rsv-acft-reg {
    font-weight: 700;
    font-size: 13px;
    letter-spacing: 0.02em;
    color: var(--text, #0E0E12);
}
.rsv-acft-status {
    margin-top: 4px;
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    align-items: center;
}
.rsv-acft-status-pill {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 5px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.4;
    border: 1px solid transparent;
    background: rgba(94,100,114,0.10);
    color: var(--muted-strong);
}
.rsv-acft-status-serviceable        { background: rgba(74,103,51,0.12);  color: var(--status-success-ink); border-color: rgba(74,103,51,0.30); }
.rsv-acft-status-grounded           { background: rgba(184,50,53,0.10);  color: var(--danger); border-color: rgba(184,50,53,0.30); }
.rsv-acft-status-maintenance        { background: rgba(216,181,109,0.18);color: var(--status-warning-ink); border-color: rgba(216,181,109,0.42); }
.rsv-acft-status-inspection_required{ background: rgba(216,181,109,0.18);color: var(--status-warning-ink); border-color: rgba(216,181,109,0.42); }
.rsv-acft-status-inactive           { background: rgba(94,100,114,0.14); color: var(--muted-strong); border-color: rgba(94,100,114,0.30); }
.rsv-acft-unavail-pill {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 5px;
    font-size: 11px;
    font-weight: 600;
    background: rgba(184,50,53,0.10);
    color: var(--danger);
    border: 1px solid rgba(184,50,53,0.30);
}

/* =====================================================================
   2026-05-14 inline-workflow refinement — filter chip bar, assigned-
   aircraft chip on the Reservations list, delay-status chip, and the
   per-row inline-action chips on the Accounts dashboard.
   --------------------------------------------------------------------
   Scoped to .rsv-chip*, .rsv-aircraft-chip, .rsv-delay-chip and
   .rsv-chip-action / .rsv-inline-* so the rules cannot bleed into
   existing badge / button styles. Reuses the existing palette tokens
   (var(--primary), var(--danger), var(--warning), var(--success),
   var(--muted-strong)).
   ===================================================================== */

/* Quick-view filter chip bar — sits above the standard filter form on
   Reservations, Accounts dashboard, and Operations intake. */
.rsv-filter-chips { background: rgba(247,249,252,0.6); }
.rsv-chip {
    display: inline-block;
    padding: 5px 12px;
    border-radius: 999px;
    border: 1px solid rgba(0,0,0,0.12);
    background: var(--card);
    color: var(--text, #0E0E12);
    font-size: 13px;
    font-weight: 600;
    line-height: 1.3;
    text-decoration: none;
    transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.rsv-chip:hover  { background: rgba(0,0,0,0.04); border-color: rgba(0,0,0,0.22); }
.rsv-chip-active {
    background: var(--primary, #1F3F6E);
    color: #FFFFFF;
    border-color: var(--primary, #1F3F6E);
}
.rsv-chip-active:hover { background: var(--primary, #1F3F6E); color: #FFFFFF; }

/* Assigned-aircraft chip on the Reservations list — read-only. */
.rsv-aircraft-chip {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 5px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.02em;
    background: rgba(31,63,110,0.10);
    color: var(--primary, #1F3F6E);
    border: 1px solid rgba(31,63,110,0.30);
    font-variant-numeric: tabular-nums;
}

/* Delay status chip under the reservation status badge. */
.rsv-delay-chip {
    display: inline-block;
    padding: 1px 7px;
    border-radius: 4px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.4;
    border: 1px solid transparent;
}
.rsv-delay-on-time   { background: rgba(74,103,51,0.10);   color: var(--status-success-ink);       border-color: rgba(74,103,51,0.30); }
.rsv-delay-delayed   { background: rgba(184,50,53,0.10);   color: var(--danger); border-color: rgba(184,50,53,0.30); }
.rsv-delay-awaiting  { background: rgba(216,181,109,0.18); color: var(--status-warning-ink);       border-color: rgba(216,181,109,0.42); }
.rsv-delay-weather   { background: rgba(94,100,114,0.12);  color: var(--muted-strong);       border-color: rgba(94,100,114,0.30); }
.rsv-delay-cancelled { background: rgba(184,50,53,0.10);   color: var(--danger); border-color: rgba(184,50,53,0.30); }

/* Inline action chips on the Accounts dashboard. Four small buttons +
   a collapsed sticky-note. Mobile usable; the row wraps naturally. */
.rsv-inline-actions { display: inline-block; }
.rsv-inline-actions-row {
    display: inline-flex;
    gap: 4px;
    flex-wrap: wrap;
    align-items: center;
}
.rsv-inline-action-form { margin: 0; padding: 0; }
.rsv-chip-action {
    display: inline-block;
    padding: 4px 10px;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.3;
    border: 1px solid transparent;
    cursor: pointer;
    background: var(--card);
    color: var(--text, #0E0E12);
    transition: background 0.12s, border-color 0.12s;
}
.rsv-chip-action:hover    { background: rgba(0,0,0,0.04); }
.rsv-chip-action:disabled { opacity: 0.45; cursor: not-allowed; }
.rsv-chip-clear  { background: rgba(74,103,51,0.10);   color: var(--status-success-ink);       border-color: rgba(74,103,51,0.32); }
.rsv-chip-clear:hover  { background: rgba(74,103,51,0.18); }
.rsv-chip-hold   { background: rgba(216,181,109,0.18); color: var(--status-warning-ink);       border-color: rgba(216,181,109,0.45); }
.rsv-chip-hold:hover   { background: rgba(216,181,109,0.30); }
.rsv-chip-block  { background: rgba(184,50,53,0.10);   color: var(--danger); border-color: rgba(184,50,53,0.32); }
.rsv-chip-block:hover  { background: rgba(184,50,53,0.18); }
.rsv-chip-review { background: rgba(31,63,110,0.10);   color: var(--primary, #1F3F6E); border-color: rgba(31,63,110,0.30); }
.rsv-chip-review:hover { background: rgba(31,63,110,0.18); }

/* =====================================================================
   2026-05-20 — Passenger / cargo / payment / capacity refinement.
   Scoped to .rsv-pay-chip*, .rsv-capacity-*, .rsv-sector-card,
   .rsv-pax-row, .rsv-cargo-row and .rsv-inline-form. Cannot touch
   existing badge / chip rules.
   ===================================================================== */
.rsv-pay-chip {
    display: inline-block;
    padding: 2px 9px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: 0.02em;
    border: 1px solid transparent;
    font-variant-numeric: tabular-nums;
}
.rsv-pay-unpaid   { background: rgba(184,50,53,0.10);   color: var(--danger);            border-color: rgba(184,50,53,0.30); }
.rsv-pay-paid     { background: rgba(74,103,51,0.10);   color: var(--status-success-ink);                  border-color: rgba(74,103,51,0.32); }
.rsv-pay-company  { background: rgba(31,63,110,0.10);   color: var(--primary, #1F3F6E);  border-color: rgba(31,63,110,0.30); }
.rsv-pay-waived   { background: rgba(94,100,114,0.12);  color: var(--muted-strong);                  border-color: rgba(94,100,114,0.30); }
.rsv-pay-refunded { background: rgba(216,181,109,0.18); color: var(--status-warning-ink);                  border-color: rgba(216,181,109,0.42); }

.rsv-capacity-card { border-left: 4px solid var(--primary, #1F3F6E); }
.rsv-capacity-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 12px;
    margin-top: 8px;
}
.rsv-capacity-tile {
    background: rgba(31,63,110,0.05);
    border: 1px solid rgba(31,63,110,0.12);
    border-radius: 8px;
    padding: 10px 12px;
}
.rsv-capacity-num {
    font-size: 22px; font-weight: 700; line-height: 1.2; margin-top: 2px;
    font-variant-numeric: tabular-nums;
}
.rsv-capacity-num .muted { font-size: 16px; font-weight: 500; }
.rsv-capacity-pill {
    display: inline-block;
    margin-top: 6px;
    padding: 2px 9px;
    border-radius: 999px;
    font-size: 11px; font-weight: 600;
    border: 1px solid transparent;
}
.rsv-capacity-ok       { background: rgba(74,103,51,0.10);   color: var(--status-success-ink);       border-color: rgba(74,103,51,0.32); }
.rsv-capacity-over     { background: rgba(184,50,53,0.10);   color: var(--danger); border-color: rgba(184,50,53,0.30); }
.rsv-capacity-locked   { background: rgba(216,181,109,0.18); color: var(--status-warning-ink);       border-color: rgba(216,181,109,0.42); }
.rsv-capacity-unlocked { background: rgba(94,100,114,0.10);  color: var(--muted-strong);       border-color: rgba(94,100,114,0.30); }
.rsv-capacity-note {
    border-top: 1px dashed rgba(0,0,0,0.08);
    padding-top: 8px;
    font-size: 13px;
}

.rsv-sector-card {
    border: 1px solid rgba(0,0,0,0.08);
    border-radius: 10px;
    padding: 12px 14px;
    margin-bottom: 14px;
    background: var(--card);
}
.rsv-sector-outbound   { border-left: 4px solid var(--primary, #1F3F6E); }
.rsv-sector-return     { border-left: 4px solid #6E4A8F; }
.rsv-sector-unassigned { border-left: 4px solid rgba(94,100,114,0.45); }
.rsv-sector-head {
    display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
    margin-bottom: 6px; padding-bottom: 6px;
    border-bottom: 1px solid rgba(0,0,0,0.06);
}
.rsv-sector-head h3 { margin: 0; font-size: 16px; font-weight: 700; }

.rsv-pax-row, .rsv-cargo-row {
    padding: 8px 10px;
    border-radius: 6px;
    margin-bottom: 6px;
    border: 1px solid rgba(0,0,0,0.04);
    background: rgba(31,63,110,0.03);
}
.rsv-cargo-row { background: rgba(216,181,109,0.06); }
.rsv-pax-main, .rsv-cargo-main { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 6px; }
.rsv-pax-name, .rsv-cargo-desc { font-weight: 600; font-size: 14px; }
.rsv-pax-side  { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.rsv-attached-cargo { margin: 0 0 6px 14px; padding-left: 8px; border-left: 2px dashed rgba(216,181,109,0.5); }
.rsv-standalone-cargo { margin-top: 6px; padding-top: 4px; }
.rsv-add-form summary {
    cursor: pointer; font-weight: 600; font-size: 13px;
    color: var(--primary, #1F3F6E);
}
.rsv-inline-form .rsv-inline-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 0 12px;
}
.rsv-inline-form .field { margin-bottom: 8px; }
.rsv-sector-quick, .rsv-link-quick {
    padding: 4px 6px;
    border-radius: 4px;
    border: 1px solid rgba(0,0,0,0.15);
    font-size: 12px;
}
.rsv-remove-btn { color: var(--danger); border-color: rgba(184,50,53,0.25); }
.rsv-pax-pay-action summary {
    cursor: pointer; font-size: 12px; font-weight: 600;
    color: var(--primary, #1F3F6E);
}
/* 2026-08-12 — one-click "Mark Paid" sitting beside the payment chip.
   Its own <form>, a sibling of the move-sector / remove forms, so it
   never nests inside another form. */
.rsv-pay-quick { display: inline-flex; margin: 0; }
.rsv-pay-quick-btn {
    padding: 3px 10px;
    font-size: 11px;
    line-height: 1.5;
    min-height: 28px;
    white-space: nowrap;
}

@media (max-width: 700px) {
    .rsv-capacity-grid { grid-template-columns: 1fr; }
    .rsv-pax-main, .rsv-cargo-main { flex-direction: column; align-items: stretch; }
    .rsv-pax-side  { justify-content: flex-start; }
    .rsv-pay-quick-btn { min-height: 34px; padding: 6px 12px; font-size: 12px; }
    .rsv-inline-form .rsv-inline-grid { grid-template-columns: 1fr; }
}

/* =====================================================================
   Reservations / Ops-intake mobile card list (2026-05-18)
   ---------------------------------------------------------------------
   The Reservations board and the Operations intake queue render a
   desktop .table-wrap.desktop-only AND a parallel
   .mobile-card-list.mobile-only.rsv-mobile-list built from the same
   data. These rules ONLY refine that mobile card on phones / tablets
   (<=900px). They build on the shared .mobile-card-list-item chrome
   (defined earlier) and are prefixed with .rsv-mobile-list so they
   cannot touch the desktop table or any other page. Desktop (>=901px)
   is byte-for-byte unchanged.
   ===================================================================== */
@media (max-width: 900px) {
    /* Reference is a single nowrap monospace badge — fixes the
       "RSV-\n2026-\n00085" hyphen-wrap seen on the squeezed table. */
    .rsv-mc-ref {
        display: inline-block;
        font-family: "SF Mono", ui-monospace, Menlo, Consolas, monospace;
        font-size: 12.5px; font-weight: 700; letter-spacing: 0.01em;
        color: var(--primary, #1F3F6E);
        background: rgba(31,63,110,0.08);
        border: 1px solid rgba(31,63,110,0.20);
        border-radius: 6px;
        padding: 3px 8px;
        white-space: nowrap;
    }
    .rsv-mobile-list .head {
        align-items: center;
        gap: 8px;
        flex-wrap: wrap;
        margin-bottom: 8px;
        padding-bottom: 8px;
        border-bottom: 1px solid var(--border);
    }
    .rsv-mc-status {
        display: inline-flex;
        flex-wrap: wrap;
        gap: 4px;
        justify-content: flex-end;
        text-align: right;
        min-width: 0;
    }
    .rsv-mc-customer {
        font-size: 15px;
        font-weight: 700;
        line-height: 1.3;
        color: var(--text-strong, #14223B);
        margin: 0 0 8px;
        overflow-wrap: anywhere;
    }
    /* Let long values (route, multi-line times) wrap inside the card
       instead of forcing horizontal overflow. */
    .rsv-mobile-list .row { align-items: flex-start; }
    .rsv-mobile-list .row .v { overflow-wrap: anywhere; }
    .rsv-mobile-list .row .v.rsv-mc-route { font-weight: 600; }
    /* Action buttons: full-width, comfortable tap targets, forms (Archive
       / Restore) stretch like the anchor buttons next to them. */
    .rsv-mc-actions {
        margin-top: 12px;
        gap: 8px;
        justify-content: stretch;
    }
    .rsv-mc-actions > a.btn,
    .rsv-mc-actions > form {
        flex: 1 1 auto;
        margin: 0;
    }
    .rsv-mc-actions > form { display: flex; }
    .rsv-mc-actions > form .btn,
    .rsv-mc-actions > form button { width: 100%; }
    .rsv-mc-actions .btn,
    .rsv-mc-actions .btn-sm { min-height: 44px; }
    /* Belt-and-suspenders: the global .main > .content already reserves
       space for the fixed bottom nav app-wide; this adds a little extra
       breathing room so the last card never visually meets the nav even
       mid-scroll, including the iPhone home-indicator safe area. */
    .rsv-mobile-list { padding-bottom: calc(var(--safe-area-bottom) + 8px); }
}

/* Sticky-note <details> embed inside the inline actions row. */
.rsv-inline-note-details { display: inline-block; margin-left: 4px; }
.rsv-inline-note-summary {
    display: inline-block;
    padding: 4px 10px;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.3;
    background: rgba(94,100,114,0.10);
    color: var(--muted-strong);
    border: 1px solid rgba(94,100,114,0.30);
    cursor: pointer;
    list-style: none;
}
.rsv-inline-note-summary::-webkit-details-marker { display: none; }
.rsv-inline-note-details[open] .rsv-inline-note-summary { background: rgba(94,100,114,0.18); }
.rsv-inline-note-body { margin-top: 6px; max-width: 320px; }
.rsv-inline-note-body textarea {
    width: 100%;
    font-size: 12px;
    padding: 6px 8px;
    border-radius: 4px;
    border: 1px solid rgba(0,0,0,0.16);
}

.rsv-acft-reasons {
    margin: 6px 0 0 16px;
    padding: 0;
    font-size: 12px;
    color: var(--muted-strong);
}

/* =====================================================================
   Feature 01 — Reservations Aircraft Availability (read-only)
   --------------------------------------------------------------------
   Scoped to .rsv-aa-* so the rules cannot bleed into the operations
   board or the reservation form. The Advisory caption uses a small
   pill / inset, never a loud full-card colour tint, per
   CANONICAL_NAMING_AND_SHARED_CONTRACTS.md §9. The Reservations-safe
   flight table reuses the existing .tbl / .tbl-compact base styles and
   only adds row-state shading and small pill colours.
   ===================================================================== */
.rsv-aa-advisory {
    align-self: stretch;
    padding: 10px 14px;
    border-radius: 8px;
    background: rgba(255,255,255,0.18);
    border: 1px solid rgba(255,255,255,0.35);
    color: #FFFFFF;
    font-size: 13px;
    line-height: 1.4;
    max-width: 360px;
}
.rsv-aa-advisory-sub {
    margin-top: 2px;
    font-size: 12px;
    opacity: 0.85;
    font-weight: 400;
}
.rsv-aa-row-cancelled    { opacity: 0.55; }
.rsv-aa-row-unavailable  { background: rgba(184,50,53,0.04); }
.rsv-aa-reg              { font-weight: 700; color: var(--primary); letter-spacing: 0.02em; }
.rsv-aa-sub              { font-size: 11px; line-height: 1.3; }
.rsv-aa-cell-time        { font-variant-numeric: tabular-nums; white-space: nowrap; }
.rsv-aa-charter          { font-weight: 600; }
.rsv-aa-pill {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 5px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.4;
    border: 1px solid transparent;
    background: rgba(94,100,114,0.10);
    color: var(--muted-strong);
    white-space: nowrap;
}
.rsv-aa-pill-success {
    background: rgba(74,103,51,0.12);
    color: var(--status-success-ink);
    border-color: rgba(74,103,51,0.30);
}
.rsv-aa-pill-muted {
    background: rgba(94,100,114,0.10);
    color: var(--muted-strong);
    border-color: rgba(94,100,114,0.22);
}
.rsv-aa-pill-warn {
    background: rgba(182,136,58,0.14);
    color: #7B5318;
    border-color: rgba(182,136,58,0.40);
}

/* Availability advisory last-updated strip — sits directly under the
   summary on the Reservations Aircraft Availability page. Quiet by
   default, switches to a warn tint when the underlying timestamp is
   older than 24 hours, and to a muted "missing" tint when no source
   returned a timestamp at all. */
.rsv-aa-lastupdated {
    margin-top: 10px;
    padding: 10px 14px;
    border-radius: 8px;
    border: 1px solid rgba(94,100,114,0.22);
    background: rgba(94,100,114,0.06);
    font-size: 13px;
    line-height: 1.4;
}
.rsv-aa-lastupdated-head {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.rsv-aa-lastupdated-label {
    color: var(--muted-strong);
}
.rsv-aa-lastupdated-value {
    font-variant-numeric: tabular-nums;
}
.rsv-aa-lastupdated-sub {
    margin-top: 2px;
    font-size: 12px;
    color: var(--muted-strong);
}
.rsv-aa-lastupdated-fresh {
    border-color: rgba(74,103,51,0.30);
    background: rgba(74,103,51,0.06);
}
.rsv-aa-lastupdated-stale {
    border-color: rgba(182,136,58,0.40);
    background: rgba(182,136,58,0.10);
}
.rsv-aa-lastupdated-missing {
    border-color: rgba(94,100,114,0.30);
    background: rgba(94,100,114,0.08);
}

/* Operations decision summary on the Reservations dashboard list. Tiny,
   informational; never overwrites or duplicates the canonical status
   badge shown in the same row. */
.rsv-ops-summary {
    margin-top: 4px;
    font-size: 11px;
    line-height: 1.35;
    color: var(--muted-strong);
}
.rsv-ops-summary-icon { margin-right: 4px; }

/* Mobile collapse for the new fieldset on the reservation form. */
@media (max-width: 700px) {
    .rsv-aircraft-type-group [style*="grid-template-columns:1fr 1fr"] { grid-template-columns: 1fr !important; }
    .rsv-availability-grid { grid-template-columns: 1fr !important; }
    .rsv-acft-card { padding: 8px; }
    .rsv-acft-thumb { width: 48px; height: 48px; flex-basis: 48px; }
    .rsv-aa-advisory { max-width: none; }
}

/* =====================================================================
   Feature 06 — Accounts / Cashier payment status badges
   --------------------------------------------------------------------
   Scoped to .pay-status-* so the rules cannot bleed into existing
   reservation status (.rsv-status-*) or special-request-type
   (.rsv-srt-*) badge styles. No loud full-card colour tints — small
   pills only, per CANONICAL_NAMING_AND_SHARED_CONTRACTS.md §9.
   ===================================================================== */
.pay-status-badge {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 6px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.4;
    white-space: nowrap;
    border: 1px solid transparent;
    background: rgba(94, 100, 114, 0.10);
    color: var(--muted-strong);
}
.pay-status-default          { background: rgba(94,100,114,0.10); color: var(--muted-strong); }
.pay-status-unpaid           { background: rgba(184,50,53,0.08);  color: var(--danger);       border-color: rgba(184,50,53,0.30); }
.pay-status-pending          { background: rgba(216,181,109,0.18);color: var(--status-warning-ink);             border-color: rgba(216,181,109,0.42); }
.pay-status-paid             { background: rgba(74,103,51,0.12);  color: var(--status-success-ink);             border-color: rgba(74,103,51,0.30); }
.pay-status-account-credit   { background: rgba(72,82,135,0.14);  color: var(--muted-strong);             border-color: rgba(72,82,135,0.32); }
.pay-status-waived           { background: rgba(94,100,114,0.14); color: var(--muted-strong);             border-color: rgba(94,100,114,0.30); }
.pay-status-refunded         { background: rgba(94,100,114,0.10); color: var(--muted-strong); border-color: rgba(94,100,114,0.22); }
.pay-status-disputed         { background: rgba(182,50,53,0.18);  color: var(--danger);       border-color: rgba(182,50,53,0.45); }

/* Accounts role chip — matches the role-badge variant key 'accounts'. */
.badge-role-accounts {
    background: rgba(72,82,135,0.10);
    color: var(--muted-strong);
    border: 1px solid rgba(72,82,135,0.32);
}

/* Subtle 4px left-border accent on the Payment card (no full-card tint). */
.pay-card { border-left: 4px solid rgba(72,82,135,0.32); }

@media (max-width: 700px) {
    .pay-summary-grid { grid-template-columns: 1fr !important; }
    .pay-record-form [style*="grid-template-columns:1fr 1fr 1fr"] { grid-template-columns: 1fr !important; }
}

/* =====================================================================
   Feature 05 — Operations Reservation Intake Refinement
   --------------------------------------------------------------------
   Scoped to .ops-intake-* so the rules cannot bleed into existing
   stat-grid, badge, or card styles. No loud full-card colour tints —
   small chips plus optional 4px left-border accents per the canonical
   styling rule (see CANONICAL_NAMING_AND_SHARED_CONTRACTS.md §9).
   ===================================================================== */

/* Aircraft-availability hint chip used in the intake list and card. */
.ops-intake-acft-warn {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 5px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
    border: 1px solid rgba(94,100,114,0.30);
    background: rgba(94,100,114,0.10);
    color: var(--muted-strong);
    white-space: normal;
    line-height: 1.35;
}
.ops-intake-acft-warn-info  { background: rgba(74,103,51,0.10);   color: var(--status-success-ink); border-color: rgba(74,103,51,0.30); }
.ops-intake-acft-warn-warn  { background: rgba(216,181,109,0.18); color: var(--status-warning-ink); border-color: rgba(216,181,109,0.42); }
.ops-intake-acft-warn-block { background: rgba(184,50,53,0.10);   color: var(--danger); border-color: rgba(184,50,53,0.30); }

/* Latest Operations decision chip — used in the intake list "Last
   Decision" column and on both the intake detail card and the
   read-only Reservations-side decision card. */
.ops-intake-decision-chip {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 5px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
    border: 1px solid rgba(72,82,135,0.32);
    background: rgba(72,82,135,0.10);
    color: var(--muted-strong);
}

/* Decision card subtle 4px left-border accent — shown on intake detail
   and on the Reservations-side read-only summary. Never a full tint. */
.ops-intake-decision-card { border-left: 4px solid rgba(72,82,135,0.32); }

/* Payment-warning card on the intake detail. Subtle amber accent. */
.ops-intake-pay-warn { border-left: 4px solid rgba(216,181,109,0.55); }

/* Operations dashboard "Reservation Intake" summary card. Reuses the
   look of .stats-grid / .stat without depending on those rules so a
   refactor of either does not silently break the intake summary. */
.ops-intake-summary-card { border-left: 4px solid rgba(72,82,135,0.32); }

.ops-intake-summary-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 10px;
    margin-top: 8px;
}
.ops-intake-summary-tile {
    padding: 12px 14px;
    border: 1px solid var(--border, rgba(0,0,0,0.08));
    border-radius: 8px;
    background: var(--surface, #FFFFFF);
}
.ops-intake-summary-label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted-strong);
}
.ops-intake-summary-value {
    font-size: 24px;
    font-weight: 700;
    line-height: 1.1;
    margin-top: 4px;
    color: var(--text-strong);
}
.ops-intake-summary-delta {
    margin-top: 2px;
    font-size: 11px;
    color: var(--muted);
}

/* "Warn" / "Info" tile variants — subtle left-border accent only. */
.ops-intake-tile-warn  { border-left: 4px solid rgba(216,181,109,0.55); }
.ops-intake-tile-info  { border-left: 4px solid rgba(72,82,135,0.40); }

@media (max-width: 700px) {
    .ops-intake-summary-grid { grid-template-columns: 1fr 1fr !important; }
}

/* =====================================================================
   Feature 07 — Customer Accounts / Credit Limits / Stop List
   --------------------------------------------------------------------
   Scoped to .cust-acct-* so the rules cannot bleed into Reservation
   status badges (.rsv-status-*), Payment status badges (.pay-status-*),
   or special-request-type badges (.rsv-srt-*). No loud full-card colour
   tints — small badges plus a tinted progress bar and a subtle 4px
   left-border accent on warning cards, per
   CANONICAL_NAMING_AND_SHARED_CONTRACTS.md §9.
   ===================================================================== */

/* Account status badges */
.cust-acct-status-badge {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 6px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.4;
    white-space: nowrap;
    border: 1px solid transparent;
    background: rgba(94, 100, 114, 0.10);
    color: var(--muted-strong);
}
.cust-acct-status-default     { background: rgba(94,100,114,0.10); color: var(--muted-strong); }
.cust-acct-status-normal      { background: rgba(74,103,51,0.12);  color: var(--status-success-ink);             border-color: rgba(74,103,51,0.30); }
.cust-acct-status-watch       { background: rgba(90,121,165,0.14); color: var(--status-info-ink);             border-color: rgba(90,121,165,0.32); }
.cust-acct-status-near-limit  { background: rgba(216,181,109,0.18);color: var(--status-warning-ink);             border-color: rgba(216,181,109,0.42); }
.cust-acct-status-on-hold     { background: rgba(184,50,53,0.10);  color: var(--danger);       border-color: rgba(184,50,53,0.30); }
.cust-acct-status-stop-list   { background: rgba(184,50,53,0.16);  color: var(--danger);       border-color: rgba(184,50,53,0.45); }
.cust-acct-status-inactive    { background: rgba(94,100,114,0.14); color: var(--muted-strong);             border-color: rgba(94,100,114,0.30); }

/* Credit progress bar */
.cust-acct-progress {
    position: relative;
    height: 8px;
    background: rgba(94, 100, 114, 0.10);
    border-radius: 6px;
    overflow: hidden;
    border: 1px solid rgba(0, 0, 0, 0.06);
}
.cust-acct-progress-large { height: 14px; }
.cust-acct-progress-bar {
    height: 100%;
    width: 0;
    background: var(--muted-strong);
    transition: width 200ms ease;
}
.cust-acct-progress-normal     .cust-acct-progress-bar { background: var(--status-success); }
.cust-acct-progress-watch      .cust-acct-progress-bar { background: #5A79A5; }
.cust-acct-progress-near       .cust-acct-progress-bar { background: var(--status-warning); }
.cust-acct-progress-over       .cust-acct-progress-bar { background: var(--danger, #B83235); }
.cust-acct-progress-stop                                { background: rgba(184, 50, 53, 0.16); }
.cust-acct-progress-stop       .cust-acct-progress-bar { background: var(--danger, #B83235); width: 100% !important; }
.cust-acct-progress-inactive                            { background: rgba(94, 100, 114, 0.14); }
.cust-acct-progress-inactive   .cust-acct-progress-bar { background: rgba(94, 100, 114, 0.55); width: 100% !important; }
.cust-acct-progress-empty                               { background: rgba(94, 100, 114, 0.06); }
.cust-acct-progress-empty      .cust-acct-progress-bar { background: rgba(94, 100, 114, 0.30); }

/* Inline warning panels — subtle 4px left-border accent only */
.cust-acct-warning {
    border-radius: 8px;
    padding: 12px 14px;
    border: 1px solid rgba(0, 0, 0, 0.06);
    background: rgba(247, 249, 252, 0.6);
    border-left: 4px solid rgba(94, 100, 114, 0.40);
}
.cust-acct-warning-block {
    border-left-color: var(--danger, #B83235);
    background: rgba(184, 50, 53, 0.05);
}
.cust-acct-warning-warn {
    border-left-color: rgba(216, 181, 109, 0.85);
    background: rgba(216, 181, 109, 0.08);
}
.cust-acct-warning-info {
    border-left-color: rgba(90, 121, 165, 0.55);
    background: rgba(90, 121, 165, 0.05);
}

/* Override-queue card — same accent system as the warning panel.
   Used in customer_account_overrides.php. */
.cust-acct-override-card {
    padding: 14px 16px;
    border: 1px solid rgba(0, 0, 0, 0.08);
    border-radius: 10px;
    background: var(--card);
    border-left: 4px solid var(--danger, #B83235);
}
.cust-acct-decision {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 5px;
    font-size: 11px;
    font-weight: 600;
    border: 1px solid transparent;
    background: rgba(94, 100, 114, 0.10);
    color: var(--muted-strong);
}
.cust-acct-decision-approved { background: rgba(74,103,51,0.12); color: var(--status-success-ink); border-color: rgba(74,103,51,0.30); }
.cust-acct-decision-rejected { background: rgba(184,50,53,0.10); color: var(--danger); border-color: rgba(184,50,53,0.30); }

@media (max-width: 700px) {
    .rsv-customer-account-group [style*="grid-template-columns:2fr 1fr"] { grid-template-columns: 1fr !important; }
}

/* ====================================================================
   Mobile app polish
   --------------------------------------------------------------------
   Final-pass refinements that build on the existing mobile layer.
   Sits last so its rules win for sub-900px breakpoints. Goal:
   smoother spacing, more comfortable touch targets, calmer headers,
   cleaner sticky surfaces, no horizontal page scroll except on tables
   that intentionally overflow. Desktop is untouched (rules are scoped
   to <=900px or <=700px).
   ==================================================================== */

/* Prevent any element from forcing a horizontal page scroll on phones —
   tables/scroll regions stay scrollable internally via their own wrappers
   (.table-wrap / .dr-scroll / .ops-board-scroll already opt in). */
@media (max-width: 900px) {
    html, body { overflow-x: hidden; }
    .main { min-width: 0; max-width: 100vw; }
    .main > .content { overflow-x: hidden; }
    .card, .stat, .ac-card, .mobile-card-list-item { max-width: 100%; }
    img, video { max-width: 100%; height: auto; }
}

/* Slightly more breathing room on phone content; tighten on small phones. */
@media (max-width: 900px) {
    .content { padding: 18px 16px; }
}
@media (max-width: 520px) {
    .content { padding: 14px 12px; }
}

/* Topbar — calmer rhythm on phones. Existing rules at line 4027 set
   the base; these refinements reduce the visual weight further on small
   phones so the page feels less crowded above the fold. */
@media (max-width: 700px) {
    .topbar { padding-top: 10px; padding-bottom: 10px; }
    .topbar h1 { font-size: 16px; letter-spacing: -0.01em; }
}
@media (max-width: 520px) {
    .topbar { padding: 9px 10px; gap: 6px; }
    .topbar h1 { font-size: 15px; }
    .topbar-user { gap: 6px; }
}

/* Section titles — keep heading + action button row from getting cramped
   on phones. Wrapping is allowed; the action drops to its own line below. */
@media (max-width: 700px) {
    .section-title { gap: 8px; margin-bottom: 12px; }
    .section-title h2 { font-size: 16px; line-height: 1.25; }
}

/* Touch targets — guarantee >=44px height on the most common controls.
   The .btn class is 44px tall by spec; this ensures inline anchors and
   icon buttons used in dense rows on mobile still hit that bar. */
@media (max-width: 900px) {
    .btn { min-height: 44px; }
    .btn-sm { min-height: 38px; }
    .btn-icon, button.btn-icon, a.btn-icon { min-width: 38px; min-height: 38px; }
    a.tab, .tabs a { min-height: 40px; display: inline-flex; align-items: center; }
    .topbar-bell { min-width: 38px; min-height: 38px; }
}

/* Form-actions row — when buttons stack, give them comfortable vertical
   rhythm. The existing rule already wraps and stretches; this just adds
   a min-height floor so a single-line CTA doesn't feel skinny on phones. */
@media (max-width: 700px) {
    .form-actions { gap: 10px; }
    .form-actions .btn { min-height: 44px; padding: 11px 14px; }
}

/* Smoother card spacing on phones — the existing rule sets 14px gap; on
   smaller screens drop a touch tighter so two stacked cards don't feel
   floaty against the bottom-nav. */
@media (max-width: 520px) {
    .card { padding: 13px; border-radius: 12px; }
    .card + .card { margin-top: 12px; }
    .stats-grid { gap: 8px; margin-bottom: 12px; }
    .stat { padding: 11px 12px; }
}

/* Tables / horizontal scroll regions — momentum scroll on iOS, soft
   scrollbars on iOS/Android. .table-wrap already has -webkit-overflow-
   scrolling; explicitly add it to the other intentional overflow wrappers
   used by Daily Report and the Operations board. */
.dr-scroll,
.ops-board-scroll {
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    scrollbar-color: rgba(39,66,112,0.30) transparent;
}
.dr-scroll::-webkit-scrollbar,
.ops-board-scroll::-webkit-scrollbar { height: 8px; }
.dr-scroll::-webkit-scrollbar-thumb,
.ops-board-scroll::-webkit-scrollbar-thumb { background: rgba(39,66,112,0.25); border-radius: 8px; }

/* Ensure long table rows wrap inside table-wrap rather than escaping the
   card on phones — keeps the page free of horizontal overflow when a
   single non-wrapping cell is wider than the viewport. */
@media (max-width: 700px) {
    .table-wrap { border-radius: 12px; }
}

/* Drawer polish — slightly larger nav rows on phones, snappier divider
   above the sticky account card so the bottom of the drawer reads as
   a separate, anchored element. */
@media (max-width: 900px) {
    .sidebar nav a {
        min-height: 44px;
        padding-top: 11px;
        padding-bottom: 11px;
    }
    .sidebar-account {
        border-top: 1px solid var(--border);
        box-shadow: 0 -4px 12px rgba(11,11,47,0.05);
    }
}

/* Bottom nav — guaranteed thumb-friendly height + a clear top hairline so
   the bar reads as anchored chrome rather than floating content. The bar
   already respects env(safe-area-inset-bottom); this ensures the visible
   tap area for each tab is at least 48px tall (icon + label + paddings). */
@media (max-width: 900px) {
    .mobile-bottom-nav a,
    .mobile-bottom-nav button {
        min-height: 48px;
    }
    .mobile-bottom-nav a:active,
    .mobile-bottom-nav button:active {
        background: rgba(90,121,165,0.10);
    }
    /* Reserved page-bottom padding adjusted slightly so a sticky button
       doesn't sit flush against the bottom nav on phones with no notch. */
    .main > .content { padding-bottom: var(--mobile-bottom-nav-clearance); }
}

/* ====================================================================
   Mobile / PWA top safe-area blur
   --------------------------------------------------------------------
   On phones (and especially the installed standalone PWA on iOS) we want
   the topbar to feel like a native app: its translucent frosted backing
   extends up into the iPhone notch / status-bar safe area so scrolled
   content visibly slides underneath a polished blur instead of meeting a
   hard white edge. Pure CSS — no extra DOM. The .topbar already has
   position: sticky, top: 0, a translucent background, and backdrop-
   filter; here we only deepen the frost on phones and add the safe-area
   inset padding so the blurred surface covers the notch.
   Desktop is intentionally unchanged. Display / FIDS surfaces (.display-
   shell) are scoped out via the existing chrome-hide rules at line 4003.
   ==================================================================== */
@media (max-width: 900px) {
    .topbar {
        /* Slightly stronger frost + softer hairline so the topbar reads
           as ambient chrome rather than a hard edge under scrolling. */
        background: rgba(var(--glass-rgb), 0.72);
        -webkit-backdrop-filter: saturate(180%) blur(18px);
        backdrop-filter: saturate(180%) blur(18px);
        border-bottom-color: rgba(226, 230, 238, 0.65);
        /* Extend the blurred surface into the iPhone notch / status-bar
           area. The visible content (h1, hamburger, bell, avatar) keeps
           its normal vertical padding; the inset is added on top. */
        padding-top: calc(10px + env(safe-area-inset-top));
        padding-left: max(14px, env(safe-area-inset-left));
        padding-right: max(14px, env(safe-area-inset-right));
    }
}
/* Slightly stronger frost when the app is launched from the home screen
   as an installed PWA — a touch more saturation so the topbar feels more
   "app native" against the device wallpaper / status bar. */
@media (display-mode: standalone) and (max-width: 900px) {
    .topbar {
        background: rgba(var(--glass-rgb), 0.66);
        -webkit-backdrop-filter: saturate(200%) blur(22px);
        backdrop-filter: saturate(200%) blur(22px);
    }
}
/* Display / wallboard surfaces opt out — those run fullscreen and have
   their own dark chrome at layout_display_open(). */
.display-shell .topbar { padding-top: 14px; background: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; }
/* Print: kill the inset (the topbar is already display:none in print). */
@media print {
    .topbar { padding-top: 14px !important; }
}

/* Press / pressed states — fingers expect a quick visual ack on tap. The
   .btn classes already scale down on :active; extend that to cards/list
   items that act as link surfaces (kept very subtle so it does not feel
   gamified). */
@media (max-width: 900px) {
    .ac-card:active,
    .mobile-card-list-item:active {
        transform: scale(0.997);
        transition: transform 80ms var(--ease-out);
    }
}

/* Page header / breadcrumbs — keep clean on mobile, no heavy wrapping. */
@media (max-width: 700px) {
    .breadcrumbs { font-size: 12px; gap: 4px; }
    .breadcrumbs li { white-space: nowrap; }
}

/* Sticky form-action bars — when both .form-actions.sticky and
   .sticky-mobile-actions are on the page (rare), make sure the
   bottom-nav clearance lifts the action bar by the full nav height. */
@media (max-width: 700px) {
    .form-actions.sticky { box-shadow: 0 -6px 18px rgba(11,11,47,0.08); }
}

/* Modal/popover surfaces — add a subtle scrollbar treatment on phones so
   long popovers do not look like they overflow the screen. */
@media (max-width: 700px) {
    .user-menu-popover,
    .bell-popover {
        -webkit-overflow-scrolling: touch;
    }
}

/* Hide tiny chevrons / decorative svgs that were tuned for desktop hover
   when the screen is small enough that they crowd labels. Scoped narrowly
   so functional icons remain visible. */
@media (max-width: 520px) {
    .topbar .topbar-user .who { display: none; }
}

/* ====================================================================
   PWA double-tap zoom guard
   --------------------------------------------------------------------
   The viewport allows accessibility zoom. WebKit (Safari, iOS WKWebView,
   the standalone PWA shell) still benefits from explicit touch behavior
   so double-taps on controls do not trigger accidental zoom. Apply
   element under the finger declares touch-action: manipulation. Apply
   this globally to interactive surfaces and the app shell so a stray
   double-tap on a card / background / button doesn't zoom the page.

   Inputs are deliberately NOT given touch-action:manipulation so text
   selection, contextual menus, and accessibility gestures still work.
   Inputs are already 16px on mobile so iOS does not auto-zoom on focus.

   Iframes and any future map containers are explicitly excluded so
   pinch-zoom inside them keeps working.
   ==================================================================== */
/* Scroll-root chain — allow vertical panning EXPLICITLY.
   `pan-y pinch-zoom` preserves accessibility zoom while restoring normal
   vertical page scroll. Children that need pinch / horizontal pan
   (inputs, iframes, .display-shell, .table-wrap, .dr-scroll,
   .ops-board-scroll, [data-allow-zoom]) re-enable it via the
   `touch-action:auto` rule just below. */
html,
body,
.app-shell,
.main,
.content {
    touch-action: pan-y pinch-zoom;
}

/* Interactive / tap + chrome surfaces — suppress double-tap-to-zoom WITHOUT
   costing a page scroll.

   IMPORTANT (Android scroll fix, 2026-05-19): content CONTAINERS
   (.card / .card-hero / .stat / .mobile-card-list-item / .ac-card) were
   deliberately REMOVED from this list. On Chromium (Android Chrome,
   Samsung Internet, Pixel, and the installed PWA's WebView) a touch that
   STARTS on an element carrying `touch-action: manipulation` inside a
   `pan-y` scroll-root chain fails to promote the gesture to a page
   scroll. Because cards fill almost the whole page, the finger almost
   always lands on one, so the page would not scroll. iOS WebKit is
   lenient here, which is why the earlier `pan-y` fix cured iOS but the
   Samsung/Pixel/Android symptom remained.
   Do NOT add the content containers back here.

   DO NOT "FOLLOW UP" BY NARROWING THIS VALUE (Android incident, 2026-07-26).
   During that incident these selectors were changed `manipulation` ->
   `pan-y pinch-zoom`, on the theory that the `pan-x` component was stopping a
   vertical gesture from promoting. That change was REVERTED, because it is
   provably incapable of fixing a scroll bug:

     - `manipulation` is exactly `pan-x pan-y pinch-zoom` (Chrome serialises
       the long form back to the keyword), so `pan-y pinch-zoom` is a strict
       SUBSET of it.
     - The effective touch-action is the INTERSECTION of the touched element
       and its ancestors up to the element implementing the gesture.
     - Therefore, for any ancestor chain C:
           manipulation ∩ C  ⊇  (pan-y pinch-zoom) ∩ C
       The narrower value can only ever permit LESS. It cannot enable a
       gesture that was previously blocked, in any engine, quirk or not.

   It also caused real regressions, each measured: mobile `.tabs` strips and
   `.page-header-actions` rows (both `overflow-x:auto`) could no longer be
   swiped sideways, and inside `.ua-scroll` (`touch-action:pan-x`) the
   intersection became EMPTY — a total dead zone where the finger did nothing
   in any direction. `pinch-zoom` is also a Chromium-only keyword, so on iOS
   Safari and Firefox the whole declaration was invalid and dropped, silently
   restoring double-tap-to-zoom on every link and button.

   `manipulation` is the correct value here: universally supported, suppresses
   double-tap zoom, and permits both pan axes plus pinch so it never traps a
   gesture. If a page "resists scrolling", look for a bare `touch-action:pan-x`
   on a horizontal rail (that DOES block vertical page scroll) — not here. */
.topbar,
.sidebar,
.mobile-drawer-backdrop,
.mobile-bottom-nav,
.mobile-nav-toggle,
.btn,
button,
a,
.tabs a,
.field-check {
    touch-action: manipulation;
}

/* Content tiles must scroll the page on Chromium/Android: pin them to the
   same vertical-pan behaviour as the scroll roots above so a finger that
   lands anywhere on a card still scrolls the page. */
.card,
.card-hero,
.stat,
.mobile-card-list-item,
.ac-card {
    touch-action: pan-y;
}

/* Restore default touch-action where pinch-zoom or full gesture support
   matters: text inputs (so iOS magnifier + selection works), content-
   editable surfaces, embedded boards, and any explicit map-like opt-in
   surface (data-allow-zoom). Tables also keep manipulation off so the
   horizontal-scroll affordance feels natural. */
input,
textarea,
select,
[contenteditable],
iframe,
.display-shell,
.display-shell *,
.table-wrap,
.dr-scroll,
.ops-board-scroll,
[data-allow-zoom],
[data-allow-zoom] * {
    touch-action: auto;
}

/* NOTE (2026-07-26): a rail-descendant opt-out rule used to live here. It
   existed only to undo the damage of narrowing the interactive selectors
   above, and was removed with that change. It was also structurally unsound:
   an allowlist of four rail classes cannot cover the ~30 horizontal scrollers
   in this app, 22 of which are inline `style="overflow-x:auto"` wrappers with
   no class to target at all. Now that the interactive rule is `manipulation`
   (which already permits pan-x), links inside every rail pan sideways without
   needing an opt-out. */

/* Belt-and-braces: kill the 300ms tap delay where any UA still applies
   one. Both rules together suppress the double-tap-to-zoom heuristic on
   the affected surfaces without disabling vertical scroll. */
a, button, .btn, .mobile-bottom-nav a, .mobile-bottom-nav button,
.mobile-nav-toggle, .topbar-bell, .btn-icon {
    -ms-touch-action: manipulation;
}

/* iOS auto-zoom protection — the .field inputs already use 16px on mobile.
   Catch the bulk-edit table inputs which intentionally drop to 12.5–13px
   on desktop so they do not also zoom the viewport on iOS when focused. */
@media (max-width: 700px) {
    .ops-bulk-table input[type=text],
    .ops-bulk-table input[type=time],
    .ops-bulk-table input[type=date],
    .ops-bulk-table input[type=number],
    .ops-bulk-table select,
    .ops-bulk-table .field-narrow input,
    .ops-bulk-table .field-narrow select {
        font-size: 16px;
        padding: 8px 10px;
        min-height: 40px;
    }
}

/* Tap highlight — replace the default heavy iOS gray flash with a calm
   brand-tinted ring so taps feel intentional, not jarring. */
a, button, .btn, .mobile-bottom-nav a, .mobile-bottom-nav button {
    -webkit-tap-highlight-color: rgba(39,66,112,0.12);
}

/* When a vertical scroll is in progress, prevent the topbar / drawer from
   bouncing past the page edge in the standalone PWA — keeps the chrome
   feeling anchored rather than rubber-banding away.

   MUST live on html (the root scroller), NEVER on body. The phone rule
   `html, body { overflow-x: hidden }` makes body its own scroll container,
   so `overscroll-behavior` on body became a MID-CHAIN boundary: a scroll
   starting over any wide table latched onto .table-wrap, could not move
   vertically, and the chain died at body before ever reaching the page
   scroller — every wide table was a full-size vertical-scroll dead zone in
   Chrome (measured 2026-08-10; the continuing "cannot scroll" reports on
   table-heavy pages). On the root, `contain` still suppresses rubber-band /
   pull-to-refresh past the page edge but leaves in-page chaining intact. */
@media (max-width: 900px) {
    html { overscroll-behavior-y: contain; }
    body { overscroll-behavior-y: auto; }
}

/* ====================================================================
   Quick-action cards + icon chips
   --------------------------------------------------------------------
   Reusable Apple-style "tile with leading icon, title, sub-line"
   pattern. Replaces the various inline `font-size:22px` glyph headers
   used across dashboard.php / technical_records.php / reports.php /
   exports.php. The tile is intentionally calm — soft surface lift on
   hover, subtle border-darken, no colour shift. The icon sits inside a
   small navy-tinted chip so it reads as intentional iconography rather
   than decoration.
   ==================================================================== */
.qa-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 12px;
}
a.qa-card, button.qa-card {
    display: flex; align-items: flex-start; gap: 12px;
    text-decoration: none; color: inherit;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 16px;
    box-shadow: var(--shadow-sm);
    cursor: pointer;
    text-align: left;
    font-family: inherit;
    transition:
        box-shadow var(--motion-med) var(--ease-soft),
        border-color var(--motion-med) var(--ease-soft),
        transform var(--motion-med) var(--ease-soft),
        background var(--motion-fast) var(--ease-out);
}
a.qa-card:hover, button.qa-card:hover {
    box-shadow: var(--shadow-md);
    border-color: rgba(39, 66, 112, 0.22);
    transform: translateY(-1px);
}
a.qa-card:focus-visible, button.qa-card:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(90, 121, 165, 0.40), var(--shadow-sm);
}
.qa-card .qa-icon {
    width: 38px; height: 38px;
    flex: 0 0 38px;
    border-radius: 10px;
    background: linear-gradient(180deg, rgba(39,66,112,0.10), rgba(39,66,112,0.04));
    color: var(--secondary);
    display: inline-flex; align-items: center; justify-content: center;
    transition: background var(--motion-fast) var(--ease-out), color var(--motion-fast) var(--ease-out);
}
.qa-card:hover .qa-icon {
    background: linear-gradient(180deg, rgba(39,66,112,0.16), rgba(39,66,112,0.07));
    color: var(--primary);
}
.qa-card .qa-icon svg { width: 20px; height: 20px; }
.qa-card .qa-body { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; }
.qa-card .qa-title {
    font-weight: 700;
    font-size: 14.5px;
    color: var(--text-strong);
    letter-spacing: -0.01em;
    line-height: 1.3;
}
.qa-card .qa-sub {
    margin-top: 3px;
    font-size: 12.5px;
    color: var(--muted);
    line-height: 1.45;
}
.qa-card .qa-meta {
    margin-top: 8px;
    font-size: 11px;
    color: var(--secondary);
    font-weight: 600;
}
/* Highlight variant — used to call out a single primary action in a row
   of quick-action cards (e.g. Update Flight Hours on TR). */
.qa-card.qa-card-primary {
    border-color: rgba(39, 66, 112, 0.32);
    box-shadow: 0 6px 18px rgba(39,66,112,0.10);
}
.qa-card.qa-card-primary .qa-icon {
    background: linear-gradient(180deg, var(--primary), var(--secondary));
    color: #fff;
}
.qa-card.qa-card-primary:hover .qa-icon {
    background: linear-gradient(180deg, var(--primary-hover), var(--primary));
    color: #fff;
}
.qa-card.qa-card-primary .qa-title { color: var(--primary); }
/* Disabled / setup-required variant — same layout, no hover lift. */
.qa-card.qa-card-disabled {
    cursor: default;
    opacity: 0.62;
    box-shadow: none;
}
.qa-card.qa-card-disabled:hover { transform: none; box-shadow: none; border-color: var(--border); }
.qa-card.qa-card-disabled:hover .qa-icon { background: linear-gradient(180deg, rgba(39,66,112,0.10), rgba(39,66,112,0.04)); color: var(--secondary); }
.qa-card .qa-pill {
    display: inline-flex; align-items: center;
    margin-top: 8px;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.012em;
    background: rgba(216,181,109,0.18);
    color: var(--status-warning-ink);
    border: 1px solid rgba(216,181,109,0.42);
}

/* ====================================================================
   Inline mini-charts (helpers.php → mini_bar_chart / mini_donut /
   mini_progress / mini_sparkline)
   --------------------------------------------------------------------
   Pure SVG, asset-free, semantic-colored. They sit ABOVE the existing
   tables, never replace them; tables remain the source of truth so a
   user with reduced motion / non-supporting browsers / print loses
   nothing.
   ==================================================================== */
.chart-card { padding: 18px 20px; }
.chart-card .chart-card-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; margin-bottom: 14px;
}
.chart-card .chart-card-head h3 {
    margin: 0;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--text-strong);
}
.chart-card .chart-card-head .meta {
    font-size: 12px;
    color: var(--muted);
    font-weight: 500;
    text-align: right;
}
.chart-grid-2 {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 14px;
}
@media (max-width: 900px) {
    .chart-grid-2 { grid-template-columns: minmax(0, 1fr); }
}
.chart-empty {
    display: flex; align-items: center; justify-content: center;
    min-height: 120px;
    color: var(--muted);
    font-size: 13px;
    text-align: center;
    padding: 16px;
    border: 1px dashed var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface-low);
}

/* Mini bar chart — horizontal bars with labels and trailing values. */
.mini-bar { display: block; max-width: 100%; }
.mini-bar .mb-label {
    fill: var(--muted-strong);
    font-size: 11.5px;
    font-weight: 600;
    font-family: var(--font-sans);
}
.mini-bar .mb-value {
    fill: var(--text-strong);
    font-size: 11.5px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    font-family: var(--font-mono);
}
.mini-bar .mb-track {
    fill: rgba(39,66,112,0.07);
}
.mini-bar .mb-fill                    { fill: var(--secondary); }
.mini-bar .mb-fill-primary            { fill: var(--secondary); }
.mini-bar .mb-fill-info               { fill: var(--info); }
.mini-bar .mb-fill-success            { fill: var(--status-success); }
.mini-bar .mb-fill-warn               { fill: var(--status-warning); }
.mini-bar .mb-fill-danger             { fill: var(--danger); }
.mini-bar .mb-fill-muted              { fill: rgba(94,100,114,0.55); }

/* Mini donut — segments around a centred total. */
.mini-donut { display: inline-block; }
.mini-donut .md-track    { stroke: rgba(39,66,112,0.10); }
.mini-donut .md-seg      { stroke: var(--secondary); }
.mini-donut .md-seg-primary { stroke: var(--secondary); }
.mini-donut .md-seg-info    { stroke: var(--info); }
.mini-donut .md-seg-success { stroke: var(--status-success); }
.mini-donut .md-seg-warn    { stroke: var(--status-warning); }
.mini-donut .md-seg-danger  { stroke: var(--danger); }
.mini-donut .md-seg-muted   { stroke: rgba(94,100,114,0.55); }
.mini-donut .md-center {
    fill: var(--text-strong);
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    font-family: var(--font-display);
}
.mini-donut .md-sub {
    fill: var(--muted);
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.10em;
    font-family: var(--font-sans);
}
.mini-donut-legend {
    display: flex; flex-wrap: wrap;
    gap: 6px 12px;
    margin-top: 8px;
    font-size: 12px;
    color: var(--muted-strong);
}
.mini-donut-legend .leg {
    display: inline-flex; align-items: center; gap: 6px;
    line-height: 1.3;
}
.mini-donut-legend .swatch {
    width: 9px; height: 9px;
    border-radius: 2px;
    background: var(--secondary);
    flex: 0 0 9px;
}
.mini-donut-legend .swatch.primary { background: var(--secondary); }
.mini-donut-legend .swatch.info    { background: var(--info); }
.mini-donut-legend .swatch.success { background: var(--status-success); }
.mini-donut-legend .swatch.warn    { background: var(--status-warning); }
.mini-donut-legend .swatch.danger  { background: var(--danger); }
.mini-donut-legend .swatch.muted   { background: rgba(94,100,114,0.55); }
.mini-donut-legend .v {
    font-variant-numeric: tabular-nums;
    color: var(--text-strong);
    font-weight: 600;
    margin-left: 2px;
}

/* Mini progress bar (used in inspection-burn / readiness panels). */
.mini-progress { display: block; }
.mini-progress .mp-track             { fill: rgba(39,66,112,0.10); }
.mini-progress .mp-fill              { fill: var(--secondary); }
.mini-progress .mp-fill-primary      { fill: var(--secondary); }
.mini-progress .mp-fill-info         { fill: var(--info); }
.mini-progress .mp-fill-success      { fill: var(--status-success); }
.mini-progress .mp-fill-warn         { fill: var(--status-warning); }
.mini-progress .mp-fill-danger       { fill: var(--danger); }

/* Sparkline. */
.mini-spark { display: inline-block; vertical-align: middle; }
.mini-spark .ms-line          { stroke: var(--secondary); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.mini-spark .ms-primary       { stroke: var(--secondary); }
.mini-spark .ms-info          { stroke: var(--info); }
.mini-spark .ms-success       { stroke: var(--status-success); }
.mini-spark .ms-warn          { stroke: var(--status-warning); }
.mini-spark .ms-danger        { stroke: var(--danger); }

/* KPI tile mini-trend row — small muted sparkline + delta caption inside
   the existing .stat tile. Opt-in via .stat .stat-trend wrapper. */
.stat .stat-trend {
    display: flex; align-items: center; gap: 8px;
    margin-top: 8px;
    font-size: 11.5px;
    color: var(--muted);
}
.stat .stat-trend .mini-spark { width: 80px; height: 22px; }

/* Reduced-motion already neutralises animation; no animation here. */
@media print {
    .mini-bar, .mini-donut, .mini-progress, .mini-spark {
        /* Print engine renders these as inline SVG with no extra
           treatment — no animation to suppress, but ensure the chart
           card title meta line stays legible. */
        color-adjust: exact !important;
        -webkit-print-color-adjust: exact !important;
    }
}

/* ====================================================================
   Page-section icon chip — small leading badge for card titles that
   carry an SVG icon. Uses the same `.ttl-icon` aesthetic used by
   `.av2-card-head` so all department cards now share one language.
   ==================================================================== */
.icon-chip {
    width: 32px; height: 32px;
    flex: 0 0 32px;
    border-radius: 9px;
    background: linear-gradient(180deg, rgba(39,66,112,0.10), rgba(39,66,112,0.04));
    color: var(--secondary);
    display: inline-flex; align-items: center; justify-content: center;
}
.icon-chip svg { width: 16px; height: 16px; }
.icon-chip.success { background: linear-gradient(180deg, rgba(74,103,51,0.14), rgba(74,103,51,0.05)); color: var(--status-success-ink); }
.icon-chip.warn    { background: linear-gradient(180deg, rgba(216,181,109,0.18), rgba(216,181,109,0.06)); color: var(--status-warning-ink); }
.icon-chip.danger  { background: linear-gradient(180deg, rgba(184,50,53,0.14), rgba(184,50,53,0.04)); color: var(--status-danger-ink); }
.icon-chip.info    { background: linear-gradient(180deg, rgba(90,121,165,0.16), rgba(90,121,165,0.05)); color: var(--status-info-ink); }

/* Card title row — pairs an icon chip with the title and a right-side
   meta string. Drop-in replacement for the existing `<div
   class="section-title">` pattern when an icon makes the card more
   scannable. */
.card-title-row {
    display: flex; align-items: center; gap: 12px;
    margin: 0 0 14px;
    flex-wrap: wrap;
}
.card-title-row .ct-text { display: flex; align-items: center; gap: 10px; min-width: 0; }
.card-title-row h2,
.card-title-row h3 {
    margin: 0;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: var(--text-strong);
}
.card-title-row .meta {
    font-size: 12px;
    color: var(--muted);
    font-weight: 500;
    margin-left: auto;
    text-align: right;
    flex-shrink: 0;
}

/* ====================================================================
   Impeccable UI polish — surgical premium refinements
   --------------------------------------------------------------------
   Final additive layer. Refines existing components without renaming
   or removing any prior rule. Uses higher specificity (or new opt-in
   classes) so existing pages render unchanged unless they adopt the
   helper. Everything here lives on top of the JAGS blue token system
   (--primary / --secondary / --info / --grad-jags). No new palette.
   ==================================================================== */

/* ---- 1) Stat tile severity rail. -----------------------------------
   The base .stat tile only re-tints the .value text on warn/danger/
   success. At a glance the grid reads flat. A 2px top accent rail (and
   a faint tinted left edge) gives the tile semantic weight without
   shouting. Tonally calibrated to the existing semantic palette. */
.stat { position: relative; }
.stat::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: transparent;
    border-top-left-radius: var(--radius);
    border-top-right-radius: var(--radius);
    transition: background var(--motion-fast) var(--ease-out);
    pointer-events: none;
}
.stat-success::before { background: linear-gradient(90deg, rgba(74,103,51,0.55), rgba(74,103,51,0.0)); }
.stat-warn::before    { background: linear-gradient(90deg, rgba(216,181,109,0.75), rgba(216,181,109,0.0)); }
.stat-danger::before  { background: linear-gradient(90deg, rgba(184,50,53,0.70),  rgba(184,50,53,0.0)); }
.stat-info::before    { background: linear-gradient(90deg, rgba(90,121,165,0.70), rgba(90,121,165,0.0)); }
/* Calm, JAGS-blue accent for tiles that want to register as "primary
   metric" rather than "alarm". Opt-in via .stat-primary. */
.stat-primary::before { background: linear-gradient(90deg, rgba(39,66,112,0.55),  rgba(39,66,112,0.0)); }

/* Small clickable label inside .stat .delta — already an <a> in most
   pages. Make the affordance crisper: subtle underline on hover,
   navy on focus. */
.stat .delta a {
    color: var(--secondary);
    font-weight: 600;
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: border-color var(--motion-fast) var(--ease-out), color var(--motion-fast) var(--ease-out);
}
.stat .delta a:hover { color: var(--primary); border-bottom-color: rgba(39,66,112,0.35); }
.stat .delta a:focus-visible { outline: none; box-shadow: var(--ring-focus); border-radius: 3px; }

/* ---- 2) Hero action buttons. ----------------------------------------
   Pages emit white-on-gradient buttons inside .card-hero with inline
   styles (Operations, Reservations dashboards). Centralise: any .btn
   that lives inside .card-hero .hero-actions, or carries .btn-on-hero,
   picks up the white/translucent treatment automatically. Existing
   inline styles still win, so this is purely opt-in for future pages. */
.card-hero .hero-actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.btn-on-hero,
.card-hero .hero-actions .btn-ghost {
    background: rgba(255,255,255,0.16);
    color: #fff;
    border-color: rgba(255,255,255,0.32);
}
.btn-on-hero:hover,
.card-hero .hero-actions .btn-ghost:hover {
    background: rgba(255,255,255,0.26);
    color: #fff;
    border-color: rgba(255,255,255,0.45);
}
.btn-on-hero-primary,
.card-hero .hero-actions .btn-primary {
    background: var(--card);
    color: var(--primary);
    border-color: #fff;
    font-weight: 700;
    box-shadow: 0 6px 18px rgba(0,0,0,0.16);
}
.btn-on-hero-primary:hover,
.card-hero .hero-actions .btn-primary:hover {
    background: #F2F4FA;
    color: var(--primary-hover);
    border-color: #F2F4FA;
}

/* ---- 3) Chart-empty refinement. ------------------------------------
   Default .chart-empty uses a dashed border that subliminally reads
   "broken / placeholder". Replace with a small icon-chip-style empty
   that reads as "intentionally minimal". Existing markup unchanged. */
.chart-empty {
    border: 1px solid var(--border);
    background: linear-gradient(180deg, var(--surface-low), #fff);
    color: var(--muted);
    font-weight: 500;
    border-radius: var(--radius);
    min-height: 140px;
}
.chart-empty::before {
    content: "";
    display: block;
    width: 28px; height: 28px;
    margin: 0 auto 8px;
    border-radius: 9px;
    background: linear-gradient(180deg, rgba(39,66,112,0.08), rgba(39,66,112,0.02));
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23274270' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='13' width='6' height='8' rx='1'/%3E%3Crect x='10' y='9' width='6' height='12' rx='1'/%3E%3Crect x='17' y='5' width='4' height='16' rx='1'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 16px 16px;
    opacity: 0.85;
}
.chart-empty { flex-direction: column; }

/* ---- 4) Alert polish. ----------------------------------------------
   Strengthen the visual semantic weight: a 3px left rail and a tighter
   icon-bound layout. Backwards-compatible — existing .alert content
   continues to render. */
.alert {
    position: relative;
    overflow: hidden;
}
.alert::before {
    content: "";
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: var(--info);
    border-top-left-radius: var(--radius);
    border-bottom-left-radius: var(--radius);
}
.alert-success::before, .alert.success::before { background: var(--success); }
.alert-warn::before,    .alert.warn::before,
.alert-warning::before, .alert.warning::before { background: var(--warning); }
.alert-danger::before,  .alert.danger::before  { background: var(--danger); }
.alert-info::before,    .alert.info::before    { background: var(--info); }

/* ---- 5) Inline KPI delta pill. -------------------------------------
   Used by analytics to surface "+2.3 pts since Jan", "Latest month"
   captions, etc. Cleaner than the inline <div style="font-size:11px;
   text-transform:uppercase;..."> pattern repeated in analytics.php. */
.kpi-pill {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.012em;
    line-height: 1.4;
    background: rgba(90,121,165,0.10);
    color: var(--secondary);
    border: 1px solid rgba(90,121,165,0.22);
    font-variant-numeric: tabular-nums lining-nums;
    white-space: nowrap;
}
.kpi-pill.success { background: rgba(74,103,51,0.12);  color: var(--status-success-ink); border-color: rgba(74,103,51,0.32); }
.kpi-pill.warn    { background: rgba(216,181,109,0.18); color: var(--status-warning-ink); border-color: rgba(216,181,109,0.42); }
.kpi-pill.danger  { background: rgba(184,50,53,0.12);  color: var(--status-danger-ink); border-color: rgba(184,50,53,0.32); }
.kpi-pill.muted   { background: rgba(94,100,114,0.10); color: var(--muted-strong); border-color: rgba(94,100,114,0.22); }
/* Dark theme flips the pills to light ink on dark tints (same treatment as
   .badge-* above) — the light-ink hexes fail contrast on dark surfaces. */
html[data-theme="dark"] .kpi-pill.success { background: rgba(127,176,105,0.18); color: #A9D392; border-color: rgba(127,176,105,0.35); }
html[data-theme="dark"] .kpi-pill.warn    { background: rgba(224,178,92,0.20);  color: #E6C078; border-color: rgba(224,178,92,0.38); }
html[data-theme="dark"] .kpi-pill.danger  { background: rgba(224,121,123,0.18); color: #EDA0A2; border-color: rgba(224,121,123,0.35); }
html[data-theme="dark"] .kpi-pill.muted   { background: rgba(162,170,192,0.14); color: var(--muted); border-color: rgba(162,170,192,0.28); }
.kpi-pill .lbl {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.10em;
    color: inherit;
    opacity: 0.72;
    font-weight: 700;
}

/* Metric-trend row — pairs a label + value + sparkline in one calm
   horizontal strip. Drop-in replacement for the
       <div style="display:flex; align-items:center; gap:14px;">…</div>
   pattern in analytics.php. */
.metric-trend {
    display: flex; align-items: center; gap: 14px;
    flex-wrap: wrap;
}
.metric-trend .mt-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.metric-trend .mt-lbl {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.10em;
    color: var(--muted);
    font-weight: 700;
}
.metric-trend .mt-val {
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.1;
    color: var(--text-strong);
    font-variant-numeric: tabular-nums lining-nums;
}
.metric-trend .mt-sub { font-size: 12px; color: var(--muted); }

/* ---- 6) Compact stat grid. -----------------------------------------
   technical_records.php inlines a denser stat grid (140px minmax) for
   the Compliance Board counts. Surface that as a token so any page
   showing 5+ small counters can opt in via .stats-grid.stats-grid-tight
   or the freestanding .stats-grid-compact. */
.stats-grid-compact {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 12px;
    margin-bottom: 18px;
}
.stats-grid.stats-grid-tight {
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 12px;
}

/* ---- 7) Section eyebrow refinement. --------------------------------
   .section-title h2 is good, but the surrounding spacing reads slightly
   loose at the top of a card on busy pages. Tighten the rhythm by 2px
   and add a discreet underline on the section meta on hover (when it's
   a link). No effect on plain spans. */
.section-title { margin-bottom: 12px; }
.section-title a.muted {
    border-bottom: 1px solid transparent;
    transition: color var(--motion-fast) var(--ease-out), border-color var(--motion-fast) var(--ease-out);
}
.section-title a.muted:hover { color: var(--secondary); border-bottom-color: rgba(39,66,112,0.30); }

/* ---- 8) Sidebar group section header polish. -----------------------
   In nav.nav-grouped, the .nav-group-section labels are calm but read
   slightly disconnected. Add a 1px hairline lead-in so each department
   group reads as a coherent block on the sidebar. */
.sidebar nav.nav-grouped .nav-group-section {
    position: relative;
}
.sidebar nav.nav-grouped .nav-group-section::before {
    content: "";
    display: inline-block;
    width: 14px; height: 1px;
    background: rgba(39,66,112,0.30);
    vertical-align: middle;
    margin-right: 8px;
}

/* ---- 9) Card hero — refined defaults. ------------------------------
   Pages occasionally re-style .card-hero h2 with inline `font-size:28px`
   — smaller than the design-system token. We honour those overrides
   (they win), but tighten the *default* hero rhythm so pages that
   don't override pick up a slightly more refined value: 30px on
   desktop, scaling down to 24px on mobile. */
.card-hero h2 {
    font-size: clamp(24px, 3.5vw, 30px);
}
@media (max-width: 700px) {
    .card-hero { padding: 22px 22px; border-radius: var(--radius); }
}

/* ---- 10) Table head — slight crispening. ---------------------------
   The header gradient is fine; the tracking is fine. Add a 1px inner
   shadow on hover at the first row so the table feels tactile. Pure
   visual. No behaviour change. */
table.tbl thead th {
    background-image: linear-gradient(180deg, #F8FAFD 0%, #EEF2F9 100%);
    box-shadow: inset 0 -1px 0 var(--border);
}

/* ---- 11) Date filter row — opt-in form structure. ------------------
   analytics.php uses inline padding/border on each date picker. When a
   page wraps its inputs in .filter-row, give them the same modern
   chrome the .field form-control has. Existing inline styles still win;
   this is opt-in only. */
.filter-row {
    display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end;
}
.filter-row .fr-field {
    display: flex; flex-direction: column; gap: 4px;
    min-width: 0;
}
.filter-row .fr-field label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    font-weight: 700;
}
.filter-row .fr-field select,
.filter-row .fr-field input[type=date],
.filter-row .fr-field input[type=text] {
    padding: 8px 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--card);
    font-size: 13.5px;
    font-family: inherit;
    color: var(--text);
    min-height: 36px;
    transition: border-color var(--motion-fast) var(--ease-out), box-shadow var(--motion-fast) var(--ease-out);
}
.filter-row .fr-field select:focus,
.filter-row .fr-field input:focus {
    outline: none;
    border-color: var(--secondary);
    box-shadow: var(--ring-focus);
}
.filter-row .fr-actions { display: flex; gap: 6px; align-items: center; }

/* ---- 12) Hero corner gradient refinement on .card-hero. ------------
   The existing radial spotlight on .card-hero is good but pages with
   tall heros (Operations dashboard with date) show a slight banding.
   Strengthen the top-left highlight to balance the top-right spotlight
   and give the hero a more "milled steel" feel. */
.card-hero { background-image: var(--grad-jags), radial-gradient(circle at 0% 0%, rgba(255,255,255,0.10), transparent 50%); }

/* ---- 13) Quick-action card right-arrow affordance. -----------------
   .qa-card is great but lacks a "this is interactive" cue. Add a faint
   right-side chevron that fades up on hover/focus. Purely decorative;
   no impact on screen reader since aria-hidden. */
a.qa-card { position: relative; padding-right: 32px; }
a.qa-card::after {
    content: "";
    position: absolute;
    right: 14px; top: 50%;
    width: 12px; height: 12px;
    margin-top: -6px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23274270' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 6l6 6-6 6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 12px 12px;
    opacity: 0.0;
    transform: translateX(-4px);
    transition: opacity var(--motion-med) var(--ease-soft), transform var(--motion-med) var(--ease-soft);
    pointer-events: none;
}
a.qa-card:hover::after,
a.qa-card:focus-visible::after { opacity: 0.55; transform: translateX(0); }
a.qa-card.qa-card-disabled::after { display: none; }

/* ---- 14) Mini-bar value typography. --------------------------------
   The mb-value font is mono, but mb-label is sans. Pull both into the
   same sans / tabular-num treatment so labels and values feel tied
   together on the same axis. The mb-fill colours stay semantic. */
.mini-bar .mb-label { font-size: 12px; fill: var(--text-strong); font-weight: 600; }
.mini-bar .mb-value { font-family: var(--font-sans); font-size: 12px; fill: var(--muted-strong); font-weight: 600; }

/* ---- 15) Compliance / regulatory pages — calmer left-rail card. ----
   technical_records.php emits an inline `border-left: 4px solid …` on
   the compliance summary card. Provide a token for this pattern so
   pages that opt-in don't need inline colour. */
.card-left-rail            { border-left: 4px solid var(--secondary); }
.card-left-rail.success    { border-left-color: var(--success); }
.card-left-rail.warn       { border-left-color: var(--warning); }
.card-left-rail.danger     { border-left-color: var(--danger); }
.card-left-rail.info       { border-left-color: var(--info); }
.card-left-rail.muted      { border-left-color: var(--border-strong); }

/* ---- 16) Print niceties. -------------------------------------------
   Already broad print rules exist; add: ensure stat severity rails
   print in colour so the printed dashboard preserves semantic weight. */
@media print {
    .stat::before { print-color-adjust: exact !important; -webkit-print-color-adjust: exact !important; }
    .alert::before { print-color-adjust: exact !important; -webkit-print-color-adjust: exact !important; }
    a.qa-card::after { display: none; }
}

/* ---- 17) Focus ring tightening on interactive surfaces. ------------
   Cards and stats inside a clickable form should get the same focus
   ring as buttons. Keeps keyboard nav legible without painting an
   in-your-face outline. */
.card:focus-within { box-shadow: var(--ring-focus), var(--shadow-sm); }

/* ---- 18) Sidebar account row — small refinement. -------------------
   The .sidebar-account chip already groups avatar + name + sign-out.
   Add a subtle hover so it feels like a single tap target on touch
   devices (already has a sign-out button inside; we don't make the
   row a link). */
.sidebar-account { transition: background var(--motion-fast) var(--ease-out), border-color var(--motion-fast) var(--ease-out); }
.sidebar-account:hover { background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.16); }

/* ---- 19) Bell badge — slightly heavier weight for legibility. ------
   At 10.5px the badge digits can feel thin on retina; bump weight and
   add a 0.5px stroke via text-shadow for crisper edges. */
.topbar-bell-badge {
    font-weight: 800;
    text-shadow: 0 0 0 currentColor;
    letter-spacing: -0.01em;
}

/* ---- 20) Calmer hover lift on .card. -------------------------------
   The existing transition is fine but the actual hover doesn't move
   .card surfaces. Cards inside .qa-grid already lift via .qa-card. For
   "interactive" cards opting into .card-interactive, give a tiny lift
   identical to .qa-card. */
.card-interactive { cursor: pointer; }
.card-interactive:hover {
    box-shadow: var(--shadow-md);
    border-color: rgba(39, 66, 112, 0.22);
    transform: translateY(-1px);
}
.card-interactive:active { transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
    .card-interactive:hover { transform: none; }
}

/* ---- 21) Typographic settle + selection polish. --------------------
   Additive only — no existing rule is overridden. `text-wrap` is a
   progressive enhancement: a browser that doesn't support it ignores
   the declaration, so wrapping only ever improves and layout can never
   regress. Balancing headings and applying `pretty` to supporting copy
   removes the ragged single-word last line that separates a "designed"
   screen from a generated one. The selection rule ties highlighted text
   to the JAGS navy instead of the OS default blue. Display boards load
   a separate stylesheet (layout_display_open) and are unaffected; the
   .display-shell guard is defensive only, matching house style. */
h1, h2, h3, h4,
.page-header-text h1, .page-header-text h2,
.section-title h2, .card-section-title,
.empty-state h3, .modern-card-head h3, .av2-card-head h3 {
    text-wrap: balance;
}
p, .muted,
.page-header-text p, .empty-state p,
.field .hint, .sub-line, .feature-value .feat-sub, .av2-feature .feat-sub {
    text-wrap: pretty;
}
::selection {
    background: rgba(39, 66, 112, 0.20);
    color: var(--text-strong);
}
.display-shell ::selection {
    background: rgba(255, 255, 255, 0.22);
    color: #fff;
}

/* ====================================================================
   Premium mobile experience (2026-07-13)
   --------------------------------------------------------------------
   Reference-driven authenticated-app layer. This block is intentionally
   last in layout_css() so it can unify older page-local mobile treatments
   without changing desktop tables, print layouts, public displays, route
   permissions, or business logic.
   ==================================================================== */
:root {
    --jags-mobile-page-bg: #F3F6FA;
    --jags-mobile-surface: #FFFFFF;
    --jags-mobile-surface-soft: #EEF2F7;
    --jags-mobile-surface-strong: #E5EAF2;
    --jags-mobile-text: #0E0E12;
    --jags-mobile-text-muted: #5E6472;
    --jags-mobile-border: rgba(39, 66, 112, 0.10);
    --jags-mobile-radius-control: 12px;
    --jags-mobile-radius-compact: 16px;
    --jags-mobile-radius-card: 20px;
    --jags-mobile-radius-feature: 24px;
    --jags-mobile-radius-floating: 26px;
    --jags-mobile-space-1: 4px;
    --jags-mobile-space-2: 8px;
    --jags-mobile-space-3: 12px;
    --jags-mobile-space-4: 16px;
    --jags-mobile-space-5: 20px;
    --jags-mobile-space-6: 24px;
    --jags-mobile-space-7: 32px;
    --jags-mobile-shadow-card: 0 1px 2px rgba(14,14,18,.025), 0 10px 28px rgba(23,23,86,.045);
    --jags-mobile-shadow-floating: 0 2px 4px rgba(14,14,18,.04), 0 18px 40px rgba(23,23,86,.12);
    --jags-z-chrome: 8000;
    --jags-z-overlay: 9200;
    --jags-z-dialog: 9210;
}
/* Dark theme values for the premium mobile layer — same surface ladder as
   the main dark palette so phones and desktop read as one system. */
html[data-theme="dark"] {
    --jags-mobile-page-bg: #0E1220;
    --jags-mobile-surface: #171C2B;
    --jags-mobile-surface-soft: #1E2438;
    --jags-mobile-surface-strong: #29314A;
    --jags-mobile-text: #E6E9F2;
    --jags-mobile-text-muted: #A2AAC0;
    --jags-mobile-border: rgba(157, 176, 240, 0.14);
    --jags-mobile-shadow-card: 0 1px 2px rgba(0,0,0,.30), 0 10px 28px rgba(0,0,0,.35);
    --jags-mobile-shadow-floating: 0 2px 4px rgba(0,0,0,.35), 0 18px 40px rgba(0,0,0,.55);
}

.topbar-title-block { min-width: 0; }

/* Shared mobile status geometry: feature-specific selectors continue to own
   semantic colours, and dense desktop audit tables keep their current fit. */
@media (max-width: 900px) {
    .badge,
    .reservation-status-badge,
    .payment-status-badge,
    .clearance-status-badge,
    .requested-aircraft-badge,
    .customer-status-badge {
        border-radius: 999px;
        padding: 4px 9px;
        line-height: 1.2;
        font-weight: 700;
    }
}

/* Opt-in responsive data table. The mobile-table script copies each visible
   header into data-mobile-label, preserving the semantic table in the DOM
   while presenting operational rows as comfortably scannable cards. */
@media (max-width: 900px) {
    table[data-mobile-cards] { display: block; border: 0 !important; background: transparent !important; }
    table[data-mobile-cards] thead {
        position: absolute !important;
        width: 1px !important; height: 1px !important;
        padding: 0 !important; margin: -1px !important;
        overflow: hidden !important; clip: rect(0,0,0,0) !important;
        white-space: nowrap !important; border: 0 !important;
    }
    table[data-mobile-cards] tbody { display: grid; gap: 12px; }
    table[data-mobile-cards] tbody tr {
        display: block;
        padding: 8px 16px;
        border: 1px solid var(--jags-mobile-border) !important;
        border-radius: var(--jags-mobile-radius-card);
        background: var(--jags-mobile-surface);
        box-shadow: var(--jags-mobile-shadow-card);
        text-decoration: none !important;
    }
    table[data-mobile-cards] tbody td {
        display: grid;
        grid-template-columns: minmax(92px, 34%) minmax(0, 1fr);
        gap: 12px;
        align-items: start;
        width: auto !important;
        max-width: none !important;
        min-height: 40px;
        padding: 10px 0 !important;
        border: 0 !important;
        border-bottom: 1px solid var(--jags-mobile-border) !important;
        background: transparent !important;
        text-align: left !important;
        white-space: normal !important;
        overflow-wrap: anywhere;
    }
    table[data-mobile-cards] tbody td:last-child { border-bottom: 0 !important; }
    table[data-mobile-cards] tbody td::before {
        content: attr(data-mobile-label);
        color: var(--jags-mobile-text-muted);
        font-size: 12px;
        font-weight: 650;
        line-height: 1.35;
    }
    table[data-mobile-cards] tbody td.cell-actions,
    table[data-mobile-cards] tbody td[data-mobile-actions] {
        display: flex;
        flex-wrap: wrap;
        justify-content: flex-start !important;
        gap: 8px;
        padding-top: 12px !important;
    }
    table[data-mobile-cards] tbody td.cell-actions::before,
    table[data-mobile-cards] tbody td[data-mobile-actions]::before { display: none; }
    table[data-mobile-cards] tbody td form { margin: 0 !important; }
    table[data-mobile-cards] tbody td .btn,
    table[data-mobile-cards] tbody td button { min-height: 44px; }
    table[data-mobile-cards] + .mobile-scroll-hint,
    .table-wrap:has(> table[data-mobile-cards]) > .mobile-scroll-hint { display: none !important; }
    .table-wrap:has(> table[data-mobile-cards]) { overflow: visible; border: 0; background: transparent; }
}

/* Central action and More surfaces. */
.mobile-action-sheet { display: none; }
.mobile-action-sheet[hidden] { display: none !important; }
.fs-quick-edit-sheet { display: none; }
.fs-quick-edit-sheet[hidden] { display: none !important; }
@media (max-width: 900px) {
    .mobile-action-sheet {
        position: fixed;
        inset: 0;
        z-index: var(--jags-z-overlay);
        display: flex;
        align-items: flex-end;
        justify-content: center;
        padding: 14px 12px calc(14px + var(--safe-area-bottom));
        pointer-events: none;
        opacity: 0;
        background: rgba(11, 14, 38, 0);
        -webkit-backdrop-filter: blur(0);
        backdrop-filter: blur(0);
        transition:
            opacity 210ms var(--ease-out),
            background-color 210ms var(--ease-out),
            -webkit-backdrop-filter 210ms var(--ease-out),
            backdrop-filter 210ms var(--ease-out);
    }
    .mobile-action-sheet.is-open {
        pointer-events: auto;
        opacity: 1;
        background: rgba(11, 14, 38, 0.48);
        -webkit-backdrop-filter: blur(7px);
        backdrop-filter: blur(7px);
    }
    .mobile-action-sheet__panel {
        width: min(560px, 100%);
        max-height: min(76dvh, 680px);
        overflow: auto;
        padding: 10px 18px 20px;
        border: 1px solid rgba(var(--glass-rgb),.72);
        border-radius: 28px;
        background: rgba(var(--glass-rgb), .98);
        box-shadow: var(--jags-mobile-shadow-floating);
        transform-origin: bottom center;
        opacity: 0;
        transform: translate3d(0, 18px, 0) scale(.985);
        transition:
            transform var(--motion-med) var(--ease-premium),
            opacity 170ms var(--ease-out);
        will-change: transform, opacity;
    }
    .mobile-action-sheet.is-open .mobile-action-sheet__panel {
        opacity: 1;
        transform: translate3d(0, 0, 0) scale(1);
    }
    .mobile-action-sheet.is-closing .mobile-action-sheet__panel {
        transition-duration: 220ms, 150ms;
        transition-timing-function: cubic-bezier(.4,0,1,1), var(--ease-out);
    }
    .mobile-action-sheet__handle {
        width: 42px; height: 5px;
        margin: 0 auto 14px;
        border-radius: 999px;
        background: var(--jags-mobile-surface-strong);
    }
    .mobile-action-sheet__head {
        display: flex; align-items: center; justify-content: space-between;
        gap: 16px; margin-bottom: 14px;
    }
    .mobile-action-sheet__head h2 { font-size: 21px; }
    .mobile-action-sheet__close {
        width: 44px; height: 44px; padding: 0;
        display: inline-flex; align-items: center; justify-content: center;
        border: 0; border-radius: 14px;
        background: var(--jags-mobile-surface-soft);
        color: var(--jags-blue); cursor: pointer;
    }
    .mobile-action-sheet__grid { display: grid; grid-template-columns: 1fr; gap: 6px; }
    .mobile-action-sheet__item {
        min-height: 54px;
        display: flex; flex-direction: row; align-items: center; justify-content: flex-start;
        gap: 12px; padding: 9px 12px;
        border: 1px solid var(--jags-mobile-border);
        border-radius: var(--jags-mobile-radius-compact);
        background: var(--jags-mobile-surface-soft);
        color: var(--jags-mobile-text);
        font-weight: 700;
        opacity: 0;
        transform: translate3d(0, 8px, 0);
        transition:
            transform 190ms var(--ease-premium),
            opacity 150ms var(--ease-out);
        transition-delay: calc(var(--action-reverse-index, 0) * 8ms);
    }
    .mobile-action-sheet.is-open .mobile-action-sheet__item {
        opacity: 1;
        transform: translate3d(0, 0, 0);
        transition-delay: calc(34ms + (var(--action-index, 0) * 8ms));
    }
    .mobile-action-sheet.is-closing .mobile-action-sheet__item {
        transition-duration: 150ms, 120ms;
        transition-delay: calc(var(--action-reverse-index, 0) * 7ms);
    }
    .mobile-action-sheet__item .jags-icon { width: 22px; height: 22px; color: var(--jags-blue); }

    /* Flight Schedule mobile Quick Edit. The editor is deliberately outside
       the dense table so opening it never changes row width, row height, or
       the schedule rail's horizontal position. */
    .fs-quick-edit-sheet {
        position: fixed;
        left: 0;
        right: 0;
        top: var(--fs-visual-offset-top, 0px);
        height: var(--fs-visual-height, 100dvh);
        z-index: var(--jags-z-overlay);
        display: flex;
        align-items: flex-end;
        justify-content: center;
        padding: 8px 8px 0;
        pointer-events: none;
        opacity: 0;
        background: rgba(11,14,38,0);
        -webkit-backdrop-filter: blur(0);
        backdrop-filter: blur(0);
        transition: opacity 200ms var(--ease-out), background-color 200ms var(--ease-out), -webkit-backdrop-filter 200ms var(--ease-out), backdrop-filter 200ms var(--ease-out);
    }
    .fs-quick-edit-sheet.is-open {
        pointer-events: auto;
        opacity: 1;
        background: rgba(11,14,38,.48);
        -webkit-backdrop-filter: blur(6px);
        backdrop-filter: blur(6px);
    }
    .fs-quick-edit-sheet__panel {
        width: min(600px, 100%);
        max-height: calc(var(--fs-visual-height, 100dvh) - 8px);
        display: flex;
        flex-direction: column;
        overflow: hidden;
        border: 1px solid rgba(var(--glass-rgb),.72);
        border-bottom: 0;
        border-radius: 26px 26px 0 0;
        background: var(--card);
        box-shadow: 0 -20px 55px rgba(9,12,35,.24);
        opacity: 0;
        transform: translate3d(0, 18px, 0) scale(.99);
        transform-origin: bottom center;
        transition: transform var(--motion-med) var(--ease-premium), opacity 170ms var(--ease-out);
        will-change: transform, opacity;
    }
    .fs-quick-edit-sheet.is-open .fs-quick-edit-sheet__panel { opacity: 1; transform: translate3d(0,0,0) scale(1); }
    .fs-quick-edit-sheet.is-closing .fs-quick-edit-sheet__panel { transition-duration: 190ms, 140ms; transition-timing-function: cubic-bezier(.4,0,1,1), var(--ease-out); }
    .fs-quick-edit-sheet__handle { width: 42px; height: 5px; margin: 9px auto 4px; flex: 0 0 auto; border-radius: 999px; background: var(--jags-mobile-surface-strong); }
    .fs-quick-edit-sheet__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; padding: 10px 18px 12px; flex: 0 0 auto; border-bottom: 1px solid var(--jags-mobile-border); }
    .fs-quick-edit-sheet__head h2 { margin: 2px 0 0; font-size: 22px; color: var(--jags-blue); }
    .fs-quick-edit-sheet__head p { margin: 4px 0 0; color: var(--jags-mobile-text-muted); font-size: 13px; line-height: 1.35; }
    .fs-quick-edit-sheet__close { width: 44px; height: 44px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: 14px; background: var(--jags-mobile-surface-soft); color: var(--jags-blue); cursor: pointer; }
    .fs-quick-edit-sheet__status { min-height: 0; padding: 0 18px; flex: 0 0 auto; color: var(--danger); font-size: 13px; font-weight: 650; line-height: 1.4; }
    .fs-quick-edit-sheet__status:not(:empty) { min-height: 42px; padding-top: 10px; padding-bottom: 8px; border-bottom: 1px solid rgba(184,50,53,.16); background: rgba(184,50,53,.055); }
    .fs-quick-edit-sheet__host { min-height: 0; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
    .fs-quick-edit-sheet .fs-mobile-edit { display: grid; gap: 13px; margin: 0; padding: 16px 18px calc(14px + var(--safe-area-bottom)); }
    .fs-quick-edit-sheet .fs-mobile-edit[hidden] { display: none; }
    .fs-quick-edit-sheet .fs-mobile-flight-actions { position: sticky; bottom: calc(-14px - var(--safe-area-bottom)); z-index: 2; margin: 3px -18px calc(-14px - var(--safe-area-bottom)); padding: 12px 18px calc(14px + var(--safe-area-bottom)); border-top: 1px solid var(--jags-mobile-border); background: rgba(var(--glass-rgb), .97); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); }
    .fs-quick-edit-sheet .fs-mobile-flight-actions .btn { min-width: 0; }
    .fs-quick-edit-sheet form[data-fs-busy="1"] { opacity: .78; }
    .fs-quick-edit-sheet form[data-fs-busy="1"] input,
    .fs-quick-edit-sheet form[data-fs-busy="1"] select,
    .fs-quick-edit-sheet form[data-fs-busy="1"] textarea { pointer-events: none; }
    table.ops-board tr.fs-row-saved td { animation: fsRowSaved 1100ms var(--ease-out); }
    @keyframes fsRowSaved { 0%, 28% { background-color: rgba(34,139,87,.13); } 100% { background-color: transparent; } }
}

@media (max-width: 900px) {
    :root {
        --mobile-bottom-nav-height: 82px;
        --mobile-bottom-nav-footprint: calc(var(--mobile-bottom-nav-height) + var(--safe-area-bottom));
        --mobile-bottom-nav-clearance: calc(var(--mobile-bottom-nav-footprint) + 22px);
    }
    html, body { background: var(--jags-mobile-page-bg); }
    body { font-size: 15.5px; }
    .app-shell { min-height: 100dvh; }

    /* Native-style page header. It scrolls with the page instead of consuming
       permanent viewport height, while keeping safe-area padding in PWA mode. */
    .topbar {
        position: relative;
        z-index: 20;
        align-items: flex-start;
        padding: calc(18px + env(safe-area-inset-top, 0px)) max(18px, env(safe-area-inset-right, 0px)) 14px max(18px, env(safe-area-inset-left, 0px));
        border: 0;
        background: var(--jags-mobile-page-bg);
        box-shadow: none;
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }
    .topbar-leading { display: flex; align-items: flex-start; gap: 12px; min-width: 0; flex: 1 1 auto; }
    .topbar-title-block { display: flex; flex-direction: column; min-width: 0; padding-top: 1px; }
    .mobile-page-context,
    .mobile-page-meta { display: block; }
    .mobile-page-context {
        color: var(--jags-mobile-text-muted);
        font-size: 12.5px;
        font-weight: 650;
        line-height: 1.2;
        text-transform: none;
    }
    .mobile-page-meta {
        margin-top: 4px;
        color: var(--jags-mobile-text-muted);
        font-size: 13px;
        line-height: 1.25;
    }
    .topbar h1 {
        /* Bounded by the flex parent, NOT by 64vw. With `overflow: visible`
           and a viewport-relative cap, this could not shrink below its
           min-content width, so a one-word title held the whole leading
           column open and pushed the action cluster off the right edge —
           measured 435px of topbar in a 393px viewport once the cluster
           reached four controls. The title is the element that should yield:
           the page you are on is already obvious from context, whereas a
           control pushed off-screen is simply gone. */
        max-width: 100%;
        margin-top: 3px;
        overflow: hidden;
        color: var(--jags-mobile-text);
        /* Scales down on narrow phones so "Dashboard" still fits WHOLE at
           360-393px. The ellipsis below is the safety net for a genuinely
           long title, not the normal path. */
        font-size: clamp(21px, 6vw, 32px);
        font-weight: 750;
        line-height: 1.05;
        letter-spacing: -.03em;
        white-space: normal;
        text-overflow: ellipsis;
        text-wrap: balance;
    }
    .topbar > div:last-child { gap: 8px !important; padding-top: 18px; flex: 0 0 auto; }
    /* Narrow phones: the large title moves to its own row.
       A 27px native-style title and four 44px targets genuinely do not fit
       across a 393px phone — squeezing the title to suit would have meant
       ~17px type or an ellipsis on "Dashboard". This is the iOS large-title
       pattern the header is already shaped for (align-items:flex-start, a
       column title block, a header that scrolls rather than pinning), and it
       needs no markup change: the leading row wraps, the title block claims
       the full width, so row 1 is [menu ........ actions] and row 2 is the
       title at full size. Extra header height is fine here — this topbar
       scrolls away with the page. */
    @media (max-width: 520px) {
        .topbar {
            padding-left: max(14px, env(safe-area-inset-left, 0px));
            padding-right: max(14px, env(safe-area-inset-right, 0px));
            padding-bottom: 10px;
            flex-wrap: wrap;
            align-items: center;
            /* The shell is a grid with min-height:100dvh, so this header box
               stretches well past its content. Once it wraps, the default
               align-content:stretch spreads the two lines across all that
               height — 396px of header. Pack them to the top instead. */
            align-content: flex-start;
            row-gap: 8px;
        }
        /* `display: contents` promotes the menu button and the title block to
           direct flex items of the topbar, so they can be ordered across what
           was their wrapper. Without it the whole leading column wraps as one
           unit and the actions land on a third row. The wrapper is a plain
           div, so dissolving its box costs nothing semantically. */
        .topbar-leading { display: contents; }
        .mobile-nav-toggle { order: 1; }
        .topbar > div:last-child { order: 2; margin-left: auto; gap: 6px !important; padding-top: 0; }
        .topbar-title-block { order: 3; flex: 1 1 100%; padding-top: 0; }
        /* Full width of its own row, so the title goes back to the size the
           design intended — the reduced clamp above exists only for the
           single-row band (521-900px), where it shares the row with four
           44px targets. */
        .topbar h1 { margin-top: 2px; font-size: clamp(24px, 7vw, 32px); }
    }
    #jags-tour-launcher,
    .topbar-refresh,
    .topbar [data-system-run-button],
    .topbar .jags-system-run-button,
    .topbar .jags-title-badge,
    .topbar .jags-pwa-install-pill { display: none !important; }
    .mobile-nav-toggle,
    .topbar-bell,
    .user-menu-button { min-width: 44px; min-height: 44px; }
    .mobile-nav-toggle { border: 0; border-radius: 14px; background: var(--jags-mobile-surface); box-shadow: var(--jags-mobile-shadow-card); }
    .topbar-bell { width: 44px; height: 44px; border: 0; border-radius: 14px; background: var(--jags-mobile-surface); box-shadow: var(--jags-mobile-shadow-card); }
    .user-menu-button { padding: 3px; border-radius: 15px; background: var(--jags-mobile-surface); box-shadow: var(--jags-mobile-shadow-card); }
    .user-menu-button .jags-avatar { border-radius: 12px; }

    .content { padding: 8px max(16px, env(safe-area-inset-right, 0px)) var(--mobile-bottom-nav-clearance) max(16px, env(safe-area-inset-left, 0px)); }
    .main > .content { animation-duration: 180ms; }
    .content > .page-header { margin-top: 0; }
    .content > .page-header .page-header-text .eyebrow,
    .content > .page-header .page-header-text h1,
    .content > .page-header .page-header-text h2 { display: none; }
    .content > .page-header .page-header-text p {
        max-width: 46ch;
        margin: 0;
        font-size: 14px;
        line-height: 1.45;
    }
    .page-header { gap: 12px; margin-bottom: 18px; }
    .page-header-actions { width: 100%; display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; }
    .page-header-actions::-webkit-scrollbar { display: none; }
    .page-header-actions .btn { flex: 0 0 auto; }

    .card {
        padding: 18px;
        border-color: var(--jags-mobile-border);
        border-radius: var(--jags-mobile-radius-card);
        box-shadow: var(--jags-mobile-shadow-card);
    }
    .card + .card { margin-top: 16px; }
    .card-hero {
        padding: 22px 20px 24px;
        border-radius: var(--jags-mobile-radius-feature);
        box-shadow: 0 18px 38px rgba(23,23,86,.16);
    }
    .card-hero h2,
    .card-hero .pp-hero-title { font-size: clamp(26px, 7vw, 31px) !important; line-height: 1.08; }
    .card-hero p { max-width: 48ch; font-size: 14.5px; line-height: 1.5; }
    .stats-grid { gap: 12px; margin-bottom: 18px; }
    .stat { min-height: 112px; padding: 17px 16px; border-radius: var(--jags-mobile-radius-compact); box-shadow: var(--jags-mobile-shadow-card); }
    .stat .value { font-size: 27px; line-height: 1; }
    .stat .label { margin-top: 8px; font-size: 12px; line-height: 1.25; text-transform: none; letter-spacing: 0; }
    .section-title { margin-bottom: 14px; gap: 10px; }
    .section-title h2 { font-size: 19px; line-height: 1.15; }
    .qa-grid { grid-template-columns: repeat(2, minmax(0,1fr)); gap: 12px; }
    a.qa-card, button.qa-card { min-height: 112px; padding: 16px 30px 16px 16px; border-radius: var(--jags-mobile-radius-card); }
    .mobile-card-list { gap: 12px; }
    .mobile-card-list-item { padding: 16px; border-radius: var(--jags-mobile-radius-card); box-shadow: var(--jags-mobile-shadow-card); }
    .fs-mobile-schedule[hidden] { display: none !important; }
    .fs-mobile-schedule:not(.fs-mobile-cards-optional) + .mobile-scroll-hint,
    .fs-mobile-schedule:not(.fs-mobile-cards-optional) ~ .ops-board-scroll { display: none !important; }
    .ops-board-wrap.fs-mobile-card-mode .mobile-scroll-hint,
    .ops-board-wrap.fs-mobile-card-mode .ops-board-scroll { display: none !important; }
    .fs-mobile-mode-tabs { order: 8; width: 100%; padding: 4px; border-radius: 14px; background: var(--jags-mobile-surface-soft); }
    .fs-mobile-mode-tabs button { flex: 1; min-height: 42px; border: 0; border-radius: 11px; background: transparent; color: var(--jags-mobile-text-muted); font-weight: 750; }
    .fs-mobile-mode-tabs button.active { background: var(--card); color: var(--jags-blue); box-shadow: 0 3px 10px rgba(23,23,86,.10); }
    .fs-quick-views { margin: 0 0 10px; padding: 0; overflow-x: auto; scrollbar-width: none; }
    .fs-quick-views > div { flex-wrap: nowrap !important; width: max-content; }
    .fs-filter-bar { margin-bottom: 12px; padding: 12px; }
    .fs-filter-date-row { display: grid; grid-template-columns: minmax(0,1fr) auto; gap: 10px; align-items: end; }
    .fs-filter-details > summary { min-height: 48px; display: flex; align-items: center; padding: 0 14px; border: 1px solid var(--jags-mobile-border); border-radius: 14px; color: var(--jags-blue); font-weight: 750; cursor: pointer; list-style: none; }
    .fs-filter-details > summary::-webkit-details-marker { display: none; }
    .fs-filter-sheet { position: absolute; z-index: 18; left: 16px; right: 16px; margin-top: 8px; padding: 16px; border: 1px solid var(--jags-mobile-border); border-radius: 18px; background: var(--card); box-shadow: var(--jags-mobile-shadow-floating); }
    .fs-filter-sheet .form-grid { grid-template-columns: 1fr; }
    .ops-board-tabs { display: none !important; }
    .fs-mobile-flight-card { display: block; }
    .fs-mobile-flight-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
    .fs-mobile-flight-head h3 { margin-top: 4px; font-size: 22px; color: var(--jags-blue); }
    .fs-mobile-route { margin-top: 14px; font-size: 18px; font-weight: 750; letter-spacing: -.02em; }
    .fs-mobile-times { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 14px; }
    .fs-mobile-times > div { padding: 12px; border-radius: 14px; background: var(--jags-mobile-surface-soft); }
    .fs-mobile-times span,
    .fs-mobile-crew span { display: block; color: var(--jags-mobile-text-muted); font-size: 12px; font-weight: 650; }
    .fs-mobile-times strong { display: block; margin-top: 3px; font-size: 20px; font-variant-numeric: tabular-nums; }
    .fs-mobile-crew { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-top: 12px; }
    .fs-mobile-crew strong { text-align: right; }
    .fs-mobile-flight-actions { margin-top: 16px; }
    .fs-mobile-flight-actions .btn:first-child { flex: 1 1 auto; }
    /* Fuel / follower / client rows reuse the .fs-mobile-crew chrome; the
       extras below cover remarks, status chips and the quick-edit form. */
    .fs-mobile-remarks { margin-top: 12px; padding: 10px 12px; border-radius: 12px; background: var(--jags-mobile-surface-soft); font-size: 14px; line-height: 1.4; overflow-wrap: anywhere; }
    .fs-mobile-handoff { border-left: 3px solid rgba(34,139,87,0.55); background: rgba(34,139,87,0.06); }
    .fs-mobile-handoff strong { font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: #1f7a4d; margin-right: 6px; }
    .fs-mobile-chip-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
    .fs-mobile-editing { border: 2px solid var(--jags-blue); }
    .fs-mobile-edit { display: grid; gap: 12px; margin-top: 14px; }
    /* Load-bearing: the grid display above beats the UA [hidden] rule, so
       the always-rendered quick-edit form needs an explicit override or
       every card would render with its editor expanded. */
    .fs-mobile-edit[hidden] { display: none; }
    /* Same load-bearing reason for the summary rows: `.fs-mobile-crew`
       declares display:flex above, and an author display beats the UA
       [hidden] rule, so the optional Client / Follower rows would render
       even when marked hidden. (`.fs-mobile-remarks` declares no display,
       so its [hidden] already works and needs no override.) */
    .fs-mobile-crew[hidden] { display: none; }
    .fs-mobile-edit input[type=text],
    .fs-mobile-edit select,
    .fs-mobile-edit textarea { width: 100%; }
    .empty-state { padding: 30px 18px 28px; border-radius: var(--jags-mobile-radius-card); }
    .empty-state h3 { font-size: 18px; }
    .form-card { padding: 18px; border-radius: var(--jags-mobile-radius-card); }
    .field label { font-size: 13px; }
    .field input, .field select, .field textarea { min-height: 48px; border-radius: var(--jags-mobile-radius-control); font-size: 16px; }
    /* iOS Safari zooms the viewport when any focused editable control is
       below 16px. Cover controls outside the canonical .field wrapper too
       (People search, Messages composer, table filters, Quick Edit, auth). */
    input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]):not([type="button"]):not([type="submit"]):not([type="reset"]),
    select,
    textarea,
    [contenteditable="true"] {
        font-size: 16px !important;
    }
    .btn { min-height: 48px; border-radius: 14px; padding: 11px 16px; }
    .btn-sm { min-height: 44px; padding: 9px 12px; }
    .form-actions .btn { min-height: 48px; }
    .tabs, .segmented-control {
        padding: 4px; gap: 4px;
        border: 1px solid var(--jags-mobile-border);
        border-radius: 16px;
        background: var(--jags-mobile-surface-soft);
    }
    .tabs a, .segmented-control a, .segmented-control button { min-height: 44px; border-radius: 12px; }

    /* Floating five-destination dock. */
    .mobile-bottom-nav {
        left: 50%; right: auto;
        bottom: calc(8px + var(--safe-area-bottom));
        width: min(560px, calc(100vw - 24px));
        min-height: 72px;
        padding: 6px;
        grid-template-columns: repeat(5, minmax(0,1fr));
        grid-auto-flow: initial;
        grid-auto-columns: initial;
        border: 1px solid rgba(var(--glass-rgb),.78);
        border-radius: var(--jags-mobile-radius-floating);
        background: rgba(var(--glass-rgb),.94);
        box-shadow: var(--jags-mobile-shadow-floating);
        transform: translateX(-50%);
        transition: opacity var(--motion-med) var(--ease-out), transform var(--motion-med) var(--ease-out);
    }
    .mobile-bottom-nav a,
    .mobile-bottom-nav button { min-height: 58px; padding: 7px 3px 5px; border-radius: 16px; font-size: 12px; }
    .mobile-bottom-nav a.active { color: var(--jags-blue); background: rgba(90,121,165,.10); }
    .mobile-bottom-nav a.active::before { display: none; }
    .mobile-bottom-nav a .jags-icon,
    .mobile-bottom-nav button .jags-icon { width: 23px; height: 23px; }
    .mobile-bottom-nav .mobile-nav-primary {
        align-self: center;
        min-height: 76px;
        margin-top: -20px;
        overflow: visible;
        color: var(--jags-blue);
        background: transparent;
    }
    .mobile-bottom-nav .mobile-nav-primary .jags-icon-wrap {
        width: 54px; height: 54px;
        display: inline-flex; align-items: center; justify-content: center;
        border: 4px solid rgba(255,255,255,.96);
        border-radius: 18px;
        background: var(--jags-blue);
        color: #fff;
        box-shadow: 0 10px 24px rgba(23,23,86,.25);
        transform: translate3d(0,0,0) rotate(0) scale(1);
        transition: transform var(--motion-fast) var(--ease-premium), box-shadow var(--motion-fast) var(--ease-out);
    }
    #jags-mobile-action-trigger.is-action-open .jags-icon-wrap {
        transform: translate3d(0,-2px,0) rotate(45deg) scale(.94);
        box-shadow: 0 8px 20px rgba(23,23,86,.20);
    }
    .mobile-bottom-nav .mobile-nav-primary .jags-icon { width: 25px; height: 25px; opacity: 1; }
    .mobile-bottom-nav .mobile-nav-primary .label { color: var(--jags-blue); font-weight: 750; }
    body.mobile-nav-open .mobile-bottom-nav { opacity: 0; pointer-events: none; transform: translate(-50%, 12px); }

    /* The existing permission-aware drawer becomes a polished More sheet. */
    .sidebar {
        top: auto; left: 50%; bottom: calc(10px + var(--safe-area-bottom));
        width: min(600px, calc(100vw - 24px));
        height: min(82dvh, 720px);
        max-height: calc(100dvh - 24px - var(--safe-area-bottom));
        padding: 16px 14px calc(18px + var(--safe-area-bottom));
        border: 1px solid rgba(255,255,255,.12);
        border-radius: 28px;
        box-shadow: 0 28px 70px rgba(5,7,22,.44);
        transform: translate(-50%, calc(100% + 40px));
        transition: transform var(--motion-med) var(--ease-premium), visibility 0s linear var(--motion-med);
    }
    body.mobile-nav-open .sidebar { transform: translate(-50%, 0); }
    .sidebar-brand { position: sticky; top: -16px; z-index: 3; border-radius: 18px; }
    .sidebar nav a { min-height: 48px; border-radius: 12px; font-size: 14px; }
    .sidebar-account { border-top-color: rgba(255,255,255,.10); box-shadow: 0 -8px 24px rgba(5,7,22,.22); }

    /* Mobile minimums win even when the user previously selected Compact. */
    body[data-density="compact"] .card { padding: 18px; border-radius: var(--jags-mobile-radius-card); }
    body[data-density="compact"] .card + .card { margin-top: 16px; }
    body[data-density="compact"] .field input,
    body[data-density="compact"] .field select,
    body[data-density="compact"] .field textarea { min-height: 48px; font-size: 16px; }
    .jags-toast .toast-close { min-width: 44px; min-height: 44px; }
    .field input::placeholder,
    .field textarea::placeholder { color: var(--muted); opacity: 1; }
    a:focus-visible,
    button:focus-visible,
    input:focus-visible,
    select:focus-visible,
    textarea:focus-visible,
    [tabindex]:focus-visible {
        outline: 3px solid #274270 !important;
        outline-offset: 3px !important;
        box-shadow: none;
    }
}

@media (max-width: 380px) {
    .topbar { padding-left: 12px; padding-right: 12px; }
    .topbar h1 { max-width: 58vw; font-size: 26px; }
    .topbar > div:last-child { gap: 5px !important; }
    .topbar-bell, .user-menu-button { min-width: 42px; min-height: 42px; }
    .content { padding-left: 12px; padding-right: 12px; }
    .qa-grid { grid-template-columns: 1fr; }
    .mobile-action-sheet__grid { grid-template-columns: 1fr; }
    .mobile-bottom-nav { width: calc(100vw - 16px); }
    .mobile-bottom-nav a, .mobile-bottom-nav button { font-size: 10.5px; }
}

@media (prefers-reduced-motion: reduce) {
    .mobile-action-sheet,
    .mobile-action-sheet__panel,
    .mobile-action-sheet__item,
    .fs-quick-edit-sheet,
    .fs-quick-edit-sheet__panel,
    .mobile-bottom-nav .mobile-nav-primary .jags-icon-wrap { transition-duration: .01ms !important; transition-delay: 0ms !important; }
    .mobile-bottom-nav, .sidebar { transition-duration: .01ms !important; }
}

@media print {
    .mobile-action-sheet { display: none !important; }
}

/* ======================================================================
   CHANGE REQUEST HUB (2026-08-24)
   Global "suggest / report" trigger, the three-path sheet, the composer,
   My Requests and the request thread.

   Token-only by construction: every colour here is a var(), so the dark
   theme is inherited rather than re-specified. There is no
   html[data-theme="dark"] block for this feature and there must not be
   one — if something reads wrong in dark mode, the token is wrong, not
   the component.
   ====================================================================== */

/* --- Topbar trigger ---------------------------------------------------
   Stronger than the neutral Help pill beside it (tonal brand fill, brand
   border) without becoming a primary CTA competing with page actions.
   No pulse, no flash — prominence comes from contrast, not motion. */
.cr-trigger {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 12px;
    /* The edge must be a STEP above the fill, or the control reads as an
       edgeless tonal blob. Both previously resolved to --accent-soft. */
    border: 1px solid var(--accent);
    border-radius: var(--radius-control);
    background: var(--accent-soft);
    color: var(--secondary);
    font: 700 12.5px/1 inherit;
    cursor: pointer;
    transition: background var(--motion-fast) var(--ease-soft), border-color var(--motion-fast) var(--ease-soft), transform var(--motion-fast) var(--ease-soft);
}
.cr-trigger:hover {
    background: var(--surface-container);
    border-color: var(--border-strong);
    transform: translateY(-1px);
}
.cr-trigger:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.cr-trigger__icon { display: inline-flex; }
.cr-trigger__icon svg { width: 17px; height: 17px; }

/* The label is "Suggest / Report" so a person whose screen just broke can see
   this is their door too — "Suggest" alone reads as ideas-only. It sheds in
   two steps rather than one: the topbar already carries search, Help, refresh,
   install, the bell and the user menu. */
@media (max-width: 1100px) {
    .cr-trigger__label-more { display: none; }
}
/* Phones: the label goes, the target does not. 44px stays tappable and the
   control stays in the topbar — never buried in the drawer. */
@media (max-width: 700px) {
    .cr-trigger { padding: 7px 10px; min-width: 44px; justify-content: center; }
    .cr-trigger__label { display: none; }
}

/* --- Sheet ------------------------------------------------------------
   Geometry mirrors the Help sheet so the two feel like one system: popover
   on desktop, bottom sheet on phones. Driven by the shared
   [data-jags-sheet] engine — no new JavaScript. */
.cr-sheet[hidden] { display: none; }
.cr-sheet { position: fixed; inset: 0; z-index: 12500; }
.cr-sheet__backdrop {
    position: absolute; inset: 0;
    background: rgba(8, 10, 20, .42);
    backdrop-filter: blur(3px);
    opacity: 0; transition: opacity var(--motion-med) var(--ease-soft);
}
.cr-sheet__panel {
    position: absolute;
    right: max(12px, env(safe-area-inset-right));
    top: max(70px, calc(env(safe-area-inset-top) + 58px));
    width: min(420px, calc(100vw - 24px));
    max-height: calc(100dvh - 92px);
    overflow: auto;
    padding: 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius-panel);
    background: var(--card);
    box-shadow: var(--shadow-lg);
    opacity: 0; transform: translateY(-8px) scale(.985);
    transition: opacity var(--motion-med) var(--ease-soft), transform .24s var(--ease-soft);
}
.cr-sheet.is-opening .cr-sheet__backdrop,
.cr-sheet.is-open .cr-sheet__backdrop { opacity: 1; }
.cr-sheet.is-opening .cr-sheet__panel,
.cr-sheet.is-open .cr-sheet__panel { opacity: 1; transform: none; }
.cr-sheet.is-closing .cr-sheet__backdrop { opacity: 0; }
.cr-sheet.is-closing .cr-sheet__panel { opacity: 0; transform: translateY(-8px) scale(.985); }

.cr-sheet__head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 12px; padding: 2px 2px 12px;
}
.cr-sheet__head h2 { margin: 0; font-size: var(--text-lg); letter-spacing: -0.01em; color: var(--text-strong); }
.cr-sheet__close {
    width: 40px; height: 40px; flex: 0 0 auto;
    border: 0; border-radius: var(--radius-control);
    background: var(--surface-container); color: var(--text);
    font-size: var(--text-2xl); line-height: 1; cursor: pointer;
}
.cr-sheet__close:hover { background: var(--surface-container-high); }
.cr-sheet__close:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.cr-sheet__paths { display: grid; gap: 6px; }
.cr-sheet__foot {
    margin-top: 10px; padding-top: 10px;
    border-top: 1px solid var(--border);
}
.cr-sheet__foot a {
    display: inline-flex; align-items: center; gap: 7px;
    min-height: 40px; padding: 0 6px;
    color: var(--link); font-size: var(--text-sm); font-weight: 600; text-decoration: none;
}
.cr-sheet__foot a:hover { text-decoration: underline; }
.cr-sheet__foot a:focus-visible { outline: none; box-shadow: var(--ring-focus); border-radius: var(--radius-sm); }

@media (max-width: 700px) {
    .cr-sheet__panel {
        top: auto; right: 0; bottom: 0; left: 0;
        width: auto;
        max-height: min(80dvh, 700px);
        padding: 14px 16px calc(16px + env(safe-area-inset-bottom));
        border-radius: var(--radius-panel) var(--radius-panel) 0 0;
        transform: translateY(105%); opacity: 1;
    }
    .cr-sheet.is-opening .cr-sheet__panel,
    .cr-sheet.is-open .cr-sheet__panel { transform: translateY(0); }
    .cr-sheet.is-closing .cr-sheet__panel { transform: translateY(105%); }
}

/* --- The three paths --------------------------------------------------
   Rows, not a card grid: one scan down the left edge reads all three
   choices, and the row grows to the copy instead of forcing equal heights. */
.cr-path {
    display: flex; align-items: center; gap: 13px;
    min-height: 62px; padding: 12px 13px;
    border: 1px solid transparent; border-radius: var(--radius-card);
    background: transparent;
    color: var(--text); text-decoration: none;
    transition: background var(--motion-fast) var(--ease-soft), border-color var(--motion-fast) var(--ease-soft);
}
.cr-path:hover { background: var(--surface-container); border-color: var(--border); }
.cr-path:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.cr-path__icon {
    flex: 0 0 auto;
    width: 40px; height: 40px;
    display: grid; place-items: center;
    border-radius: var(--radius-control);
    background: var(--surface-container);
    color: var(--secondary);
}
.cr-path:hover .cr-path__icon { background: var(--card); }
.cr-path__body { display: grid; gap: 3px; min-width: 0; }
.cr-path__body strong { font-size: var(--text-base); color: var(--text-strong); }
.cr-path__body span { font-size: var(--text-sm); color: var(--muted); }
.cr-path__go { margin-left: auto; color: var(--muted); flex: 0 0 auto; }
.cr-path:hover .cr-path__go { color: var(--secondary); }

/* --- Hub pages --------------------------------------------------------- */
.cr-shell { max-width: 760px; margin: 0 auto; }

.cr-intro { margin: 4px 0 22px; }
.cr-intro h1 { margin: 0 0 8px; font-size: var(--text-2xl); letter-spacing: -0.02em; color: var(--text-strong); }
.cr-intro p { margin: 0; color: var(--muted); font-size: var(--text-base); max-width: 56ch; }

.cr-paths { display: grid; gap: 6px; padding: 10px; }
.cr-intro-foot { margin-top: 16px; }

.cr-back {
    display: inline-flex; align-items: center; gap: 6px;
    min-height: 40px;
    color: var(--muted); font-size: var(--text-sm); font-weight: 600; text-decoration: none;
}
.cr-back:hover { color: var(--text); }
.cr-back:focus-visible { outline: none; box-shadow: var(--ring-focus); border-radius: var(--radius-sm); }

/* --- Composer ---------------------------------------------------------- */
/* These are cards. Match the incumbent .card exactly rather than landing 2px
   and one shadow-step away from it — request_view.php renders a real .card
   directly above .cr-reply, and a near-miss reads worse than a difference. */
.cr-composer, .cr-reply, .cr-paths {
    padding: 22px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-card);
    background: var(--card);
    box-shadow: var(--shadow-card);
}
.cr-composer__head { margin-bottom: 16px; }
.cr-composer__head h1 { margin: 0 0 6px; font-size: var(--text-2xl); letter-spacing: -0.02em; color: var(--text-strong); }
.cr-composer__head p { margin: 0; color: var(--muted); font-size: var(--text-base); }

.cr-field { display: block; }
.cr-field__label {
    display: block; margin-bottom: 6px;
    font-size: var(--text-sm); font-weight: 600; color: var(--muted-strong);
}
.cr-field textarea {
    width: 100%;
    padding: 12px 13px;
    border: 1px solid var(--border-strong); border-radius: var(--radius-control);
    background: var(--surface-low); color: var(--text);
    font: inherit; font-size: var(--text-base); line-height: 1.55;
    resize: vertical;
}
.cr-field textarea::placeholder { color: var(--muted); }
.cr-field textarea:focus { outline: none; border-color: var(--secondary); box-shadow: var(--ring-focus); }

/* --- Attachment controls ---------------------------------------------- */
.cr-attach { margin-top: 14px; }
.cr-attach__row { display: flex; flex-wrap: wrap; gap: 8px; }
.cr-chip {
    display: inline-flex; align-items: center; gap: 7px;
    min-height: 40px; padding: 0 13px;
    border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
    background: var(--surface-low); color: var(--text);
    font-size: var(--text-sm); font-weight: 600; cursor: pointer;
    transition: background var(--motion-fast) var(--ease-soft), border-color var(--motion-fast) var(--ease-soft);
}
.cr-chip:hover { background: var(--surface-container); border-color: var(--secondary); }
.cr-chip:focus-within, .cr-chip:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.cr-chip svg { color: var(--secondary); }
.cr-chip[disabled] { opacity: .55; cursor: not-allowed; }

/* Recording state: the dot is a live indicator, not decoration — it exists
   only while the microphone is actually open. */
.cr-chip__dot {
    width: 9px; height: 9px; border-radius: 50%;
    background: var(--muted); flex: 0 0 auto;
}
.cr-chip--rec.is-live { border-color: var(--danger); color: var(--danger); }
.cr-chip--rec.is-live .cr-chip__dot { background: var(--danger); animation: cr-pulse 1.4s ease-in-out infinite; }
@keyframes cr-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

.cr-attach__hint { margin: 8px 0 0; font-size: var(--text-xs); color: var(--muted); }
.cr-attach__list { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 6px; }
.cr-attach__list li {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 10px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface-low);
    font-size: var(--text-sm);
}
.cr-attach__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cr-attach__size { margin-left: auto; color: var(--muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
.cr-attach__drop {
    width: 30px; height: 30px; flex: 0 0 auto;
    border: 0; border-radius: var(--radius-sm);
    background: transparent; color: var(--muted);
    font-size: 18px; line-height: 1; cursor: pointer;
}
.cr-attach__drop:hover { background: var(--surface-container); color: var(--danger); }
.cr-attach__drop:focus-visible { outline: none; box-shadow: var(--ring-focus); }

/* --- Captured context -------------------------------------------------- */
.cr-context {
    margin-top: 16px; padding: 13px 14px;
    border: 1px solid var(--border); border-radius: var(--radius-control);
    background: var(--surface-low);
}
.cr-context__title {
    display: block; margin-bottom: 9px;
    font-size: var(--text-xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
    color: var(--muted);
}
.cr-context dl, .cr-ctx { display: flex; flex-wrap: wrap; gap: 8px 26px; margin: 0; }
.cr-context dl > div, .cr-ctx > div { display: grid; gap: 2px; }
.cr-context dt, .cr-ctx dt { font-size: var(--text-xs); color: var(--muted); }
.cr-context dd, .cr-ctx dd { margin: 0; font-size: var(--text-sm); font-weight: 600; color: var(--text); }

.cr-urgent {
    display: flex; align-items: flex-start; gap: 11px;
    margin-top: 14px; padding: 12px 13px;
    border: 1px solid var(--border); border-radius: var(--radius-control);
    background: var(--surface-low);
    cursor: pointer;
}
.cr-urgent input { margin-top: 2px; width: 18px; height: 18px; flex: 0 0 auto; accent-color: var(--danger); }
.cr-urgent span { display: grid; gap: 2px; font-size: var(--text-sm); }
.cr-urgent .muted { font-size: var(--text-sm); }

.cr-composer__foot { margin-top: 20px; display: flex; justify-content: flex-end; }
.cr-submit { min-height: 46px; padding: 0 24px; font-size: var(--text-base); }

/* --- My Requests ------------------------------------------------------- */
.cr-listhead {
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: 16px; flex-wrap: wrap;
    margin: 4px 0 20px;
}
.cr-listhead h1 { margin: 0 0 6px; font-size: var(--text-2xl); letter-spacing: -0.02em; color: var(--text-strong); }
.cr-listhead p { margin: 0; color: var(--muted); font-size: var(--text-base); }

.cr-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.cr-list__item > a {
    display: block; padding: var(--space-4);
    border: 1px solid var(--border-subtle); border-radius: var(--radius-card);
    background: var(--card); color: var(--text); text-decoration: none;
    transition: border-color var(--motion-fast) var(--ease-soft), background var(--motion-fast) var(--ease-soft);
}
.cr-list__item > a:hover { border-color: var(--border); background: var(--surface-high); }
.cr-list__item > a:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.cr-list__top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cr-ref {
    font-size: var(--text-sm); font-weight: 700; letter-spacing: .02em;
    font-variant-numeric: tabular-nums;
    color: var(--secondary);
}
.cr-ref--lg { font-size: var(--text-base); }
.cr-list__excerpt {
    margin: 9px 0 0; font-size: var(--text-sm); line-height: 1.5; color: var(--text);
}
.cr-list__meta {
    display: flex; flex-wrap: wrap; gap: 6px 14px;
    margin-top: 9px; font-size: var(--text-xs); color: var(--muted);
}

/* --- Request detail ---------------------------------------------------- */
.cr-received {
    display: flex; align-items: flex-start; gap: 12px;
    margin: 10px 0 18px; padding: 14px 16px;
    border: 1px solid var(--success); border-radius: var(--radius-card);
    background: var(--status-success-soft);
}
.cr-received__tick { color: var(--success); flex: 0 0 auto; display: inline-flex; }
.cr-received div { display: grid; gap: 3px; }
.cr-received strong { font-size: var(--text-base); color: var(--text-strong); }
.cr-received span { font-size: var(--text-sm); color: var(--muted-strong); }

.cr-detail__head { margin: 8px 0 16px; }
.cr-detail__ident { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.cr-detail__when { margin: 8px 0 0; font-size: var(--text-sm); color: var(--muted); }

.cr-original__body {
    margin: 0; font-size: var(--text-base); line-height: 1.62; color: var(--text);
    max-width: 70ch; white-space: pre-line;
}
.cr-ctx { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); }

.cr-triage__grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 12px; margin-bottom: 12px;
}
.cr-triage__grid label { display: grid; gap: 6px; }
.cr-triage__grid span { font-size: var(--text-sm); font-weight: 600; color: var(--muted-strong); }
.cr-triage__grid select {
    min-height: 42px; padding: 0 11px;
    border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
    background: var(--surface-low); color: var(--text);
    font: inherit; font-size: var(--text-base);
}
.cr-triage__grid select:focus { outline: none; border-color: var(--secondary); box-shadow: var(--ring-focus); }
.cr-triage__form .cr-field textarea { font-size: var(--text-base); }
.cr-triage__hint { margin: 12px 0 16px; font-size: var(--text-sm); color: var(--muted); max-width: 68ch; }

/* --- Attachments ------------------------------------------------------- */
.cr-att-grid { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
.cr-att--image {
    display: block; overflow: hidden;
    border: 1px solid var(--border); border-radius: var(--radius-control);
    line-height: 0;
}
.cr-att--image img { display: block; max-width: 220px; max-height: 160px; object-fit: cover; }
.cr-att--image:hover { border-color: var(--secondary); }
.cr-att--image:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.cr-att--file {
    display: inline-flex; align-items: center; gap: 9px;
    min-height: 44px; padding: 0 13px;
    border: 1px solid var(--border); border-radius: var(--radius-control);
    background: var(--surface-low); color: var(--text);
    font-size: var(--text-sm); font-weight: 600; text-decoration: none;
}
.cr-att--file:hover { border-color: var(--secondary); }
.cr-att--file:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.cr-att--file svg { color: var(--secondary); }
.cr-att--audio {
    display: grid; gap: 6px;
    padding: 11px 13px;
    border: 1px solid var(--border); border-radius: var(--radius-control);
    background: var(--surface-low);
}
.cr-att--audio audio { width: min(320px, 100%); height: 38px; }
.cr-att__meta { font-size: var(--text-xs); color: var(--muted); font-variant-numeric: tabular-nums; }
.cr-att__name { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --- Thread ------------------------------------------------------------ */
.cr-thread { margin-top: 26px; }
.cr-thread__title {
    margin: 0 0 14px; font-size: var(--text-base); font-weight: 700;
    letter-spacing: .01em; color: var(--text-strong);
}
.cr-thread__empty { margin: 0 0 16px; font-size: var(--text-sm); color: var(--muted); max-width: 62ch; }

.cr-msgs { list-style: none; margin: 0 0 18px; padding: 0; display: grid; gap: 10px; }
.cr-msg {
    padding: 13px 15px;
    border: 1px solid var(--border); border-radius: var(--radius-card);
    background: var(--card);
}
/* A reviewer's message is the one a submitter is scanning for, so that is the
   side that gets marked. --surface-container is a real step from --card (not
   the adjacent rung --surface-low was), and the accent rule carries the
   distinction without relying on colour at all. */
.cr-msg.is-mine { background: var(--surface-low); }
.cr-msg--reviewer {
    background: var(--surface-container);
    border-left: 3px solid var(--accent);
}
.cr-msg__head { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; margin-bottom: 6px; }
.cr-msg__head strong { font-size: var(--text-sm); color: var(--text-strong); }
.cr-msg__role {
    padding: 2px 7px; border-radius: var(--radius-round);
    background: var(--accent-soft);
    color: var(--secondary);
    font-size: var(--text-xs); font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
}
.cr-msg__head time { margin-left: auto; font-size: var(--text-xs); color: var(--muted); font-variant-numeric: tabular-nums; }
.cr-msg__body { margin: 0; font-size: var(--text-base); line-height: 1.58; color: var(--text); white-space: pre-line; }


.cr-reply__foot {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; flex-wrap: wrap; margin-top: 12px;
}

@media (max-width: 640px) {
    .cr-composer, .cr-reply { padding: 15px; }
    .cr-att--image img { max-width: 150px; max-height: 120px; }
    .cr-reply__foot { flex-direction: column; align-items: stretch; }
    .cr-reply__foot .btn { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
    .cr-trigger, .cr-sheet__backdrop, .cr-sheet__panel, .cr-path { transition: none !important; }
    .cr-chip--rec.is-live .cr-chip__dot { animation: none; }
}

/* Paper output never carries the Hub chrome. */
@media print {
    .cr-trigger, .cr-sheet, .cr-back, .cr-reply, .cr-attach, .cr-triage { display: none !important; }
}
