/* layout-core.css — generated from layout_css() in includes/layout.php. Edit there is NOT the source anymore; edit this file. */
:root {
    color-scheme: light;
    /* ------------------------------------------------------------------
       GDF AirCore "FLIGHT DECK" system (2026-07-02 ground-up redesign).
       Cockpit-placard / ops-status-wall language: flat cool paper, ruled
       panels (hairlines + tint steps, no floating shadows), condensed
       placard display type, ALL data figures in mono, one saturated
       accent (GDF gold) expressed as the 3px "keel line" on active /
       priority elements. Identity stays unmistakably Guyana Defence
       Force: deep green + gold; red critical-only.
       Token NAMES are load-bearing (7k lines of component CSS + per-page
       glue resolve them) — values changed, names kept.
       ------------------------------------------------------------------ */
    --bg: #EFF1EC;
    --card: #FAFBF8;
    --surface: #FFFFFF;
    --surface-low: #F4F6F1;
    --surface-high: #FFFFFF;
    --surface-container: #E9EDE6;
    --surface-container-high: #E1E6DD;
    --surface-container-highest: #D7DED2;
    --inverse-surface: #10281A;
    --inverse-on-surface: #ECF1EB;
    --text: #1B2620;
    --text-strong: #0C1811;
    --muted: #5F6E64;
    --muted-strong: #47564C;
    --primary: #173F29;
    --primary-hover: #0D2818;
    --secondary: #1D5233;
    --secondary-hover: #173F29;
    --link: #1D5233;
    --border: #D8DED3;
    --border-strong: #B9C3B4;
    --outline: #75816F;
    --success: #2E6B34;
    --info: #2D6A4F;
    --danger: #A31621;
    --warning: #8A6414;
    /* Signature gold accent — the single saturated colour. Expressed as the
       keel line, active tab marker, focus ring and gold CTAs. */
    --accent-gold: #E8B923;
    --accent-gold-strong: #C79B0A;
    --accent-gold-soft: rgba(232, 185, 35, 0.14);
    --accent-gold-line: rgba(199, 155, 10, 0.42);
    /* Dark panel — the ops-wall surface (command bar, display shells,
       priority panels). Flat deep green, no gradient sheen. */
    --panel-dark: #0E2718;
    --panel-dark-2: #143521;
    --panel-on: #ECF1EB;
    --panel-muted: #93A899;
    /* Active "ink" marker — deep green (legacy name kept). */
    --ink-pill: #12271A;
    /* RETIRED: Air-Corps blue. Tokens kept only so any straggling reference
       renders on-brand green instead of navy (live uses are purged). */
    --accent-blue: #2D6A4F;
    --accent-blue-deep: #173F29;
    --accent-blue-soft: rgba(45, 106, 79, 0.10);
    /* FLIGHT DECK elevation = rules, not shadows. The shadow tokens now
       draw 1px hairline "rings" so every legacy shadow consumer renders
       as a ruled placard instead of a floating card. */
    --rule: 1px solid #D8DED3;
    --rule-strong: 2px solid #B9C3B4;
    --keel: 3px solid #E8B923;
    --shadow-xs: 0 0 0 1px rgba(27, 38, 32, 0.07);
    --shadow-sm: 0 0 0 1px rgba(27, 38, 32, 0.09);
    --shadow-md: 0 0 0 1px rgba(27, 38, 32, 0.11);
    --shadow-lg: 0 0 0 1px rgba(27, 38, 32, 0.14);
    /* Focus stays a bold gold ring — visible on paper AND dark panels. */
    --ring-focus: 0 0 0 3px rgba(232, 185, 35, 0.55);
    /* Placard geometry: flat 3px everywhere; controls 4px. The pill token
       is intentionally squared — pill shapes are the old system's DNA. */
    --radius: 3px;
    --radius-sm: 3px;
    --radius-lg: 4px;
    --radius-pill: 4px;
    /* Spacing scale — one rhythm for the whole deck. Edited/new rules
       consume these instead of re-inventing magic paddings. */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 24px;
    --space-6: 32px;
    /* Flat panel fills (legacy gradient token names kept, gradients gone). */
    --grad-jags: linear-gradient(180deg, #0E2718 0%, #0E2718 100%);
    --grad-soft: linear-gradient(180deg, #FAFBF8 0%, #FAFBF8 100%);
    --grad-gold: linear-gradient(180deg, #E8B923 0%, #E8B923 100%);
    /* Page canvas: flat cool paper. The wash is dead. */
    --grad-page: linear-gradient(180deg, #EFF1EC 0%, #EFF1EC 100%);

    /* ------------------------------------------------------------------
       Aliases — legacy token NAMES kept so existing call sites keep
       working; the VALUES now resolve to the GDF green scale. 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:        #173F29;  /* same as --primary */
    --jags-blue-deep:   #0D2818;  /* same as --primary-hover */
    --jags-blue-soft:   #2D6A4F;  /* same as --info */
    --jags-navy:        #1D5233;  /* same as --secondary */
    --jags-surface:     #FFFFFF;
    --jags-surface-low: #FAFAF7;
    --jags-success:     #4A6733;  /* same as --success */
    --jags-warning:     #B6883A;  /* same as --warning */
    --jags-danger:      #A31621;  /* 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
       army-green rail (GDF AirCore 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 the GDF gold so the active
       marker reads as a deliberate accent against the green.
       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. ------------------------------ */
    /* "Command Rail" — a floating deep-green tactical console panel
       (2026-06-11 distinctive-redesign pass). Dark rail over the warm ivory
       canvas = command/ops character, not generic SaaS. The active item is a
       "selected channel": a raised panel with a 3px gold left bar (NOT a
       pill); section labels are mono small-caps with a leading gold tick. */
    /* FLIGHT DECK: these tokens now drive the mobile COMMAND SHEET (the
       bottom-up full-screen nav) and the tier-1 command bar. There is no
       desktop left rail any more. Names kept — the sheet reuses the
       .sidebar element and its guard-pinned drawer mechanics. */
    --sidebar-bg:        #0E2718;  /* command sheet / bar base */
    --sidebar-bg-2:      #143521;
    --sidebar-text:      #ECF1EB;
    --sidebar-muted:     #93A899;
    --sidebar-border:    rgba(255, 255, 255, 0.10);
    --sidebar-hover-bg:  rgba(255, 255, 255, 0.06);
    --sidebar-active-bg: rgba(255, 255, 255, 0.08);
    --sidebar-accent:    #E8B923;
    --sidebar-brand-bg:  transparent;
    --grad-sidebar:      linear-gradient(180deg, #0E2718 0%, #0E2718 100%);

    /* ------------------------------------------------------------------
       Typography — FLIGHT DECK placard voice. Display/nav/headings use a
       condensed grotesque stack (system fonts only, no webfont, degrades
       to Arial Narrow); body is the plain system stack; EVERY numeral,
       time, registration and status figure uses mono (cockpit
       convention). Inter is deliberately gone from the stacks.
       ------------------------------------------------------------------ */
    --font-sans:    system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-display: "Avenir Next Condensed", "Helvetica Neue Condensed", "Arial Narrow", "Roboto Condensed", "Segoe UI Semibold", system-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: 82px; /* 60px floating dock rail + 10px bottom gap + cushion */
    --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);
    /* Floating command dock (mobile) — capsule rail + detached primary action. */
    --dock-radius: 28px;
    --dock-item-radius: 22px;
    --dock-shadow: 0 10px 30px rgba(10, 33, 20, .30), 0 2px 8px rgba(10, 33, 20, .22);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* The app shell is purpose-built for a polished light theme. Display boards
   (TV wallboards) opt into their own dark scheme via layout_display_open().
   We pin color-scheme to light here so mobile browsers (Chrome / Samsung
   Internet / iOS Safari with "Force dark" enabled) do not auto-invert the
   page and produce the muddy half-light/half-dark look we observed. */
html { color-scheme: light; background: var(--bg); }
body {
    font-family: var(--font-sans);
    /* FLIGHT DECK: flat cool paper. No wash, no glow, nothing floats. */
    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;
    /* Tabular numerals everywhere — data columns must align. */
    font-variant-numeric: tabular-nums;
}
/* If a user agent still forces dark mode, neutralise it for app surfaces.
   Display boards intentionally use their own dark palette — those rules are
   namespaced under .display-shell and remain untouched. */
@media (prefers-color-scheme: dark) {
    :root { color-scheme: light; }
    html, body { background: var(--bg); color: var(--text); }
}
/* Baseline heading rhythm — placard voice: condensed, semi-bold, tight.
   Page-level pages can still override per panel. */
h1, h2, h3, h4 {
    font-family: var(--font-display);
    color: var(--text-strong);
    line-height: var(--line-tight);
    letter-spacing: 0.005em;
    margin: 0;
    font-weight: 600;
}
h1 { font-size: 26px; text-transform: none; letter-spacing: 0.01em; }
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);
    /* Muted gold (darkened for small-caps legibility on light surfaces). */
    color: #A8861D;
    font-weight: 600;
}

/* App shell — FLIGHT DECK: single column under the top command bar.
   There is NO desktop rail: the .sidebar element exists only as the
   mobile COMMAND SHEET (≤900px, bottom-up full screen — see the mobile
   drawer block, whose guard-pinned mechanics are unchanged). */
.app-shell {
    min-height: 100vh;
    min-height: 100dvh;
    display: block;
    padding: 0;
}
@media (min-width: 901px) {
    .sidebar { display: none; }
}
.sidebar {
    background: var(--sidebar-bg);
    color: var(--sidebar-text);
    border: 0;
    padding: 16px 13px 16px;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(255,255,255,0.20) 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.30); }
.sidebar-brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    margin: 4px 6px 18px;
    padding: 12px 10px 14px;
    /* Crest sits directly on the ivory panel now (no white lockup card). */
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--sidebar-border);
    border-radius: 0;
}
.sidebar-brand img { width: auto; height: 70px; max-height: 70px; object-fit: contain; background: transparent; display: block; filter: drop-shadow(0 4px 10px rgba(0,0,0,0.28)); }
.sidebar-brand .brand-sub {
    font-size: 9px; color: var(--sidebar-muted); text-transform: uppercase;
    letter-spacing: 0.2em; text-align: center; font-weight: 700; padding-bottom: 0;
    font-family: var(--font-mono);
}
/* Section labels — mono small-caps with a short gold "tick" rule before the
   text, like a console channel group header. */
.sidebar-section {
    display: flex; align-items: center; gap: 8px;
    font-family: var(--font-mono);
    font-size: 9.5px;
    text-transform: uppercase;
    letter-spacing: 0.2em;
    color: var(--sidebar-muted);
    margin: 18px 12px 9px;
    font-weight: 600;
}
.sidebar-section::before {
    content: ""; width: 12px; height: 2px; border-radius: 2px;
    background: var(--sidebar-accent); flex: 0 0 12px; opacity: 0.9;
}
.sidebar nav a {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 9px 12px 9px 14px;
    border-radius: 3px;
    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: #FFFFFF; }
.sidebar nav a:hover .nav-icon {
    color: var(--accent-gold);
    background: rgba(232, 185, 35, 0.14);
    border-color: rgba(232, 185, 35, 0.30);
}
.sidebar nav a.active {
    /* Selected row — a raised inset panel whose icon CHIP fills solid gold
       (see .active .nav-icon). The old 3px gold left command-bar was the
       JAGS-shared tell; it's gone — the filled chip now carries selection. */
    background: var(--sidebar-active-bg);
    color: #FFFFFF;
    font-weight: 600;
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.06), inset 0 1px 0 rgba(255,255,255,0.05);
}
.sidebar nav a.active .nav-icon {
    /* Solid gold tile + dark glyph — the Panze "filled active" signature. */
    color: var(--sidebar-bg);
    background: var(--sidebar-accent);
    border-color: var(--sidebar-accent);
    box-shadow: 0 2px 8px rgba(232, 185, 35, 0.35);
}
.nav-icon {
    /* Panze-inspired icon "chip" (2026-06-29 de-JAGS pass): each nav glyph
       sits in its own soft rounded tile instead of floating bare beside the
       label. Revert to the original bare-icon look by restoring 18px
       width/height/flex and dropping background/border/border-radius. */
    width: 30px; height: 30px;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--sidebar-muted);
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--sidebar-border);
    border-radius: 3px;
    transition: color var(--motion-fast) var(--ease-out),
                background var(--motion-fast) var(--ease-out),
                border-color var(--motion-fast) var(--ease-out),
                box-shadow var(--motion-fast) var(--ease-out);
    flex: 0 0 30px;
}
.nav-icon svg { width: 18px; height: 18px; display: block; }
.nav-icon .jags-icon-glyph { font-size: 14px; line-height: 1; }
/* "Spark" — the single filled focal element inside the bespoke GDF instrument
   hero glyphs (radar sweep, gauge needle, shield check, etc.; class set in
   icon_svg_paths()). Gold at rest so the redesign is visible on load; flips to
   the rail base on the active gold chip so it never sits gold-on-gold. The
   inline fill="currentColor" on the path is the no-CSS fallback (PDF/email),
   which CSS overrides here. Works on every surface since --accent-gold is :root. */
.ic-spark { fill: var(--accent-gold); stroke: none; }
.sidebar nav a.active .nav-icon .ic-spark { fill: var(--sidebar-bg); }

/* ---------- 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 {
    display: flex; align-items: center; gap: 8px;
    margin: 14px 12px 7px;
    padding-top: 2px;
    color: var(--sidebar-muted);
    /* Console channel-group header — mono small-caps with a gold tick. */
    font-family: var(--font-mono);
    font-size: 9.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.2em;
}
.sidebar nav.nav-grouped .nav-group-section::before {
    content: ""; width: 12px; height: 2px; border-radius: 2px;
    background: var(--sidebar-accent); flex: 0 0 12px; opacity: 0.9;
}
.sidebar nav.nav-grouped .nav-group-section--first { margin-top: 4px; }
/* ---------- End admin grouped workspace navigation ---------- */
/* Live status strip — a small console readout above the account chip. */
.sidebar-status {
    display: flex; align-items: center; gap: 8px;
    margin: 14px 6px 8px;
    padding: 8px 11px;
    border-radius: 3px;
    background: rgba(63, 122, 62, 0.14);
    border: 1px solid rgba(63, 122, 62, 0.26);
    font-family: var(--font-mono);
    font-size: 9.5px; font-weight: 600; letter-spacing: 0.16em;
    text-transform: uppercase; color: #9FD3A0;
}
.sidebar-status .dot {
    width: 7px; height: 7px; border-radius: 50%; flex: 0 0 7px;
    background: #58C45B; box-shadow: 0 0 0 0 rgba(88, 196, 91, 0.55);
    animation: gdfPulse 2.4s ease-out infinite;
}
@keyframes gdfPulse {
    0%   { box-shadow: 0 0 0 0 rgba(88, 196, 91, 0.5); }
    70%  { box-shadow: 0 0 0 6px rgba(88, 196, 91, 0); }
    100% { box-shadow: 0 0 0 0 rgba(88, 196, 91, 0); }
}
@media (prefers-reduced-motion: reduce) { .sidebar-status .dot { animation: none; } }
.sidebar-account {
    margin-top: 4px;
    padding: 10px 11px;
    border-radius: 3px;
    background: rgba(255, 255, 255, 0.045);
    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(163, 22, 33,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; }

/* ==================================================================
   FLIGHT DECK COMMAND BAR — tier 1. Dark green placard strip across
   the very top: crest + unit line, DOMAIN TABS (condensed uppercase,
   active tab carries the 3px gold keel line), mono clock. On phones it
   holds the crest + hamburger + page title; tabs live in the command
   sheet instead.
   ================================================================== */
:root { --fd-bar-h: 52px; }
.fd-bar {
    position: sticky;
    top: 0;
    z-index: 60;
    height: var(--fd-bar-h);
    display: flex;
    align-items: stretch;
    gap: 0;
    background: var(--panel-dark);
    color: var(--panel-on);
    border-bottom: var(--keel);
    padding: 0 14px 0 10px;
}
.fd-ident {
    display: flex; align-items: center; gap: 10px;
    padding: 0 14px 0 4px;
    min-width: 0;
    text-decoration: none;
    color: var(--panel-on);
    border-right: 1px solid rgba(255,255,255,0.12);
}
.fd-ident img { height: 34px; width: auto; display: block; }
.fd-ident .fd-ident-name {
    font-family: var(--font-display);
    font-size: 17px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
}
.fd-ident .fd-ident-sub {
    display: block;
    font-family: var(--font-mono);
    font-size: 8.5px;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--panel-muted);
    margin-top: 2px;
}
.fd-tabs {
    display: flex;
    align-items: stretch;
    gap: 2px;
    margin-left: 8px;
    min-width: 0;
    overflow-x: auto;
    scrollbar-width: none;
}
.fd-tabs::-webkit-scrollbar { display: none; }
.fd-tabs a {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 0 16px;
    font-family: var(--font-display);
    font-size: 13.5px;
    font-weight: 600;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--panel-muted);
    text-decoration: none;
    border-bottom: 3px solid transparent;
    margin-bottom: -3px; /* keel sits ON the bar's gold rule */
    white-space: nowrap;
    transition: color var(--motion-fast) var(--ease-out);
}
.fd-tabs a:hover { color: var(--panel-on); }
.fd-tabs a:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.fd-tabs a.active {
    color: #FFFFFF;
    border-bottom-color: var(--accent-gold);
}
.fd-clock {
    margin-left: auto;
    display: flex; align-items: center;
    font-family: var(--font-mono);
    font-size: 12.5px;
    letter-spacing: 0.08em;
    color: var(--panel-muted);
    white-space: nowrap;
    padding-left: 14px;
}
.fd-clock strong { color: var(--panel-on); font-weight: 600; }
@media (max-width: 900px) {
    .fd-tabs, .fd-clock { display: none; }
    /* html/body get overflow-x:hidden on phones (breaks sticky); the bar
       scrolls with the page there — the fixed bottom nav owns persistence. */
    .fd-bar { padding-right: 8px; position: static; }
    .fd-ident { border-right: none; }
    .fd-ident .fd-ident-sub { display: none; }
    .fd-ident .fd-ident-name { font-size: 15px; }
    .user-menu { margin-left: auto; }
}
/* The tier-2 h1 names the page on every width — the bar's own title slot
   is dormant (kept in markup for JS that updates it). One rule, not two
   per-breakpoint copies. */
.fd-bar .fd-page-title { display: none; }

.fd-sheet-close {
    position: sticky;
    top: 0;
    z-index: 2;
    display: inline-flex; align-items: center; gap: 8px;
    margin-left: auto;
    min-height: 44px;
    padding: 10px 16px;
    font-family: var(--font-display);
    font-size: 13px; font-weight: 600;
    letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--panel-on);
    background: rgba(255,255,255,0.08);
    border: 1px solid rgba(255,255,255,0.18);
    border-radius: var(--radius-lg);
    cursor: pointer;
    float: right;
}
.fd-sheet-close:focus-visible { outline: none; box-shadow: var(--ring-focus); }

/* a11y: any coarse pointer gets the 44px tap floor on the strip controls. */
@media (pointer: coarse) {
    .topbar-bell, .topbar-refresh, #jags-tour-launcher, a.jags-system-run-pill,
    .fd-sheet-close, .mobile-nav-toggle { min-width: 44px; min-height: 44px; }
}

/* Tier 2 — the SECTION STRIP (.topbar, name kept for JS + page glue).
   Flat paper strip under the command bar: page title (placard), the
   active domain's section links, utilities as square ruled placards on
   the right end. Nothing floats; a 2px rule closes the strip. */
.topbar {
    background: var(--surface);
    border-bottom: var(--rule-strong);
    border-radius: 0;
    padding: 8px 18px;
    margin-bottom: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    position: sticky;
    top: var(--fd-bar-h);
    z-index: 50;
    min-height: 50px;
}
@media (max-width: 900px) { .topbar { top: 0; position: static; } }
.topbar h1 {
    margin: 0;
    flex: 0 0 auto;
    max-width: 340px;
    font-size: 19px;
    font-family: var(--font-display);
    letter-spacing: 0.045em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--text-strong);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Section links — the active domain's routes, slim placard tabs. */
.fd-sections {
    display: flex; align-items: center; gap: 2px;
    min-width: 0; overflow-x: auto; scrollbar-width: none;
    margin-left: 6px; padding-left: 14px;
    border-left: 1px solid var(--border);
}
.fd-sections::-webkit-scrollbar { display: none; }
.fd-sections a {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 7px 10px;
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--muted-strong);
    text-decoration: none;
    border-radius: var(--radius-lg);
    white-space: nowrap;
}
.fd-sections a:hover { background: var(--surface-container); color: var(--text-strong); }
.fd-sections a:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.fd-sections a.active {
    color: var(--text-strong);
    font-weight: 600;
    background: var(--accent-gold-soft);
    box-shadow: inset 0 -3px 0 0 var(--accent-gold);
}
@media (max-width: 900px) { .fd-sections { display: none; } }
/* Sub-nav overflow affordance (audit C P2-2). These horizontal strips hide
   their scrollbar, so a clipped / off-screen tab used to be silent. The
   data-scroll attribute is maintained by layout-core.js; here we fade the
   edge(s) that still have content, cueing "scroll for more" and keeping the
   active tab from being truncated without warning. No mask when it all fits. */
.fd-tabs[data-scroll="start"], .fd-sections[data-scroll="start"] {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent 100%);
            mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent 100%);
}
.fd-tabs[data-scroll="mid"], .fd-sections[data-scroll="mid"] {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 32px, #000 calc(100% - 32px), transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 32px, #000 calc(100% - 32px), transparent 100%);
}
.fd-tabs[data-scroll="end"], .fd-sections[data-scroll="end"] {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 32px, #000 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 32px, #000 100%);
}
/* 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: 190px;
    max-width: 300px;
    border-radius: var(--radius-lg);
    border: 1px solid var(--border-strong);
    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: #fff; 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: #fff;
    border: 1px solid var(--border);
    border-radius: 3px;
    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(45, 106, 79,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: 38px; height: 38px;
    border-radius: var(--radius-lg);
    color: var(--text-strong);
    background: var(--surface-low);
    border: 1px solid var(--border-strong);
    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(45, 106, 79,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: 4px;
    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) {
    /* a11y: 44px minimum tap target on touch layouts. */
    .topbar-bell { width: 44px; height: 44px; }
}

/* 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: 38px; height: 38px;
    padding: 0;
    border-radius: var(--radius-lg);
    color: var(--text-strong);
    background: var(--surface-low);
    border: 1px solid var(--border-strong);
    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(45, 106, 79,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: 44px; height: 44px; }
}

/* ---------------------------------------------------------------
   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: var(--radius-lg);
    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, #2D6A4F, #1D5233); }

/* 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, 106, 96,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(163, 22, 33,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(45, 106, 79,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, 106, 96,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: var(--radius-lg);
    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: 18px 22px 40px; max-width: 1500px; margin: 0 auto; width: 100%; }
.content-narrow { max-width: 760px; 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 — large radius, generous padding, soft layered lift. */
.card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-md);
    padding: 24px;
    transition:
        box-shadow var(--motion-med) var(--ease-soft),
        border-color var(--motion-med) var(--ease-soft);
}
.card + .card { margin-top: 20px; }
.card-elevated { box-shadow: var(--shadow-lg); }
/* 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(255,255,255,0.85), rgba(255,255,255,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);
}

/* ONE placard-header system (2026-07-02 refinement): every panel header
   in the app — dashboard, planners, records, admin — speaks the same
   condensed-uppercase placard voice. Matches the dashboard's
   .fdd-panel-head exactly so nothing feels one-off. An optional leading
   instrument icon (inline SVG inside the h2) picks up the family look;
   a .section-desc line directly below translates the ops jargon for
   non-expert users. */
.section-title {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-3); flex-wrap: wrap;
    margin: 0 0 14px;
}
.section-title h2 {
    margin: 0;
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-strong);
    display: inline-flex; align-items: center; gap: var(--space-2);
    line-height: 1.25;
}
.section-title h2 svg { width: 16px; height: 16px; color: var(--secondary); flex: none; }
.section-title .muted { font-size: var(--text-sm); text-transform: none; letter-spacing: normal; }
/* Plain-language descriptor tucked under a .section-title. */
.section-desc {
    margin: -8px 0 14px;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--muted);
    max-width: 68ch;
}
.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: #7C5A1F; }
.feature-value.danger { background: rgba(163, 22, 33,0.06); }
.feature-value.danger .feat-val { color: #8C1220; }
.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: 3px;
    background: linear-gradient(180deg, rgba(29, 82, 51,0.10), rgba(29, 82, 51,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: 4px;
    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: #3B5326; }
.countdown-chip.info    { background: rgba(45, 106, 79,0.14); color: #1D5233; }
.countdown-chip.warn    { background: rgba(216,181,109,0.18); color: #7C5A1F; }
.countdown-chip.danger  { background: rgba(163, 22, 33,0.14); color: #8C1220; }
.countdown-chip.muted   { background: rgba(94, 106, 96,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(201,162,39,0.55), 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(13, 40, 24,0.18), 0 2px 6px rgba(13, 40, 24,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: 4px;
    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, 106, 96,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(163, 22, 33,0.40); background: linear-gradient(180deg, rgba(163, 22, 33,0.04), #fff); }
.jags-toast.danger  .toast-icon { color: #A31621; }
.jags-toast.info    { border-color: rgba(45, 106, 79,0.36); background: linear-gradient(180deg, rgba(45, 106, 79,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.
   ==================================================================== */
/* Identity placard (2026-07-02 refinement) — lives on the DARK tier-1
   command bar. Instrument-bezel avatar (gold keel frame with a dark
   gap), name over a ruled uppercase role-tag, chevron affordance.
   Never a plain bordered initials square. */
.user-menu-button {
    display: flex; align-items: center; gap: 12px;
    padding: 4px 10px 4px 14px;
    background: transparent;
    border: 1px solid transparent;
    border-left: 1px solid rgba(255,255,255,0.12);
    border-radius: 0;
    cursor: pointer;
    font-family: inherit;
    font-size: var(--text-sm);
    color: var(--panel-on);
    height: 100%;
    transition: background var(--motion-fast) var(--ease-out);
}
.user-menu-button .who { line-height: 1.15; text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 3px; }
.user-menu-button .who .name { font-weight: 600; color: var(--panel-on); white-space: nowrap; }
/* Ruled role-tag — rank placard under the name. */
.fd-role-tag {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 1px 6px;
    border: 1px solid rgba(232, 185, 35, 0.45);
    border-radius: var(--radius);
    background: rgba(232, 185, 35, 0.08);
    font-family: var(--font-display);
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #E9CD6F;
    line-height: 1.6;
    white-space: nowrap;
}
.fd-role-tag::before {
    content: "";
    width: 4px; height: 4px;
    background: var(--accent-gold);
    flex: none;
}
.fd-role-tag.on-paper { color: #7A5E0C; background: var(--accent-gold-soft); border-color: var(--accent-gold-line); }
/* Instrument bezel — hairline gold frame + dark gap around the avatar. */
.fd-avatar-bezel {
    display: inline-flex;
    padding: 2px;
    border: 1px solid rgba(232, 185, 35, 0.8);
    border-radius: 5px;
    background: rgba(0, 0, 0, 0.25);
    flex: none;
}
.fd-avatar-bezel .jags-avatar { box-shadow: none; border-radius: 3px; }
.fd-avatar-bezel.on-paper { border-color: var(--accent-gold-strong); background: var(--accent-gold-soft); }
.user-menu-button .um-chev { color: var(--panel-muted); flex: none; transition: transform var(--motion-fast) var(--ease-out); }
.user-menu-button[aria-expanded="true"] .um-chev { transform: rotate(180deg); }
.user-menu-button:hover { background: rgba(255,255,255,0.07); }
.user-menu-button:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.user-menu-button[aria-expanded="true"] { background: rgba(255,255,255,0.10); }
@media (max-width: 900px) {
    .user-menu-button .who, .user-menu-button .um-chev { display: none; }
    .user-menu-button { border-left: none; padding: 4px; min-width: 44px; min-height: 44px; justify-content: center; }
}

.user-menu {
    position: relative;
    display: flex; align-items: stretch;
    margin-left: 6px;
}
.user-menu-popover {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    min-width: 268px;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 16px 40px rgba(13, 40, 24,0.16), 0 2px 6px rgba(13, 40, 24,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 {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 4px 10px;
    align-items: center;
    padding: 10px 12px 10px;
    border-bottom: 2px solid var(--border-strong);
    margin-bottom: 4px;
}
.user-menu-popover .menu-head > :nth-child(n+3) { grid-column: 1 / -1; }
.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; overflow-wrap: anywhere; }
/* Placard section labels inside the account menu. */
.user-menu-popover .menu-sect {
    font-family: var(--font-display);
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--muted);
    padding: 9px 12px 3px;
}
.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(45, 106, 79,0.08); color: var(--primary); }
.user-menu-popover .menu-item:focus-visible { outline: none; background: rgba(45, 106, 79,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: #8C1220; }
.user-menu-popover .menu-item.danger:hover { background: rgba(163, 22, 33,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(13, 40, 24,0.16), 0 2px 6px rgba(13, 40, 24,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);
}
.bell-popover .bell-list a:hover { background: rgba(45, 106, 79,0.06); }
.bell-popover .bell-list a:focus-visible { outline: none; background: rgba(45, 106, 79,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); }

/* ====================================================================
   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(13, 40, 24,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(13, 40, 24,0.30), 0 4px 12px rgba(13, 40, 24,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(45, 106, 79,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(45, 106, 79,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, 106, 96,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(45, 106, 79,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: 4px;
    background: linear-gradient(180deg, rgba(29, 82, 51,0.08), rgba(29, 82, 51,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; }
/* Compact one-line empty state for ruled panels (dashboard queues,
   planner lists). Same voice everywhere: quiet, informative, never a
   blank hole. */
.empty-line {
    display: flex; align-items: center; gap: var(--space-2);
    padding: var(--space-4);
    color: var(--muted);
    font-size: 13px;
    line-height: 1.5;
}
.empty-line svg { width: 15px; height: 15px; flex: none; opacity: 0.75; }

/* Plain-language tooltip affordance for mono codes and status
   abbreviations (SVC, INSP., NM, RTB, PIC/SIC …). Dotted underline +
   help cursor signals "hover / long-press me"; the title attribute
   carries the expansion. Keyboard users get the expansion via the
   title on a focusable element where pages provide one. */
.gdf-abbr, abbr[title] {
    text-decoration: underline dotted rgba(95, 110, 100, 0.65);
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
    cursor: help;
}
/* Touch-usable expansion: the native title tooltip never appears on
   mobile browsers, so a small script (jags_abbr_tip_script) makes each
   abbr focusable and mirrors title -> data-tip; tap/focus shows this
   ruled placard bubble. Hover on desktop keeps the native tooltip too —
   the bubble also appears on keyboard focus, which doubles as the
   visible-focus treatment. */
.gdf-abbr, abbr[title] { position: relative; }
.gdf-abbr:focus { outline: none; }
.gdf-abbr:focus-visible { box-shadow: var(--ring-focus); border-radius: 2px; }
.gdf-abbr.tip-open::after, abbr[title].tip-open::after {
    content: attr(data-tip);
    position: absolute;
    left: 50%;
    bottom: calc(100% + 6px);
    transform: translateX(-50%);
    z-index: 1300; /* above sticky table heads + toolbars, below chrome */
    max-width: min(78vw, 320px);
    width: max-content;
    padding: 7px 10px;
    background: var(--panel-dark, #10281A);
    color: #F2F3EE;
    font-family: var(--font-body, system-ui);
    font-size: 12.5px;
    font-weight: 500;
    letter-spacing: 0.02em;
    line-height: 1.4;
    text-transform: none;
    white-space: normal;
    border: 1px solid rgba(232, 185, 35, 0.55);
    border-radius: 3px;
    pointer-events: none;
}
/* Keep the bubble on-screen when the abbr sits near the left/right edge
   of a scroll container or the viewport. */
.gdf-abbr.tip-open.tip-edge-left::after, abbr[title].tip-open.tip-edge-left::after { left: 0; transform: none; }
.gdf-abbr.tip-open.tip-edge-right::after, abbr[title].tip-open.tip-edge-right::after { left: auto; right: 0; transform: none; }

/* ====================================================================
   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: 4px;
    background: rgba(45, 106, 79,0.10);
    border: 1px solid rgba(45, 106, 79,0.22);
    color: var(--secondary);
    font-weight: 600;
    line-height: 1.3;
}
.filter-chips .filter-chip .x {
    width: 18px; height: 18px;
    border-radius: 4px;
    background: rgba(45, 106, 79,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: 4px;
    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, 106, 96,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: #FAFBF6; }

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(45, 106, 79,0.07);
}
table.tbl tbody tr.row-link:focus-within td {
    background: rgba(45, 106, 79,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(163, 22, 33,0.0); }
    50%      { box-shadow: 0 0 0 4px rgba(163, 22, 33,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;
    /* Muted-gold eyebrow — darkened from GDF_BRAND_GOLD_MUTED (#C9A227)
       so the 11px caps stay legible on the warm canvas. */
    color: #A8861D;
    font-weight: 700;
    margin-bottom: 2px;
}
.page-header-text h1,
.page-header-text h2 {
    margin: 0;
    /* FLIGHT DECK placard page title — condensed, tight-tracked, upper.
       (Replaces the JAGS-era 38px "editorial" heading.) */
    font-family: var(--font-display);
    font-size: 30px;
    font-weight: 650;
    letter-spacing: 0.015em;
    text-transform: uppercase;
    line-height: 1.05;
    color: var(--text-strong);
}
.page-header-text p {
    margin: 6px 0 0;
    font-size: 14.5px;
    line-height: 1.5;
    color: var(--muted);
}
.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: 27px; }
    .page-header-actions .btn { flex: 1 1 auto; justify-content: center; }
}

/* 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;
}
/* FLIGHT DECK: flat placard tile — the old soft radial spotlight is gone. */
.stat .label { font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--muted); font-weight: 600; }
/* Placard figures — mono, heavy, tabular. */
.stat .value { font-family: var(--font-mono); font-size: 34px; font-weight: 700; letter-spacing: -0.01em; margin-top: 6px; line-height: 1.0; 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);
}
/* Flat hover — placards never float. */
a.stat:hover, a.card:hover { border-color: var(--outline); box-shadow: var(--shadow-md); transform: none; }
a.stat:active, a.card:active { transform: none; background: var(--surface-low); }
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 — rounded-12, dark-green primary with a subtle hover lift,
   quiet outlined ghost. */
/* Buttons — "engineered" shape (2026-06-11): a crisp 10px rectangle, not a
   full pill, with a hairline keyline and a confident press. The corner-radius
   system on the page: cards = 24px (soft panels), controls = 10px (engineered
   buttons + inputs), status chips/badges = full pill. */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 11px 19px;
    border-radius: 3px;
    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(--ink-pill);
    color: #FBF8EE;
    /* A 1px gold top keyline gives the primary an engineered, machined edge. */
    box-shadow: inset 0 1px 0 rgba(232, 185, 35, 0.30);
}
/* Subtle hover lift + press scale — calm, never bouncy. */
.btn-primary:hover {
    background: var(--primary-hover);
    color: #fff;
    transform: translateY(-1px);
    box-shadow: inset 0 1px 0 rgba(232, 185, 35, 0.40), 0 8px 20px -6px rgba(13, 40, 24, 0.32);
}
.btn-primary:active { transform: translateY(0) scale(0.985); }
.btn-secondary {
    background: var(--secondary);
    color: #fff;
}
.btn-secondary:hover { background: var(--secondary-hover); color: #fff; }
.btn-secondary:active { transform: scale(0.98); }
/* Gold accent button — the reference's yellow CTA. Dark ink text on gold. */
.btn-gold {
    background: var(--grad-gold);
    color: #2A2410;
}
.btn-gold:hover {
    color: #221E0C;
    transform: translateY(-1px);
    box-shadow: 0 8px 20px -6px rgba(216, 168, 19, 0.45);
}
.btn-gold:active { transform: scale(0.98); }
.btn-ghost {
    background: var(--surface);
    color: var(--muted-strong);
    border-color: var(--border);
}
.btn-ghost:hover { background: var(--surface-low); color: var(--primary); border-color: var(--border-strong); }
.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 { padding: 7px 14px; font-size: 13px; }
.btn-block { width: 100%; justify-content: center; }

/* 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 15px;
    border: 1px solid var(--border);
    border-radius: 3px;
    background: #FFF;
    /* 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='%235E6A60' 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, 106, 96,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: 3px;
    background: #FFF;
    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, 106, 96,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(163, 22, 33,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: 4px;
    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: 3px;
    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: 3px;
    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(163, 22, 33,0.55);
    background: rgba(163, 22, 33,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(163, 22, 33,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(255,255,255,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: 4px;
    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 — soft status pills: ~12% tinted fill, strong ink, no border.
   The "In progress / Completed" chip language from the reference. */
.badge {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 5px 12px;
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.012em;
    line-height: 1.4;
    white-space: nowrap;
    border: 1px solid transparent;
}
/* Ruled tags (FLIGHT DECK): every badge variant carries its 1px rule so
   status reads as a placard tag, never a floating tint. Status is never
   colour-only — the label is the status. */
.badge-success { background: rgba(63, 122, 62, 0.14); color: #2F6A2E; border-color: rgba(63, 122, 62, 0.36); }
.badge-warn    { background: rgba(216, 181, 109, 0.20); color: #6B4E17; border-color: rgba(138, 100, 20, 0.38); }
.badge-danger  { background: rgba(163, 22, 33, 0.12); color: #8C1220; border-color: rgba(163, 22, 33, 0.32); }
.badge-info    { background: rgba(45, 106, 79, 0.14); color: #1D5233; border-color: rgba(45, 106, 79, 0.32); }
.badge-neutral { background: rgba(94, 106, 96, 0.12); color: var(--muted-strong); border-color: rgba(94, 106, 96, 0.32); }
/* Gold tag — active/highlight states. */
.badge-gold    { background: var(--accent-gold-soft); color: #6B5208; border-color: var(--accent-gold-line); }
/* Legacy "blue" informational tag — renders on-brand green (blue purge). */
.badge-blue    { background: var(--accent-blue-soft); color: var(--accent-blue); border-color: rgba(45, 106, 79, 0.32); }

/* ---------------------------------------------------------------
   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: 4px;
    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(45, 106, 79, 0.14);
    color: #1D5233;
    border-color: rgba(45, 106, 79, 0.22);
}
.jags-title-badge-admin {
    background: rgba(163, 22, 33, 0.10);
    color: #8C1220;
    border-color: rgba(163, 22, 33, 0.28);
}
.jags-title-badge-senior {
    background: rgba(182, 136, 58, 0.13);
    color: #7C5A1F;
    border-color: rgba(182, 136, 58, 0.32);
}
.jags-title-badge-safety {
    background: rgba(216, 181, 109, 0.18);
    color: #7C5A1F;
    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 GDF 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: 4px;
    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: 4px;
    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: #fff;
    box-shadow: var(--shadow-sm);
    scrollbar-width: thin;
    scrollbar-color: rgba(29, 82, 51,0.30) transparent;
}
.table-wrap::-webkit-scrollbar { height: 8px; }
.table-wrap::-webkit-scrollbar-track { background: transparent; }
.table-wrap::-webkit-scrollbar-thumb { background: rgba(29, 82, 51,0.25); border-radius: 8px; }
.table-wrap::-webkit-scrollbar-thumb:hover { background: rgba(29, 82, 51,0.45); }

table.tbl { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
table.tbl th, table.tbl td {
    padding: 13px 16px;
    text-align: left;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
    line-height: 1.42;
}
table.tbl th {
    background: var(--surface-low);
    font-weight: 700;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    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(--accent-gold-soft); }

/* 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; }

/* Legacy per-page aliases (2026-07-02 mobile pass): several pages emit
   class="table" / class="data-table" / class="input", which had NO
   definition anywhere — tables rendered as unpadded UA defaults and
   .input fields as tiny browser-default controls. Alias them to the
   shell primitives so every caller inherits the placard table + 16px/44px
   field treatment without touching each page. */
table.table, table.data-table { width: 100%; border-collapse: collapse; font-size: 14px; background: var(--card); }
table.table th, table.table td,
table.data-table th, table.data-table td {
    padding: 10px 12px;
    text-align: left;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
    line-height: 1.42;
}
table.table th, table.data-table th {
    background: var(--surface-low);
    font-weight: 700;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--muted-strong);
}
table.table tr:last-child td, table.data-table tr:last-child td { border-bottom: none; }
input.input, select.input, textarea.input {
    width: 100%;
    padding: 10px 12px;
    font-size: 16px;
    min-height: 44px;
    font-family: inherit;
    color: var(--text);
    background: #FFFFFF;
    border: 1px solid var(--border-strong);
    border-radius: 4px;
}
input.input:focus-visible, select.input:focus-visible, textarea.input:focus-visible {
    outline: none;
    box-shadow: var(--ring-focus);
}
/* Bare wide tables cannot scroll on phones (.main > .content clips
   horizontal overflow at <=900px) — pages SHOULD wrap them in
   .table-wrap, but for the ones that don't, let the table itself become
   the scroll container so no data is ever unreachable. Tables that fit
   keep their natural full width via width:100%. */
@media (max-width: 900px) {
    table.table, table.data-table {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    .table-wrap table.table, .table-wrap table.data-table { display: table; overflow-x: visible; }
}

/* 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: #fff; 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: 3px; background: #fff; 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: #F9FBF6; 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;
}
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, #EFF3EC 0%, #E5EBE0 100%);
    text-transform: uppercase;
    font-size: 11px;
    letter-spacing: 0.04em;
    color: #2A4034;
    text-align: center;
}
table.dr tbody td.reg-cell {
    background: #F7FAF4;
    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: rgba(244, 247, 240, 0.6); }
.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(45, 106, 79,0.16) !important; color: #173F29; 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: #5C3F0E; font-weight: 600; }
.cell-outstanding{ background: rgba(163, 22, 33,0.13) !important; color: #8C1220; 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(163, 22, 33,0.20) !important; color: #8C1220; 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: #8C1220; }
.dr-kw-warn     { color: #5C3F0E; }
.dr-kw-info     { color: #173F29; }

/* Legend / key */
.legend { display: flex; flex-wrap: wrap; gap: 10px; padding: 12px 24px; background: #FAFBF6; border-top: 1px solid var(--border); }
.legend .swatch { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; border-radius: 4px; 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: rgba(244, 247, 240, 0.6);
    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;
    min-height: 100dvh;
    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: 4px; background: #fff; 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: 4px;
    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(29, 82, 51, 0.10);
    border: 1px solid rgba(29, 82, 51, 0.18);
    padding: 4px 10px;
    border-radius: 4px;
    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
   GDF AirCore 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 the crest asset 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: 4px;
    background: #ffffff;
    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: "GDF";
    display: block;
    font-size: 30px;
    font-weight: 800;
    letter-spacing: 0.04em;
    color: var(--primary);
}
.auth-side .brand-fallback::after {
    content: "AIRCORE";
    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: 4px;
    border: 1px solid var(--border);
    background: #fff;
    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: #fff;
    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.
   All sit inside the GDF green family (with quiet olive / sage / gray-green
   shifts) so departments stay distinguishable without leaving the brand. */
.auth-page.auth-portal-tr          .auth-side { background: linear-gradient(135deg, #0D2818 0%, #173F29 55%, #2D6A4F 100%); }
.auth-page.auth-portal-operations  .auth-side { background: linear-gradient(135deg, #122A1C 0%, #1D5233 60%, #35704C 100%); }
.auth-page.auth-portal-radio       .auth-side { background: linear-gradient(135deg, #14241B 0%, #2E4A38 60%, #57755F 100%); }
.auth-page.auth-portal-maintenance .auth-side { background: linear-gradient(135deg, #16302A 0%, #2A5D4E 60%, #4F8A76 100%); }
.auth-page.auth-portal-pilot       .auth-side { background: linear-gradient(135deg, #0D2818 0%, #1A4A2E 55%, #2F6B45 100%); }
.auth-page.auth-portal-viewer      .auth-side { background: linear-gradient(135deg, #1B211C 0%, #3A4A3E 60%, #6E7F70 100%); }
.auth-page.auth-portal-admin       .auth-side { background: linear-gradient(135deg, #0D2818 0%, #1D402C 60%, #6B6F3A 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(45, 106, 79,0.10); color: #1D5233; border-color: rgba(45, 106, 79,0.22); }
.alert-success { background: rgba(74,103,51,0.10);  color: #3B5326; border-color: rgba(74,103,51,0.22); }
.alert-warn    { background: rgba(216,181,109,0.16); color: #7C5A1F; border-color: rgba(216,181,109,0.32); }
.alert-danger  { background: rgba(163, 22, 33,0.10);  color: #8C1220; border-color: rgba(163, 22, 33,0.22); }

/* Aircraft status card */
.ac-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; }
.ac-card {
    background: #fff; 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: 3px;
    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(11, 26, 17, 0.55) 0%,
            rgba(5, 14, 9, 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(13, 40, 24, 0.18), 0 1px 2px rgba(13, 40, 24, 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: 3px;
    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: #ffffff;
    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, #FAFBF6 0%, #EEF1E9 100%);
    color: var(--muted);
}
.av2-hero-image .av2-hero-image-fallback svg {
    width: 56px; height: 56px;
    color: rgba(29, 82, 51,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: 4px;
    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: #fff;
    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: 3px;
    background: linear-gradient(180deg, rgba(29, 82, 51,0.10), rgba(29, 82, 51,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: #7C5A1F; }
.av2-feature.warn             { background: rgba(216,181,109,0.10); }
.av2-feature.danger .feat-val { color: #8C1220; }
.av2-feature.danger           { background: rgba(163, 22, 33,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: 4px;
    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: #3B5326; }
.av2-countdown.info    { background: rgba(45, 106, 79,0.14); color: #1D5233; }
.av2-countdown.warn    { background: rgba(216,181,109,0.18); color: #7C5A1F; }
.av2-countdown.danger  { background: rgba(163, 22, 33,0.14); color: #8C1220; }
.av2-countdown.muted   { background: rgba(94, 106, 96,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, #F7FAF4 0%, #EFF3EC 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: #fff;
    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: #F7FAF4;
    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: #fff; 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, #FAFBF6, #F3F6EF);
    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: 4px; overflow: hidden; background: #fff; }
.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: #EFF3EC; color: #1D5233;
    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: #fff;
    transition: background var(--motion-fast) var(--ease-out);
}
table.ops-board tbody tr:hover { background: #F9FAF6; }
table.ops-board tbody tr.ops-row-priority {
    background: linear-gradient(90deg, rgba(163, 22, 33,0.05) 0%, rgba(163, 22, 33,0.02) 30%, #fff 65%);
}
table.ops-board tbody tr.ops-row-priority td:first-child {
    box-shadow: inset 4px 0 0 0 #A31621;
}
table.ops-board tbody tr.ops-row-vip td:first-child   { box-shadow: inset 4px 0 0 0 #A31621; }
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 #2D6A4F; }

/* 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: #5E6A60;
    background: repeating-linear-gradient(0deg, transparent 0, transparent 22px, rgba(94, 106, 96,0.05) 22px, rgba(94, 106, 96,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: #5E6A60;
}

/* 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(163, 22, 33,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: #1D5233; }

/* 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: #FAFBF6; 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: #A31621; 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: #EFF3EC; 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(163, 22, 33,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: #fff;
}
.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: #fff;
    font-family: "SF Mono", ui-monospace, Menlo, Consolas, monospace; font-size: 12px; color: #1D5233;
}
.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: #E5EBE0 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    table.ops-board tbody tr.ops-row-priority { background: rgba(163, 22, 33,0.06) !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* Print */
@media print {
    body { background: #fff; font-size: 10pt; }
    .sidebar, .topbar, .dr-toolbar, .no-print { display: none !important; }
    .app-shell { grid-template-columns: 1fr; }
    .content { padding: 0; }
    .dr-wrap { box-shadow: none; border: none; border-radius: 0; }
    .dr-header { background: #173F29 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    table.dr { font-size: 9pt; min-width: 0; }
    table.dr th { background: #E5EBE0 !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: #8C1220 !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: #173F29 !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 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 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: 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: block; }
    .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: 4px; }
    .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(201, 162, 39, 0.50), var(--shadow-sm);
}
.btn-primary:focus-visible {
    box-shadow: 0 0 0 3px rgba(201, 162, 39, 0.50), var(--shadow-md);
}
.btn-danger:focus-visible {
    box-shadow: 0 0 0 3px rgba(163, 22, 33, 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
   GDF 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(201, 162, 39, 0.55) 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(201, 162, 39, 0.50);
}

/* 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(29, 82, 51, 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(29, 82, 51, 0.22);
}
a.card-glass:focus-visible, button.card-glass:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(201, 162, 39, 0.50), 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(29, 82, 51, 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(201, 162, 39, 0.65);
    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;
    height: 38px;
    padding: 0 12px;
    border-radius: var(--radius-lg);
    border: 1px solid var(--border-strong);
    background: var(--surface-low);
    color: var(--secondary);
    font-family: var(--font-display);
    font-weight: 600; font-size: 12px;
    letter-spacing: 0.08em; text-transform: uppercase;
    cursor: pointer;
    transition: background 160ms var(--ease-out), border-color 160ms var(--ease-out);
}
#jags-tour-launcher:hover {
    border-color: var(--outline);
    background: var(--surface-container);
}
#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(13, 40, 24,0.42) 0%, rgba(13, 40, 24,0.62) 60%, rgba(13, 40, 24,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(255,255,255,0.94) 0%, rgba(247, 250, 244,0.92) 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: 4px;
    box-shadow:
      0 1px 0 rgba(255,255,255,0.9) inset,
      0 0 0 1px rgba(29, 82, 51,0.06),
      0 28px 60px -12px rgba(13, 40, 24,0.34),
      0 8px 18px -8px rgba(13, 40, 24,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, 63, 41,0)   0%,
        rgba(23, 63, 41,0.55) 18%,
        rgba(201,162,39,0.95) 50%,
        rgba(23, 63, 41,0.55) 82%,
        rgba(23, 63, 41,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(29, 82, 51,0.06);
    border: 1px solid rgba(29, 82, 51,0.10);
    color: var(--secondary);
    padding: 3px 9px 3px 8px; border-radius: 4px;
    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: 4px;
    background: var(--info);
    box-shadow: 0 0 0 3px rgba(45, 106, 79,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: 4px;
    transition: background 140ms var(--ease-out), color 140ms var(--ease-out);
}
.jags-tour-head .close-btn:hover { background: rgba(94, 106, 96,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(29, 82, 51,0.08); margin: 0 20px;
    border-radius: 4px; 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: 4px;
    background: rgba(29, 82, 51,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(29, 82, 51,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: 3px;
}
.jags-tour-actions .btn-primary {
    box-shadow: 0 4px 14px rgba(23, 63, 41,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: 3px;
    box-shadow:
      0 0 0 3px rgba(255,255,255,0.96),
      0 0 0 5px rgba(201,162,39,0.70),
      0 0 0 9px rgba(201,162,39,0.20),
      0 18px 40px -8px rgba(13, 40, 24,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(201,162,39,0.60),
          0 0 0 9px rgba(201,162,39,0.16),
          0 18px 40px -8px rgba(13, 40, 24,0.26);
    }
    50% {
        box-shadow:
          0 0 0 3px rgba(255,255,255,0.96),
          0 0 0 5px rgba(201,162,39,0.90),
          0 0 0 12px rgba(201,162,39,0.25),
          0 18px 44px -8px rgba(13, 40, 24,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(13, 40, 24, 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(201, 162, 39, 0.40);
}

/* Hairline divider on the topbar so it floats over scrolled content
   instead of sitting on a hard line. */
.topbar { box-shadow: none; }

/* Ruled-tag geometry — enough padding for the 1px rule to breathe. */
.badge { padding: 3px 9px; font-weight: 600; }

/* (2026-07-02) The .stat radial "glow corner" is fully retired — the
   FLIGHT DECK tile is flat and no ::after content exists any more, so
   the old highlight rule is gone (it was the "ghost icon" suspect on
   the approval-inbox stat tiles). */

/* (2026-07-02) Section titles are the placard header system defined
   above — this legacy polish override is retired so the condensed
   uppercase voice wins everywhere. */

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

/* Empty-state copy — a tiny, consistent treatment for every card
   that says "nothing here yet." Pages can opt in with the class. */
.empty-state {
    color: var(--muted);
    font-size: var(--text-sm);
    padding: 4px 0 2px;
}

/* 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 green hover. */
table.tbl tbody tr:nth-child(even) td { background: #FAFBF6; }
table.tbl tbody tr:hover td { background: rgba(45, 106, 79, 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(45, 106, 79,0.08);
    border: 1px solid var(--border);
    border-radius: 3px;
    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(45, 106, 79,0.18); }
.mobile-nav-toggle:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(201, 162, 39, 0.50);
}
.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(13, 40, 24,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. FLIGHT DECK: the
   drawer is now the full-screen COMMAND SHEET sliding up from the
   bottom (not in from the left). Same open/close mechanics, ids and
   body classes — only geometry and travel direction changed. */
@media (max-width: 900px) {
    .sidebar {
        position: fixed;
        top: 0; left: 0; right: 0;
        width: 100vw;
        height: 100vh;
        height: 100dvh;
        max-height: 100vh;
        max-height: 100dvh;
        z-index: 9100;
        background: var(--sidebar-bg);
        border-top: 3px solid var(--accent-gold);
        border-right: none;
        border-bottom: none;
        padding: 18px 16px calc(20px + var(--safe-area-bottom));
        transform: translateY(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: translateY(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: 70px; }
    .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: block; }
    .sidebar-account {
        position: sticky;
        bottom: 0;
        background: rgba(10, 32, 20, 0.96);
        -webkit-backdrop-filter: blur(8px);
        backdrop-filter: blur(8px);
        margin: 12px -4px -4px;
        padding: 12px;
        z-index: 1;
    }
}

/* Mobile floating command dock — a role-aware capsule rail (icon-only inactive
   destinations, an active destination that expands into a gold inner capsule)
   plus a detached circular primary-action button. FLIGHT DECK identity: deep
   green rail, restrained gold active chip, soft deliberate shadow. Desktop
   (>900px) never sees it. The outer element keeps the .mobile-bottom-nav class
   so the print / display-shell kill rules and tap-feedback selectors still
   match. */
.mobile-bottom-nav { display: none; }
@media (max-width: 900px) {
    /* Container: floating, centred, capsule rail + detached FAB. */
    .mobile-dock {
        position: fixed;
        left: 11px; right: 11px;
        bottom: calc(10px + var(--safe-area-bottom));
        margin-inline: auto;
        max-width: 420px;
        z-index: 8000;
        display: flex;
        align-items: center;
        gap: 8px;
    }
    .mobile-dock__rail {
        flex: 1;
        min-width: 0;
        height: 60px;
        display: flex;
        align-items: center;
        gap: 3px;
        padding: 5px;
        border-radius: var(--dock-radius);
        background: linear-gradient(180deg, #143521, #0E2718);
        border: 1px solid var(--sidebar-border);
        box-shadow: var(--dock-shadow);
    }
    /* Every rail cell — inactive is a 44px icon-only tile (44 = a11y floor). */
    .mobile-dock__item {
        position: relative;
        flex: 0 0 44px;
        height: 48px;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 8px;
        padding: 0;
        border: none;
        background: transparent;
        color: var(--sidebar-muted);
        text-decoration: none;
        cursor: pointer;
        border-radius: var(--dock-item-radius);
        font-family: var(--font-display);
        transition:
            background var(--motion-med) var(--ease-premium),
            color var(--motion-med) var(--ease-premium),
            flex-basis var(--motion-med) var(--ease-premium),
            padding var(--motion-med) var(--ease-premium);
    }
    .mobile-dock__item .jags-icon { width: 22px; height: 22px; display: block; flex: 0 0 auto; }
    /* Label: hidden for inactive (present for screen readers via the grid
       collapse), animates open only on the active destination. */
    .mobile-dock__label-wrap {
        display: grid;
        grid-template-columns: 0fr;
        transition: grid-template-columns var(--motion-med) var(--ease-premium);
    }
    .mobile-dock__label-wrap .label {
        overflow: hidden;
        min-width: 0;
        white-space: nowrap;
        text-overflow: ellipsis; /* safety net only — geometry fits all role labels */
        font-size: 12px;
        font-weight: 700;
        letter-spacing: var(--tracking-wide);
        text-transform: uppercase;
    }
    /* Active destination — grows into its own gold inner capsule. */
    .mobile-dock__item.active {
        flex: 0 1 auto;
        padding: 0 16px 0 13px;
        background: var(--accent-gold);
        color: var(--sidebar-bg);
    }
    .mobile-dock__item.active .mobile-dock__label-wrap { grid-template-columns: 1fr; }
    /* Filled active glyph flips its gold spark to the rail base (never
       gold-on-gold). Mirrors the sidebar-active rule at .ic-spark above. */
    .mobile-dock__item.active .ic-spark { fill: var(--sidebar-bg); }
    /* Press + focus feedback (scoped high enough to beat legacy :active bg). */
    .mobile-dock .mobile-dock__item:active { background: var(--sidebar-hover-bg); transform: scale(.96); }
    .mobile-dock .mobile-dock__item.active:active { background: var(--accent-gold-strong); }
    .mobile-dock__item:focus-visible { outline: none; box-shadow: var(--ring-focus); }
    /* Detached circular primary action (+). Same component family as the rail. */
    .mobile-dock__fab {
        flex: 0 0 58px;
        width: 58px; height: 58px;
        display: flex;
        align-items: center;
        justify-content: center;
        border: 1px solid var(--sidebar-border);
        border-radius: 50%;
        background: linear-gradient(180deg, #143521, #0E2718);
        box-shadow: var(--dock-shadow), 0 2px 8px rgba(232, 185, 35, .35);
        color: var(--accent-gold);
        cursor: pointer;
        transition: transform var(--motion-fast) var(--ease-premium);
    }
    .mobile-dock__fab .jags-icon { width: 24px; height: 24px; display: block; }
    .mobile-dock .mobile-dock__fab:active { transform: scale(.94); background: linear-gradient(180deg, #143521, #0E2718); }
    .mobile-dock__fab:focus-visible { outline: none; box-shadow: var(--ring-focus); }
    /* Reserve space below content so the floating dock never covers actions. */
    .main > .content { padding-bottom: var(--mobile-bottom-nav-clearance); }
    @media (prefers-reduced-motion: reduce) {
        .mobile-dock__item,
        .mobile-dock__label-wrap,
        .mobile-dock__fab { transition: none !important; }
        .mobile-dock .mobile-dock__item:active,
        .mobile-dock .mobile-dock__fab:active { transform: none; }
    }
}

/* 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: 3px; }
    .stat .value { font-size: 21px; }
    .stat .label { font-size: 10.5px; }
    .stat .delta { font-size: 11px; }
    .card { padding: 14px; border-radius: 3px; }
    .card + .card { margin-top: 14px; }
    .card-hero { padding: 18px 16px 20px; border-radius: 4px; }
    .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(45, 106, 79,0.08);
        border: 1px solid rgba(45, 106, 79,0.20);
        border-radius: 3px;
        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(255,255,255,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: #fff;
        border: 1px solid var(--border);
        border-radius: 3px;
        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: 4px;
    }
    .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, 63, 41,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, 63, 41, 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: #fff;
    border: 1px solid rgba(23, 63, 41, 0.14);
    border-radius: 4px;
    box-shadow: 0 12px 32px rgba(6, 18, 11, 0.18);
    padding: 10px 12px;
}
.jags-pwa-auth-banner__icon {
    flex: 0 0 auto;
    width: 38px; height: 38px;
    border-radius: 3px;
    background: var(--primary, #173F29);
    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, #173F29);
    line-height: 1.25;
}
.jags-pwa-auth-banner__sub {
    display: block;
    font-size: 12px; color: #5E6A60; line-height: 1.3; margin-top: 1px;
}
.jags-pwa-auth-banner__btn {
    flex: 0 0 auto;
    border: 0;
    border-radius: 4px;
    background: var(--primary, #173F29);
    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(201, 162, 39, 0.45);
}
.jags-pwa-auth-banner__dismiss {
    flex: 0 0 auto;
    border: 0; background: none;
    color: #8A998C;
    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, 63, 41, 0.18);
    border-radius: 4px;
    background: rgba(23, 63, 41, 0.04);
    color: var(--primary, #173F29);
    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, 63, 41, 0.10);
    border-color: rgba(23, 63, 41, 0.32);
    transform: translateY(-1px);
    box-shadow: 0 2px 6px rgba(23, 63, 41, 0.12);
}
.jags-pwa-install-pill:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(201, 162, 39, 0.45);
}
.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, 63, 41, 0.06), rgba(23, 63, 41, 0.02));
    border: 1px solid rgba(23, 63, 41, 0.14);
    border-radius: 3px;
    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, #173F29);
    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, #0E1410);
    line-height: 1.2;
}
.jags-pwa-install-card__sub {
    font-size: 11.5px; color: var(--muted, #6B7A6C);
    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, #173F29);
    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: #0D2818; transform: translateY(-1px); }
.jags-pwa-install-card__btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(201, 162, 39, 0.45);
}
/* Dark command-rail context (2026-06-11) — the install card lives inside the
   deep-green .sidebar. It reads as a defined console card: faint white-wash
   surface, a gold "download" glyph chip, cream copy, and a single warm GOLD
   Install button (the one warm CTA in the rail, intentional). Scoped to
   .sidebar so the card stays light if ever reused on a light surface. The
   install PILL (.jags-pwa-install-pill) in the light topbar is untouched. */
.sidebar .jags-pwa-install-card {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--sidebar-border);
    border-radius: 3px;
    color: var(--sidebar-text);
    margin: 12px 6px 4px;
}
.sidebar .jags-pwa-install-card__icon {
    background: rgba(232, 185, 35, 0.16);
    color: #F0C84A;
    border-radius: 3px;
}
.sidebar .jags-pwa-install-card__title { color: #F2F6F0; }
.sidebar .jags-pwa-install-card__sub { color: var(--sidebar-muted); }
.sidebar .jags-pwa-install-card__btn {
    background: var(--accent-gold, #E8B923);
    color: #2A2410;
    border-radius: 3px;
    font-weight: 700;
}
.sidebar .jags-pwa-install-card__btn:hover { background: #F1C846; transform: translateY(-1px); }

/* 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(6, 18, 11, 0.55);
    backdrop-filter: blur(2px);
}
.jags-pwa-modal-dialog {
    position: relative;
    max-width: 380px; width: 100%;
    background: #fff;
    border-radius: 4px;
    box-shadow: 0 24px 60px rgba(6, 18, 11, 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: 3px;
    background: var(--primary, #173F29);
    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, #0E1410);
    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, 63, 41, 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, 63, 41, 0.08);
    color: var(--primary, #173F29);
    display: inline-flex; align-items: center; justify-content: center;
}
.jags-pwa-modal-dialog__hint {
    font-size: 11.5px; color: var(--muted, #6B7A6C);
    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, #173F29);
    color: #fff;
    font-size: 13px; font-weight: 600;
    cursor: pointer;
}
.jags-pwa-modal-dialog__close:hover { background: #0D2818; }
.jags-pwa-modal-dialog__close:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(201, 162, 39, 0.45);
}
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(163, 22, 33,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, #1D5233); }

/* =====================================================================
   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, 106, 96, 0.10);
    color: var(--muted-strong);
}
.rsv-srt-medevac    { background: rgba(163, 22, 33,0.10); color: #8C1220; border-color: rgba(163, 22, 33,0.30); }
.rsv-srt-vip        { background: rgba(216,181,109,0.18); color: #7A5A1A; border-color: rgba(216,181,109,0.42); }
.rsv-srt-government { background: rgba(45, 106, 79,0.14); color: #1D5233; border-color: rgba(45, 106, 79,0.35); }
.rsv-srt-cargo      { background: rgba(74,103,51,0.12); color: #3B5326; border-color: rgba(74,103,51,0.35); }
.rsv-srt-default    { background: rgba(94, 106, 96,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, 106, 96, 0.10);
    color: var(--muted-strong);
}
.rsv-status-default            { background: rgba(94, 106, 96,0.10); color: var(--muted-strong); }
.rsv-status-draft              { background: rgba(94, 106, 96,0.10); color: var(--muted-strong); }
.rsv-status-pending-review     { background: rgba(45, 106, 79,0.14); color: #1D5233; border-color: rgba(45, 106, 79,0.30); }
.rsv-status-customer-confirmed { background: rgba(74,103,51,0.12);  color: #3B5326; border-color: rgba(74,103,51,0.30); }
.rsv-status-sent-to-operations { background: rgba(58, 84, 71,0.14);  color: #2A4034; border-color: rgba(58, 84, 71,0.32); }
.rsv-status-returned           { background: rgba(216,181,109,0.18);color: #7A5A1A; 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: #7A5A1A; border-color: rgba(216,181,109,0.42); }
.rsv-status-cancelled          { background: rgba(163, 22, 33,0.10);  color: var(--danger); border-color: rgba(163, 22, 33,0.30); }
.rsv-status-completed          { background: rgba(94, 106, 96,0.14); color: #46544A; border-color: rgba(94, 106, 96,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: #7A5A1A;
    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(58, 84, 71,0.32);
    background: rgba(58, 84, 71,0.10);
    color: #2A4034;
}
.rsv-acft-type-pill-backup {
    background: rgba(94, 106, 96,0.10);
    color: var(--muted-strong);
    border-color: rgba(94, 106, 96,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(246, 248, 241, 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: #7A5A1A;
}

/* 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: #FFFFFF;
}
.rsv-acft-card-available    { border-left: 4px solid var(--success, #4A7B33); }
.rsv-acft-card-unavailable  {
    border-left: 4px solid rgba(163, 22, 33,0.55);
    /* Subtle dim — never paint the whole card. */
    opacity: 0.78;
    background: rgba(246, 248, 241, 0.85);
}
.rsv-acft-thumb {
    flex: 0 0 56px;
    width: 56px;
    height: 56px;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(94, 106, 96,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, 106, 96,0.10);
    color: var(--muted-strong);
}
.rsv-acft-status-serviceable        { background: rgba(74,103,51,0.12);  color: #3B5326; border-color: rgba(74,103,51,0.30); }
.rsv-acft-status-grounded           { background: rgba(163, 22, 33,0.10);  color: var(--danger); border-color: rgba(163, 22, 33,0.30); }
.rsv-acft-status-maintenance        { background: rgba(216,181,109,0.18);color: #7A5A1A; border-color: rgba(216,181,109,0.42); }
.rsv-acft-status-inspection_required{ background: rgba(216,181,109,0.18);color: #7A5A1A; border-color: rgba(216,181,109,0.42); }
.rsv-acft-status-inactive           { background: rgba(94, 106, 96,0.14); color: #46544A; border-color: rgba(94, 106, 96,0.30); }
.rsv-acft-unavail-pill {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 5px;
    font-size: 11px;
    font-weight: 600;
    background: rgba(163, 22, 33,0.10);
    color: var(--danger);
    border: 1px solid rgba(163, 22, 33,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(246, 248, 241,0.6); }
.rsv-chip {
    display: inline-block;
    padding: 5px 12px;
    border-radius: 4px;
    border: 1px solid rgba(0,0,0,0.12);
    background: #FFFFFF;
    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); }
@media (max-width: 900px) {
    .rsv-chip { min-height: 44px; display: inline-flex; align-items: center; }
}
.rsv-chip-active {
    background: var(--primary, #173F29);
    color: #FFFFFF;
    border-color: var(--primary, #173F29);
}
.rsv-chip-active:hover { background: var(--primary, #173F29); 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(23, 63, 41,0.10);
    color: var(--primary, #173F29);
    border: 1px solid rgba(23, 63, 41,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: #3B5326;       border-color: rgba(74,103,51,0.30); }
.rsv-delay-delayed   { background: rgba(163, 22, 33,0.10);   color: var(--danger); border-color: rgba(163, 22, 33,0.30); }
.rsv-delay-awaiting  { background: rgba(216,181,109,0.18); color: #7A5A1A;       border-color: rgba(216,181,109,0.42); }
.rsv-delay-weather   { background: rgba(94, 106, 96,0.12);  color: #46544A;       border-color: rgba(94, 106, 96,0.30); }
.rsv-delay-cancelled { background: rgba(163, 22, 33,0.10);   color: var(--danger); border-color: rgba(163, 22, 33,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: #FFFFFF;
    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: #3B5326;       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: #7A5A1A;       border-color: rgba(216,181,109,0.45); }
.rsv-chip-hold:hover   { background: rgba(216,181,109,0.30); }
.rsv-chip-block  { background: rgba(163, 22, 33,0.10);   color: var(--danger); border-color: rgba(163, 22, 33,0.32); }
.rsv-chip-block:hover  { background: rgba(163, 22, 33,0.18); }
.rsv-chip-review { background: rgba(23, 63, 41,0.10);   color: var(--primary, #173F29); border-color: rgba(23, 63, 41,0.30); }
.rsv-chip-review:hover { background: rgba(23, 63, 41,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: 4px;
    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(163, 22, 33,0.10);   color: var(--danger);            border-color: rgba(163, 22, 33,0.30); }
.rsv-pay-paid     { background: rgba(74,103,51,0.10);   color: #3B5326;                  border-color: rgba(74,103,51,0.32); }
.rsv-pay-company  { background: rgba(23, 63, 41,0.10);   color: var(--primary, #173F29);  border-color: rgba(23, 63, 41,0.30); }
.rsv-pay-waived   { background: rgba(94, 106, 96,0.12);  color: #46544A;                  border-color: rgba(94, 106, 96,0.30); }
.rsv-pay-refunded { background: rgba(216,181,109,0.18); color: #7A5A1A;                  border-color: rgba(216,181,109,0.42); }

.rsv-capacity-card { border-left: 4px solid var(--primary, #173F29); }
.rsv-capacity-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 12px;
    margin-top: 8px;
}
.rsv-capacity-tile {
    background: rgba(23, 63, 41,0.05);
    border: 1px solid rgba(23, 63, 41,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: 4px;
    font-size: 11px; font-weight: 600;
    border: 1px solid transparent;
}
.rsv-capacity-ok       { background: rgba(74,103,51,0.10);   color: #3B5326;       border-color: rgba(74,103,51,0.32); }
.rsv-capacity-over     { background: rgba(163, 22, 33,0.10);   color: var(--danger); border-color: rgba(163, 22, 33,0.30); }
.rsv-capacity-locked   { background: rgba(216,181,109,0.18); color: #7A5A1A;       border-color: rgba(216,181,109,0.42); }
.rsv-capacity-unlocked { background: rgba(94, 106, 96,0.10);  color: #46544A;       border-color: rgba(94, 106, 96,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: 3px;
    padding: 12px 14px;
    margin-bottom: 14px;
    background: #FFFFFF;
}
.rsv-sector-outbound   { border-left: 4px solid var(--primary, #173F29); }
.rsv-sector-return     { border-left: 4px solid #C9A227; }
.rsv-sector-unassigned { border-left: 4px solid rgba(94, 106, 96,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(23, 63, 41,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; }
.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, #173F29);
}
.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(163, 22, 33,0.25); }
.rsv-pax-pay-action summary {
    cursor: pointer; font-size: 12px; font-weight: 600;
    color: var(--primary, #173F29);
}

@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-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, #173F29);
        background: rgba(23, 63, 41,0.08);
        border: 1px solid rgba(23, 63, 41,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, #14241B);
        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, 106, 96,0.10);
    color: var(--muted-strong);
    border: 1px solid rgba(94, 106, 96,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, 106, 96,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(163, 22, 33,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, 106, 96,0.10);
    color: var(--muted-strong);
    white-space: nowrap;
}
.rsv-aa-pill-success {
    background: rgba(74,103,51,0.12);
    color: #3B5326;
    border-color: rgba(74,103,51,0.30);
}
.rsv-aa-pill-muted {
    background: rgba(94, 106, 96,0.10);
    color: var(--muted-strong);
    border-color: rgba(94, 106, 96,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, 106, 96,0.22);
    background: rgba(94, 106, 96,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, 106, 96,0.30);
    background: rgba(94, 106, 96,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, 106, 96, 0.10);
    color: var(--muted-strong);
}
.pay-status-default          { background: rgba(94, 106, 96,0.10); color: var(--muted-strong); }
.pay-status-unpaid           { background: rgba(163, 22, 33,0.08);  color: var(--danger);       border-color: rgba(163, 22, 33,0.30); }
.pay-status-pending          { background: rgba(216,181,109,0.18);color: #7A5A1A;             border-color: rgba(216,181,109,0.42); }
.pay-status-paid             { background: rgba(74,103,51,0.12);  color: #3B5326;             border-color: rgba(74,103,51,0.30); }
.pay-status-account-credit   { background: rgba(58, 84, 71,0.14);  color: #2A4034;             border-color: rgba(58, 84, 71,0.32); }
.pay-status-waived           { background: rgba(94, 106, 96,0.14); color: #46544A;             border-color: rgba(94, 106, 96,0.30); }
.pay-status-refunded         { background: rgba(94, 106, 96,0.10); color: var(--muted-strong); border-color: rgba(94, 106, 96,0.22); }
.pay-status-disputed         { background: rgba(163, 22, 33,0.18);  color: var(--danger);       border-color: rgba(163, 22, 33,0.45); }

/* Accounts role chip — matches the role-badge variant key 'accounts'. */
.badge-role-accounts {
    background: rgba(58, 84, 71,0.10);
    color: #2A4034;
    border: 1px solid rgba(58, 84, 71,0.32);
}

/* Subtle 4px left-border accent on the Payment card (no full-card tint). */
.pay-card { border-left: 4px solid rgba(58, 84, 71,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, 106, 96,0.30);
    background: rgba(94, 106, 96,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: #3B5326; border-color: rgba(74,103,51,0.30); }
.ops-intake-acft-warn-warn  { background: rgba(216,181,109,0.18); color: #7A5A1A; border-color: rgba(216,181,109,0.42); }
.ops-intake-acft-warn-block { background: rgba(163, 22, 33,0.10);   color: var(--danger); border-color: rgba(163, 22, 33,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(58, 84, 71,0.32);
    background: rgba(58, 84, 71,0.10);
    color: #2A4034;
}

/* 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(58, 84, 71,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(58, 84, 71,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(58, 84, 71,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, 106, 96, 0.10);
    color: var(--muted-strong);
}
.cust-acct-status-default     { background: rgba(94, 106, 96,0.10); color: var(--muted-strong); }
.cust-acct-status-normal      { background: rgba(74,103,51,0.12);  color: #3B5326;             border-color: rgba(74,103,51,0.30); }
.cust-acct-status-watch       { background: rgba(45, 106, 79,0.14); color: #1D5233;             border-color: rgba(45, 106, 79,0.32); }
.cust-acct-status-near-limit  { background: rgba(216,181,109,0.18);color: #7A5A1A;             border-color: rgba(216,181,109,0.42); }
.cust-acct-status-on-hold     { background: rgba(163, 22, 33,0.10);  color: var(--danger);       border-color: rgba(163, 22, 33,0.30); }
.cust-acct-status-stop-list   { background: rgba(163, 22, 33,0.16);  color: var(--danger);       border-color: rgba(163, 22, 33,0.45); }
.cust-acct-status-inactive    { background: rgba(94, 106, 96,0.14); color: #46544A;             border-color: rgba(94, 106, 96,0.30); }

/* Credit progress bar */
.cust-acct-progress {
    position: relative;
    height: 8px;
    background: rgba(94, 106, 96, 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: #4A7B33; }
.cust-acct-progress-watch      .cust-acct-progress-bar { background: #2D6A4F; }
.cust-acct-progress-near       .cust-acct-progress-bar { background: #C09A3D; }
.cust-acct-progress-over       .cust-acct-progress-bar { background: var(--danger, #A31621); }
.cust-acct-progress-stop                                { background: rgba(163, 22, 33, 0.16); }
.cust-acct-progress-stop       .cust-acct-progress-bar { background: var(--danger, #A31621); width: 100% !important; }
.cust-acct-progress-inactive                            { background: rgba(94, 106, 96, 0.14); }
.cust-acct-progress-inactive   .cust-acct-progress-bar { background: rgba(94, 106, 96, 0.55); width: 100% !important; }
.cust-acct-progress-empty                               { background: rgba(94, 106, 96, 0.06); }
.cust-acct-progress-empty      .cust-acct-progress-bar { background: rgba(94, 106, 96, 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(246, 248, 241, 0.6);
    border-left: 4px solid rgba(94, 106, 96, 0.40);
}
.cust-acct-warning-block {
    border-left-color: var(--danger, #A31621);
    background: rgba(163, 22, 33, 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(45, 106, 79, 0.55);
    background: rgba(45, 106, 79, 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: 3px;
    background: #FFFFFF;
    border-left: 4px solid var(--danger, #A31621);
}
.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, 106, 96, 0.10);
    color: var(--muted-strong);
}
.cust-acct-decision-approved { background: rgba(74,103,51,0.12); color: #3B5326; border-color: rgba(74,103,51,0.30); }
.cust-acct-decision-rejected { background: rgba(163, 22, 33,0.10); color: var(--danger); border-color: rgba(163, 22, 33,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: 13px; line-height: 1.3; }
}

/* 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: 44px; }
    .btn-icon, button.btn-icon, a.btn-icon { min-width: 44px; min-height: 44px; }
    a.tab, .tabs a { min-height: 44px; display: inline-flex; align-items: center; }
    .topbar-bell { min-width: 44px; min-height: 44px; }
    /* Dense-table micro buttons (.btn-mini) keep their compact face but
       gain a full-size invisible hit area so rows stay tight while the
       thumb still gets a 44px target. */
    .btn-mini { position: relative; }
    .btn-mini::after { content: ""; position: absolute; inset: -12px; }
    /* Bare inline checkbox/radio labels (several forms skip .field-check):
       grow the box itself so the target is usable without reflowing the
       label text around it. */
    input[type=checkbox], input[type=radio] { width: 20px; height: 20px; }
    /* Chrome controls also get the floor by WIDTH, not just pointer:coarse
       (644) — desktop-emulated small windows and hybrid devices included. */
    .mobile-nav-toggle, #jags-tour-launcher, .topbar-refresh,
    .fd-sheet-close, a.jags-system-run-pill, #jags-push-checkbtn,
    .toast-close, .jags-toast-close {
        min-width: 44px; min-height: 44px;
    }
    /* Leaflet map zoom controls (route feasibility / map planning) render
       30px by default — Apple HIG floor for the only precision controls
       that sit over a pannable map. */
    .leaflet-control-zoom a {
        width: 44px !important;
        height: 44px !important;
        line-height: 44px !important;
    }
}

/* 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: 3px; }
    .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(29, 82, 51,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(29, 82, 51,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: 3px; }
}

/* 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(13, 40, 24,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(45, 106, 79,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.
   ==================================================================== */
/* FLIGHT DECK reconciliation (2026-07-02): the safe-area top inset used
   to live on .topbar with a JAGS-era frosted-glass treatment — but since
   the command-bar redesign the FIRST element on every page is the dark
   .fd-bar, so in the installed standalone PWA the iPhone status bar /
   Dynamic Island overlapped the dark bar while the paper topbar below it
   grew a spurious gap. The inset now extends the dark command bar into
   the notch (native cockpit look); the frost is retired — FLIGHT DECK
   surfaces are flat. Landscape notch insets stay on both bars. */
@media (max-width: 900px) {
    .fd-bar {
        height: auto;
        min-height: var(--fd-bar-h);
        padding-top: env(safe-area-inset-top);
        padding-left: max(10px, env(safe-area-inset-left));
        padding-right: max(8px, env(safe-area-inset-right));
    }
    .topbar {
        padding-left: max(14px, env(safe-area-inset-left));
        padding-right: max(14px, env(safe-area-inset-right));
    }
}

/* 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(13, 40, 24,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 meta now declares maximum-scale=1, user-scalable=no, but
   WebKit (Safari, iOS WKWebView, the standalone PWA shell) historically
   ignores those flags and still allows a double-tap to zoom unless the
   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.
   touch-action:manipulation on html/body/.app-shell/.main/.content,
   combined with the zoom-locked viewport (maximum-scale=1,
   user-scalable=no), makes iOS WebKit suppress single-finger page
   scrolling: the page then only scrolled while the drawer (its own
   overflow-y:auto fixed container) was open. `pan-y` keeps double-tap
   and pinch zoom suppressed on the shell 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;
}

/* Interactive / tap + chrome surfaces — keep `manipulation` so a stray
   double-tap on a control or nav doesn't zoom the page.

   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. The viewport is already pinned
   (user-scalable=no) so dropping `manipulation` from these non-interactive
   containers cannot reintroduce zoom; the real tap targets inside them
   (a / button / .btn) stay in this list and keep the double-tap guard.
   Do NOT add the content containers back 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;
}

/* 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;
    }
}

/* iOS auto-zoom floor — several per-page glue styles size their own
   inputs at 11–14px (bulk editors, filter bars, role selects). Any
   focused control below 16px makes iOS Safari zoom the viewport, which
   the zoom-locked meta only partially suppresses. Enforce the 16px
   floor on every text-entry control on phones/tablets; !important is
   deliberate because per-page <style> blocks are emitted after this
   sheet and would otherwise win on order. Checkboxes/radios/ranges are
   excluded (no zoom trigger); display/wallboard shells opt back out
   below. */
@media (max-width: 900px) {
    input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=file]):not([type=color]):not([type=hidden]):not([type=button]):not([type=submit]),
    select,
    textarea {
        font-size: 16px !important;
    }
    .display-shell input,
    .display-shell select,
    .display-shell textarea {
        font-size: inherit !important;
    }
}

/* 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(29, 82, 51,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. */
@media (max-width: 900px) {
    body { overscroll-behavior-y: contain; }
}

/* ====================================================================
   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 green-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(29, 82, 51, 0.22);
    transform: translateY(-1px);
}
a.qa-card:focus-visible, button.qa-card:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(201, 162, 39, 0.50), var(--shadow-sm);
}
.qa-card .qa-icon {
    width: 38px; height: 38px;
    flex: 0 0 38px;
    border-radius: 3px;
    background: linear-gradient(180deg, rgba(29, 82, 51,0.10), rgba(29, 82, 51,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(29, 82, 51,0.16), rgba(29, 82, 51,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(29, 82, 51, 0.32);
    box-shadow: 0 6px 18px rgba(29, 82, 51,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(29, 82, 51,0.10), rgba(29, 82, 51,0.04)); color: var(--secondary); }
.qa-card .qa-pill {
    display: inline-flex; align-items: center;
    margin-top: 8px;
    padding: 2px 8px;
    border-radius: 4px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.012em;
    background: rgba(216,181,109,0.18);
    color: #7C5A1F;
    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(29, 82, 51,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: #4A7B33; }
.mini-bar .mb-fill-warn               { fill: #C09A3D; }
.mini-bar .mb-fill-danger             { fill: var(--danger); }
.mini-bar .mb-fill-muted              { fill: rgba(94, 106, 96,0.55); }

/* Mini donut — segments around a centred total. */
.mini-donut { display: inline-block; }
.mini-donut .md-track    { stroke: rgba(29, 82, 51,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: #4A7B33; }
.mini-donut .md-seg-warn    { stroke: #C09A3D; }
.mini-donut .md-seg-danger  { stroke: var(--danger); }
.mini-donut .md-seg-muted   { stroke: rgba(94, 106, 96,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: #4A7B33; }
.mini-donut-legend .swatch.warn    { background: #C09A3D; }
.mini-donut-legend .swatch.danger  { background: var(--danger); }
.mini-donut-legend .swatch.muted   { background: rgba(94, 106, 96,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(29, 82, 51,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: #4A7B33; }
.mini-progress .mp-fill-warn         { fill: #C09A3D; }
.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: #4A7B33; }
.mini-spark .ms-warn          { stroke: #C09A3D; }
.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: 3px;
    background: linear-gradient(180deg, rgba(29, 82, 51,0.10), rgba(29, 82, 51,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: #3B5326; }
.icon-chip.warn    { background: linear-gradient(180deg, rgba(216,181,109,0.18), rgba(216,181,109,0.06)); color: #7C5A1F; }
.icon-chip.danger  { background: linear-gradient(180deg, rgba(163, 22, 33,0.14), rgba(163, 22, 33,0.04)); color: #8C1220; }
.icon-chip.info    { background: linear-gradient(180deg, rgba(45, 106, 79,0.16), rgba(45, 106, 79,0.05)); color: #1D5233; }

/* 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 GDF green 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(163, 22, 33,0.70),  rgba(163, 22, 33,0.0)); }
.stat-info::before    { background: linear-gradient(90deg, rgba(45, 106, 79,0.70), rgba(45, 106, 79,0.0)); }
/* Calm, GDF-green 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(29, 82, 51,0.55),  rgba(29, 82, 51,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(29, 82, 51,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: #fff;
    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: #F2F4EF;
    color: var(--primary-hover);
    border-color: #F2F4EF;
}

/* ---- 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: 3px;
    background: linear-gradient(180deg, rgba(29, 82, 51,0.08), rgba(29, 82, 51,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='%231D5233' 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: 4px;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.012em;
    line-height: 1.4;
    background: rgba(45, 106, 79,0.10);
    color: var(--secondary);
    border: 1px solid rgba(45, 106, 79,0.22);
    font-variant-numeric: tabular-nums lining-nums;
    white-space: nowrap;
}
.kpi-pill.success { background: rgba(74,103,51,0.12);  color: #3B5326; border-color: rgba(74,103,51,0.32); }
.kpi-pill.warn    { background: rgba(216,181,109,0.18); color: #7C5A1F; border-color: rgba(216,181,109,0.42); }
.kpi-pill.danger  { background: rgba(163, 22, 33,0.12);  color: #8C1220; border-color: rgba(163, 22, 33,0.32); }
.kpi-pill.muted   { background: rgba(94, 106, 96,0.10); color: var(--muted-strong); border-color: rgba(94, 106, 96,0.22); }
.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(29, 82, 51,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(29, 82, 51,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, #F7FAF4 0%, #ECF1E8 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: #fff;
    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='%231D5233' 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(29, 82, 51, 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 GDF green 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(29, 82, 51, 0.20);
    color: var(--text-strong);
}
.display-shell ::selection {
    background: rgba(255, 255, 255, 0.22);
    color: #fff;
}

/* ====================================================================
   GDF demo-data notice — one slim, unobtrusive bar at the top of the
   content column when GDF_BRAND_ENABLED is on. Muted gold border, small
   text, print-hidden (also carries .no-print). No dismiss control by
   design: this is an evaluation build watermark, not a flash message.
   ==================================================================== */
.gdf-demo-notice {
    margin: 0 0 14px;
    padding: 6px 12px;
    border: 1px solid rgba(201, 162, 39, 0.40);
    border-left: 3px solid #C9A227;
    border-radius: var(--radius-sm);
    background: rgba(201, 162, 39, 0.07);
    color: #6B5712;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.4;
}
@media print {
    .gdf-demo-notice { display: none !important; }
}
