/* ============================================================
   FleetForge — Application Design System
   DM Sans (UI) · DM Mono (data) · Alpine.js v3 · Heroicons

   Sections
   ─────────────────────────────────────────────────
   00. Self-hosted Fonts (S-PROD-3)
   01. Reset & Base
   02. CSS Custom Properties (Design Tokens)
   03. Typography
   04. App Layout Shell
   05. Sidebar
   06. Topbar
   07. Page Content & Panels
   08. Buttons
   09. Badges & Status Chips
   10. Forms
   11. Tables
   12. Modals
   13. Toast Notifications
   14. Notification Dropdown
   15. Global Search Modal
   16. Skeleton Loaders
   17. Utilities
   18. Alpine.js Helpers & Transitions
   19. Responsive / Mobile
   ============================================================ */


/* ============================================================
   00. Self-hosted Fonts (S-PROD-3 2026-05-14)

   DM Sans v17 + DM Mono v16 — self-hosted to eliminate external
   CDN calls at runtime (was: <link> to fonts.googleapis.com on
   every page; now zero requests to fonts.googleapis.com or
   fonts.gstatic.com).

   @font-face URLs use paths relative to this file's location
   (public/assets/css/app.css → ../vendor/fonts/...). Browsers
   resolve them automatically; no PHP rendering needed.

   Source CSS captured 2026-05-14 from Google Fonts CSS2 API with
   Safari User-Agent (modern browser → woff2 subset URLs). License:
   SIL OFL 1.1 — self-hosting permitted. See
   public/assets/vendor/fonts/README.md for the full inventory +
   re-fetch procedure.
   ============================================================ */

/* DM Mono — italic 300 — latin-ext */
@font-face {
  font-family: 'DM Mono';
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  src: url('../vendor/fonts/dm-mono/dm-mono-italic-300-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* DM Mono — italic 300 — latin */
@font-face {
  font-family: 'DM Mono';
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  src: url('../vendor/fonts/dm-mono/dm-mono-italic-300-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* DM Mono — normal 300 — latin-ext */
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('../vendor/fonts/dm-mono/dm-mono-normal-300-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* DM Mono — normal 300 — latin */
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('../vendor/fonts/dm-mono/dm-mono-normal-300-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* DM Mono — normal 400 — latin-ext */
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../vendor/fonts/dm-mono/dm-mono-normal-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* DM Mono — normal 400 — latin */
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../vendor/fonts/dm-mono/dm-mono-normal-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* DM Mono — normal 500 — latin-ext */
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../vendor/fonts/dm-mono/dm-mono-normal-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* DM Mono — normal 500 — latin */
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../vendor/fonts/dm-mono/dm-mono-normal-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* DM Sans — italic, variable weight 300-700 — latin-ext */
@font-face {
  font-family: 'DM Sans';
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
  src: url('../vendor/fonts/dm-sans/dm-sans-italic-300-700-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* DM Sans — italic, variable weight 300-700 — latin */
@font-face {
  font-family: 'DM Sans';
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
  src: url('../vendor/fonts/dm-sans/dm-sans-italic-300-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* DM Sans — normal, variable weight 300-700 — latin-ext */
@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('../vendor/fonts/dm-sans/dm-sans-normal-300-700-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* DM Sans — normal, variable weight 300-700 — latin */
@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('../vendor/fonts/dm-sans/dm-sans-normal-300-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


/* ============================================================
   01. Reset & Base
   ============================================================ */

*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    font-size: 16px;
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    tab-size: 4;
}

body {
    font-family: 'DM Sans', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
    font-size: 0.9375rem; /* 15px */
    line-height: 1.6;
    background-color: var(--bg-body);
    color: var(--text-primary);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

img, svg { display: block; max-width: 100%; }

a {
    color: var(--color-primary);
    text-decoration: none;
}
a:hover { text-decoration: underline; }

ul, ol { list-style: none; }

button {
    font-family: inherit;
    cursor: pointer;
    border: none;
    background: none;
}

input, textarea, select, button {
    font-family: inherit;
    font-size: inherit;
}

hr {
    border: none;
    border-top: 1px solid var(--border-color);
    margin: 1.5rem 0;
}


/* ============================================================
   02. CSS Custom Properties (Design Tokens)
   ============================================================ */

:root {
    /* ── Brand Colours ────────────────────────────── */
    --color-primary:         #f97316;   /* orange — fleet/logistics identity */
    --color-primary-hover:   #ea6f00;
    --color-primary-light:   rgba(249, 115, 22, 0.14);
    --color-primary-text:    #fb923c;

    --color-success:         #22c55e;
    --color-success-light:   rgba(34, 197, 94, 0.13);
    --color-success-text:    #4ade80;

    --color-warning:         #eab308;
    --color-warning-light:   rgba(234, 179, 8, 0.13);
    --color-warning-text:    #facc15;

    --color-danger:          #ef4444;
    --color-danger-light:    rgba(239, 68, 68, 0.13);
    --color-danger-text:     #f87171;

    --color-info:            #06b6d4;
    --color-info-light:      rgba(6, 182, 212, 0.12);
    --color-info-text:       #22d3ee;

    /* ── Dark Surfaces (default theme) ──────────── */
    --bg-body:               #0a0b0e;
    --bg-surface:            #111318;
    --bg-surface-2:          #181b23;
    --bg-surface-hover:      #1e2230;

    /* ── Text ────────────────────────────────────── */
    --text-primary:          #f1f5f9;
    --text-secondary:        #94a3b8;
    --text-tertiary:         #64748b;
    --text-on-primary:       #ffffff;
    --text-on-danger:        #ffffff;

    /* ── Borders ─────────────────────────────────── */
    --border-color:          #1d2133;
    --border-color-strong:   #2a3347;
    --border-focus:          #f97316;

    /* ── Sidebar ─────────────────────────────────── */
    --sidebar-width:         240px;
    --sidebar-width-collapsed: 64px;
    --sidebar-bg:            #0d0e12;
    --sidebar-border:        rgba(255, 255, 255, 0.06);
    --sidebar-text:          #6b7280;
    --sidebar-text-hover:    #f9fafb;
    --sidebar-text-active:   #ffffff;
    --sidebar-item-hover-bg: rgba(255, 255, 255, 0.05);
    --sidebar-item-active-bg: rgba(249, 115, 22, 0.15);
    --sidebar-icon-active:   #f97316;
    --sidebar-section-text:  #4b5563;
    --sidebar-brand-text:    #f9fafb;

    /* ── Topbar ──────────────────────────────────── */
    --topbar-height:         60px;
    --topbar-bg:             #111318;
    --topbar-border:         #1d2133;
    --topbar-text:           #f1f5f9;

    /* ── Shadows (deeper on dark bg) ─────────────── */
    --shadow-xs:  0 1px 2px rgba(0, 0, 0, 0.30);
    --shadow-sm:  0 1px 4px rgba(0, 0, 0, 0.40), 0 1px 2px rgba(0, 0, 0, 0.25);
    --shadow-md:  0 4px 12px rgba(0, 0, 0, 0.45), 0 2px 4px rgba(0, 0, 0, 0.25);
    --shadow-lg:  0 10px 24px rgba(0, 0, 0, 0.55), 0 4px 8px rgba(0, 0, 0, 0.30);
    --shadow-xl:  0 20px 40px rgba(0, 0, 0, 0.60), 0 8px 16px rgba(0, 0, 0, 0.35);
    --shadow-glow-primary: 0 0 20px rgba(249, 115, 22, 0.18);

    /* ── Radius ──────────────────────────────────── */
    --radius-sm:   4px;
    --radius-md:   6px;
    --radius-lg:   8px;
    --radius-xl:   12px;
    --radius-full: 9999px;

    /* ── Transitions ─────────────────────────────── */
    --transition-fast:   120ms ease;
    --transition-base:   200ms ease;
    --transition-slow:   280ms ease;

    /* ── Z-index Stack ───────────────────────────── */
    --z-sidebar:   40;
    --z-topbar:    30;
    --z-dropdown:  50;
    --z-modal:     60;
    --z-toast:     70;

    /* ── Form ────────────────────────────────────── */
    /* S-DESIGN-INPUTS (2026-05-03): Apple-aesthetic input tokens.
       Inputs render as borderless tinted-gray pills; on focus the
       background brightens and a 2px brand-orange ring appears.
       Dark mode uses warm-tinted alphas to match the brownish-black
       palette (rgba 140,130,115); light mode uses Apple's cool gray
       (rgba 118,118,128) verbatim. Labels use --label-text muted alpha.
       --input-border is retained for .form-check (checkbox borders)
       which intentionally keep the bordered look. */
    --input-height:      40px;
    --input-height-sm:   32px;
    --input-height-lg:   48px;
    --input-bg:          rgba(140, 130, 115, 0.18);
    --input-bg-focus:    rgba(140, 130, 115, 0.32);
    --input-border:      #2a3347;
    --input-text:        rgba(255, 255, 255, 0.96);
    --input-placeholder: rgba(235, 230, 220, 0.40);
    --label-text:        rgba(235, 230, 220, 0.60);
    --label-text-strong: rgba(255, 255, 255, 0.85);

    /* ── FIX #28: Spec-name aliases (both conventions work) ─── */
    /* Design spec uses different names than what was implemented */
    --bg-page:      var(--bg-body);
    --bg-card:      var(--bg-surface);
    --color-accent: var(--color-primary);
    --color-accent-hover: var(--color-primary-hover);
    --text-muted:   var(--text-tertiary);
    --text-inverse: var(--text-on-primary);
    --border-strong: var(--border-color-strong);
    --bg-selected:  rgba(249, 115, 22, 0.12);  /* FIX #35: --bg-selected */
}

/* Light mode override (opt-in via data-theme="light") */
[data-theme="light"] {
    --color-primary:         #ea6f00;
    --color-primary-hover:   #c45f00;
    --color-primary-light:   #fff7ed;
    --color-primary-text:    #c2410c;

    --color-success:         #16a34a;
    --color-success-light:   #dcfce7;
    --color-success-text:    #15803d;

    --color-warning:         #d97706;
    --color-warning-light:   #fef3c7;
    --color-warning-text:    #b45309;

    --color-danger:          #dc2626;
    --color-danger-light:    #fee2e2;
    --color-danger-text:     #b91c1c;

    --color-info:            #0891b2;
    --color-info-light:      #cffafe;
    --color-info-text:       #0e7490;

    --bg-body:               #f8fafc;
    --bg-surface:            #ffffff;
    --bg-surface-2:          #f1f5f9;
    --bg-surface-hover:      #f8fafc;

    --text-primary:          #0f172a;
    --text-secondary:        #475569;
    --text-tertiary:         #94a3b8;

    --border-color:          #e2e8f0;
    --border-color-strong:   #cbd5e1;
    --border-focus:          #ea6f00;

    --topbar-bg:             #ffffff;
    --topbar-border:         #e2e8f0;
    --topbar-text:           #0f172a;

    --shadow-xs:  0 1px 2px rgba(0, 0, 0, 0.05);
    --shadow-sm:  0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04);
    --shadow-md:  0 4px 6px -1px rgba(0, 0, 0, 0.08), 0 2px 4px -1px rgba(0, 0, 0, 0.04);
    --shadow-lg:  0 10px 15px -3px rgba(0, 0, 0, 0.10), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
    --shadow-xl:  0 20px 25px -5px rgba(0, 0, 0, 0.10), 0 10px 10px -5px rgba(0, 0, 0, 0.04);

    /* S-DESIGN-INPUTS: light-mode Apple input tokens (cool gray tints).
       --label-text bumped from Apple's 0.60 to 0.72 to pass WCAG AA
       contrast (4.5:1) for 13px label text on white. */
    --input-bg:          rgba(118, 118, 128, 0.12);
    --input-bg-focus:    rgba(118, 118, 128, 0.22);
    --input-border:      #cbd5e1;
    --input-text:        rgba(0, 0, 0, 0.92);
    --input-placeholder: rgba(60, 60, 67, 0.40);
    --label-text:        rgba(60, 60, 67, 0.72);
    --label-text-strong: rgba(0, 0, 0, 0.85);
}

/* Dark mode — deeper blacks for explicit dark-mode toggle */
/* ============================================================
   THEME-1 (2026-04-08) — Dark theme refresh
   Warm brownish-black palette replaces the previous cool blue-black.
   STRICTLY scoped to [data-theme="dark"]; light theme is untouched.

   Why every variable lives here:
   - Existing names (--bg-body, --bg-surface, --topbar-bg, etc.) keep
     their meaning so the rest of the codebase rendering doesn't move.
     Their VALUES are simply rebased onto the warm palette.
   - The new spec names (--bg-card, --bg-page, --bg-muted, --bg-hover,
     --bg-input, --bg-secondary, --text-disabled, --input-focus-bg,
     --scrollbar-*, --table-*, --sidebar-text-muted, --sidebar-hover,
     --sidebar-active, --sidebar-icon) are added so the spec selectors
     work without rewriting every existing rule.
   - --bg-card and --bg-page are *redefined* here (overriding the
     :root aliases) so cards get the deep #141413 instead of the
     fall-through default of var(--bg-surface).
   - We never touch --color-accent / --color-success / --color-warning
     / --color-danger / --color-info — those stay theme-agnostic.
   ============================================================ */
[data-theme="dark"] {
    /* ── Page backgrounds ─────────────────────────── */
    --bg-body:               #262624;
    --bg-page:               #262624;
    --bg-surface:            #141413;
    --bg-card:               #141413;
    --bg-surface-2:          #1f1e1d;
    --bg-muted:              #1f1e1d;
    --bg-secondary:          #1f1e1d;
    --bg-input:              #1f1e1d;
    --bg-surface-hover:      #2a2927;
    --bg-hover:              #2a2927;
    --bg-selected:           #2e2d2b;

    /* ── Sidebar — always dark regardless of theme ── */
    --sidebar-bg:            #1f1e1d;
    --sidebar-text:          #c2c0b6;
    --sidebar-text-muted:    #8a8880;
    --sidebar-section-text:  #8a8880;
    --sidebar-text-hover:    #ffffff;
    --sidebar-text-active:   #ffffff;
    --sidebar-brand-text:    #ffffff;
    --sidebar-hover:         #2a2927;
    --sidebar-active:        #2e2d2b;
    --sidebar-item-hover-bg: #2a2927;
    --sidebar-item-active-bg: #2e2d2b;
    --sidebar-border:        #333330;
    --sidebar-icon:          #8a8880;
    --sidebar-icon-active:   #ffffff;

    /* ── Text colors ─────────────────────────────── */
    --text-primary:          #ffffff;
    --text-secondary:        #c2c0b6;
    --text-tertiary:         #8a8880;
    --text-muted:            #8a8880;
    --text-inverse:          #141413;
    --text-disabled:         #5a5855;

    /* ── Border colors ───────────────────────────── */
    --border-color:          #333330;
    --border-color-strong:   #4a4845;
    --border-strong:         #4a4845;
    --border-focus:          var(--color-accent);

    /* ── Topbar ──────────────────────────────────── */
    --topbar-bg:             #1f1e1d;
    --topbar-border:         #333330;
    --topbar-text:           #c2c0b6;

    /* ── Input fields ────────────────────────────── */
    /* S-DESIGN-INPUTS: warm-tinted Apple-style alphas, palette-matched
       to the brownish-black dark theme (#262624/#141413). */
    --input-bg:              rgba(140, 130, 115, 0.18);
    --input-bg-focus:        rgba(140, 130, 115, 0.32);
    --input-border:          #333330;
    --input-text:            rgba(255, 255, 255, 0.96);
    --input-placeholder:     rgba(235, 230, 220, 0.40);
    --input-focus-bg:        rgba(140, 130, 115, 0.32);
    --label-text:            rgba(235, 230, 220, 0.60);
    --label-text-strong:     rgba(255, 255, 255, 0.85);

    /* ── Shadows — warmer tones ──────────────────── */
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.4);
    --shadow-md: 0 4px 6px rgba(0,0,0,0.4),
                 0 1px 3px rgba(0,0,0,0.3);
    --shadow-lg: 0 10px 15px rgba(0,0,0,0.5),
                 0 4px 6px rgba(0,0,0,0.4);

    /* ── Scrollbar ───────────────────────────────── */
    --scrollbar-bg:          #1f1e1d;
    --scrollbar-thumb:       #4a4845;

    /* ── Table ───────────────────────────────────── */
    --table-header-bg:       #1f1e1d;
    --table-row-hover:       #2a2927;
    --table-border:          #333330;
    --table-stripe:          #1a1918;
}


/* ============================================================
   03. Typography
   ============================================================ */

h1, h2, h3, h4, h5, h6 {
    font-weight: 600;
    line-height: 1.25;
    color: var(--text-primary);
}

h1 { font-size: 1.5rem;    }   /* 24px */
h2 { font-size: 1.25rem;   }   /* 20px */
h3 { font-size: 1.125rem;  }   /* 18px */
h4 { font-size: 1rem;      }   /* 16px */
h5 { font-size: 0.9375rem; }   /* 15px */
h6 { font-size: 0.875rem;  }   /* 14px */

p { margin-bottom: 0.75rem; }
p:last-child { margin-bottom: 0; }

small, .text-sm { font-size: 0.875rem; }
.text-xs        { font-size: 0.8125rem; }

code, kbd, pre {
    font-family: 'DM Mono', 'Fira Code', Consolas, monospace;
    font-size: 0.875em;
}

code {
    background: var(--bg-surface-2);
    padding: 0.1em 0.35em;
    border-radius: var(--radius-sm);
    color: var(--color-danger);
}

kbd {
    background: var(--bg-surface-2);
    border: 1px solid var(--border-color-strong);
    border-radius: var(--radius-sm);
    padding: 0.1em 0.4em;
    font-size: 0.8125rem;
    color: var(--text-secondary);
    box-shadow: 0 1px 0 var(--border-color-strong);
}

.text-primary   { color: var(--text-primary) !important; }
.text-secondary { color: var(--text-secondary) !important; }
.text-tertiary  { color: var(--text-tertiary) !important; }
.text-danger    { color: var(--color-danger) !important; }
.text-success   { color: var(--color-success) !important; }
.text-warning   { color: var(--color-warning) !important; }
.text-mono      { font-family: 'DM Mono', monospace; }


/* ============================================================
   04. App Layout Shell
   ============================================================ */

.app-layout {
    display: flex;
    min-height: 100vh;
    background-color: var(--bg-body);
}

/* Main content column: topbar + page content */
.app-main {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;   /* prevent flex blowout */
    min-height: 100vh;
    transition: margin-left var(--transition-slow);
}


/* ============================================================
   05. Sidebar
   ============================================================ */

.sidebar {
    width: var(--sidebar-width);
    flex-shrink: 0;
    background-color: var(--sidebar-bg);
    border-right: 1px solid var(--sidebar-border);
    display: flex;
    flex-direction: column;
    height: 100vh;
    position: sticky;
    top: 0;
    /* SIDEBAR-SCROLL-1: outer sidebar clips, inner .sidebar-nav owns the scroll.
       Previously this element scrolled as a whole, which dragged the brand
       header off-screen on short viewports. Now .sidebar-brand + .sidebar-footer
       stay pinned and only the middle .sidebar-nav scrolls. */
    overflow: hidden;
    transition: width var(--transition-slow);
    z-index: var(--z-sidebar);
}

/* ── Brand / Logo ──────────────────────── */
/* S-DESIGN-LOGO-BIGGER: brand area decoupled from --topbar-height
   so the logo can render at a presence-worthy size regardless of
   the topbar's 60px constraint. 96px tall gives a wide wordmark
   room to breathe in the open sidebar. The topbar still anchors
   at 60px, producing a deliberate L-step that reads as "brand
   block extends below header" — common premium-app pattern. */
.sidebar-brand {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 12px 12px 16px;
    height: 96px;
    border-bottom: 1px solid var(--sidebar-border);
    flex-shrink: 0;
}

.sidebar-brand-link {
    display: flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
    overflow: hidden;
    min-width: 0;
    /* S-DESIGN-LOGO-WIDE: claim the full horizontal track so a width:100%
       child img actually grows to fill the sidebar (minus padding and the
       collapse button to its right). Without flex:1 the link sized to its
       single child's natural width, leaving dead space. */
    flex: 1;
    justify-content: center;
}

/* S-DESIGN-LOGO-WIDE: logo fills the available horizontal space in
   the brand area (was previously height-driven, leaving dead space
   to the right of narrower-aspect wordmarks). width:100% claims the
   full flex width; max-height caps total visual presence; height:auto
   preserves the source aspect ratio. object-fit:contain ensures no
   cropping when the natural width is less than 100%. */
.sidebar-logo {
    width: 100%;
    height: auto;
    max-height: 80px;
    border-radius: var(--radius-md);
    object-fit: contain;
}

.sidebar-brand-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    background: var(--color-primary);
    border-radius: var(--radius-md);
    flex-shrink: 0;
}

.brand-icon {
    width: 32px;
    height: 32px;
    color: #ffffff;
}

.sidebar-brand-name {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--sidebar-brand-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: opacity var(--transition-base), max-width var(--transition-slow);
    max-width: 160px;
}

.sidebar-collapse-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: var(--radius-md);
    color: var(--sidebar-text);
    flex-shrink: 0;
    transition: background var(--transition-fast), color var(--transition-fast),
                transform var(--transition-slow);
}

.sidebar-collapse-btn:hover {
    background: var(--sidebar-item-hover-bg);
    color: var(--sidebar-text-hover);
}

.collapse-icon {
    width: 16px;
    height: 16px;
    transition: transform var(--transition-slow);
}

/* ── Navigation ─────────────────────────── */
/* SIDEBAR-SCROLL-1: this is the real scroll container inside the flex column.
   `min-height: 0` is REQUIRED — without it a `flex: 1` child refuses to
   shrink below its content height, so `overflow: auto` never triggers and
   bottom items (Settings, Users, etc.) get cut off on short viewports.
   Scrollbar is transparent until hover for a cleaner look. */
.sidebar-nav {
    flex: 1 1 0;
    min-height: 0;
    padding: 12px 8px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    overflow-y: auto;
    overflow-x: hidden;
    scroll-behavior: smooth;
    scrollbar-width: thin;
    scrollbar-color: transparent transparent;
}

/* SIDEBAR-SCROLL-1: lock direct children to their natural size. When the
   parent has `min-height: 0` and the total children height exceeds the
   container, default `flex-shrink: 1` would squish each nav item vertically.
   This was the regression that made the sidebar look compressed on tall
   desktops after the initial scroll fix. */
.sidebar-nav > * {
    flex-shrink: 0;
}

.sidebar-nav:hover {
    scrollbar-color: rgba(255, 255, 255, 0.18) transparent;
}

.sidebar-nav::-webkit-scrollbar {
    width: 4px;
}
.sidebar-nav::-webkit-scrollbar-track {
    background: transparent;
}
.sidebar-nav::-webkit-scrollbar-thumb {
    background: transparent;
    border-radius: 4px;
    transition: background 0.2s ease;
}
.sidebar-nav:hover::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.18);
}

.nav-section-label {
    font-size: 0.6875rem;  /* 11px */
    font-weight: 600;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--sidebar-section-text);
    padding: 12px 8px 4px;
    white-space: nowrap;
    overflow: hidden;
    transition: opacity var(--transition-base);
}

.nav-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: var(--radius-md);
    color: var(--sidebar-text);
    text-decoration: none;
    font-size: 0.9rem;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    transition: background var(--transition-fast), color var(--transition-fast);
    position: relative;
}

.nav-item:hover {
    background: var(--sidebar-item-hover-bg);
    color: var(--sidebar-text-hover);
    text-decoration: none;
}

.nav-item.is-active {
    background: var(--sidebar-item-active-bg);
    color: var(--sidebar-text-active);
}

.nav-item-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    flex-shrink: 0;
}

.nav-icon {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
}

.nav-item .nav-icon { color: inherit; }
.nav-item.is-active .nav-icon { color: var(--color-primary); }

.nav-item-label {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: opacity var(--transition-base);
}

.nav-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 5px;
    background: var(--color-danger);
    color: #ffffff;
    font-size: 0.6875rem;
    font-weight: 700;
    border-radius: var(--radius-full);
    flex-shrink: 0;
    transition: opacity var(--transition-base);
}

/* ── Nav groups (collapsible parent + children) ── */
.nav-group {
    display: flex;
    flex-direction: column;
}

.nav-group > .nav-item {
    position: relative;
}

.nav-group-arrow {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    color: var(--sidebar-text);
    opacity: 0.5;
    transition: transform var(--transition-fast), opacity var(--transition-fast);
}

.nav-group.is-open > .nav-item .nav-group-arrow {
    transform: rotate(90deg);
    opacity: 0.7;
}

.nav-children {
    display: none;
    flex-direction: column;
    padding-left: 14px;
}

.nav-group.is-open > .nav-children {
    display: flex;
}

.nav-item--child {
    font-size: 0.825rem;
    padding: 6px 10px;
}

.nav-item--child .nav-item-icon {
    width: 16px;
    height: 16px;
}

.nav-item--child .nav-icon {
    width: 14px;
    height: 14px;
}

/* ────────── S-SIDEBAR-LOCK-ALL-RESTRICTED ──────────
   Locked nav items render in place of hidden ones so every role sees
   the full module map. .nav-item base rules still apply (flex layout,
   gap, padding, border-radius) — the modifier overrides only what
   needs to change for the locked state. */
.nav-item--locked {
    cursor: not-allowed;
    pointer-events: none;
    user-select: none;
    opacity: 0.38;
    color: var(--text-muted);
}
.nav-icon--locked {
    opacity: 0.6;
    flex-shrink: 0;
}
.nav-lock-icon {
    margin-left: auto;
    flex-shrink: 0;
    opacity: 0.7;
    display: flex;
    align-items: center;
}
/* Defensive: section separators never wrap a lock icon today, but
   keep this rule in case the structure changes. */
.nav-section-label .nav-lock-icon { display: none; }
/* Collapsed-state rules live alongside the existing
   .sidebar:not(.is-open) block — see further down in the file
   for the matching @media (min-width: 1024px) overrides. */
/* ────────── S-SIDEBAR-LOCK-ALL-RESTRICTED END ────────── */

/* ── User Footer ─────────────────────────── */
.sidebar-footer {
    border-top: 1px solid var(--sidebar-border);
    padding: 12px 10px;
    flex-shrink: 0;
}

.sidebar-user {
    display: flex;
    align-items: center;
    gap: 8px;
}

.sidebar-user-info {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    transition: opacity var(--transition-base), max-width var(--transition-slow);
    max-width: 160px;
}

.sidebar-user-name {
    display: block;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--sidebar-text-hover);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar-user-role {
    display: block;
    font-size: 0.75rem;
    color: var(--sidebar-section-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar-user-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

/* ── Theme toggle icons ──────────────────── */
.theme-icon { width: 18px; height: 18px; }

/* Light mode: show moon (click → switch to dark), hide sun */
.theme-icon--light { display: none;  }
.theme-icon--dark  { display: block; }

/* Dark mode: show sun (click → switch to light), hide moon */
[data-theme="dark"] .theme-icon--light { display: block; }
[data-theme="dark"] .theme-icon--dark  { display: none;  }

/* ── Collapsed sidebar (desktop) ─────────── */
@media (min-width: 1024px) {
    .sidebar:not(.is-open) {
        width: var(--sidebar-width-collapsed);
    }

    .sidebar:not(.is-open) .sidebar-brand-name,
    .sidebar:not(.is-open) .nav-item-label,
    .sidebar:not(.is-open) .nav-badge,
    .sidebar:not(.is-open) .nav-group-arrow,
    .sidebar:not(.is-open) .sidebar-user-info {
        opacity: 0;
        pointer-events: none;
        max-width: 0;
    }

    /* Elements that must FULLY collapse out of layout in icons-only
       mode — opacity:0 + max-width:0 alone leaves vertical padding +
       child heights behind, accumulating into 60-200px of empty
       vertical space between top-level icons (operator surfaced
       2026-05-20).

       Section separators: ~16px of padding per separator (12+4 vertical).
       Nav-children: the active group has .is-open which forces
       display:flex on its .nav-children container, expanding to the
       full natural height of the child links (~36px each × N children).
       Both are decorative-only in collapsed mode, so display:none is
       the cleanest fix. */
    .sidebar:not(.is-open) .nav-section-label,
    .sidebar:not(.is-open) .nav-children {
        display: none;
    }

    /* S-SIDEBAR-COLLAPSED-BADGE-DOT — keep notification badges visible
       in collapsed mode but pin them to the top-right of the nav item
       as a small iOS-style dot. position:absolute removes the badge
       from the flex flow so it cannot reserve a gap slot that pushes
       the icon off center. Override every "hide" property the shared
       rule above sets (opacity / pointer-events / max-width) to make
       sure the badge actually renders. Smaller dimensions + tighter
       padding + smaller font appropriate for the 64px collapsed track. */
    .sidebar:not(.is-open) .nav-badge {
        position: absolute;
        top: 4px;
        right: 8px;
        min-width: 16px;
        height: 16px;
        padding: 0 4px;
        font-size: 0.5625rem;    /* 9px */
        line-height: 1;
        opacity: 1;
        pointer-events: auto;
        max-width: none;
        visibility: visible;
        z-index: 1;
    }

    .sidebar:not(.is-open) .sidebar-brand {
        justify-content: center;
        padding: 0 8px;
    }

    /* S-DESIGN-LOGO-BIGGER: cap the bigger logo when the sidebar
       collapses to icon-only so a wide wordmark doesn't overflow
       the 64px-wide collapsed track. Brand area also returns to
       topbar-height in collapsed mode so the L-step disappears
       when the user has compacted the chrome. */
    .sidebar:not(.is-open) .sidebar-brand {
        height: var(--topbar-height);
        padding: 0 8px;
    }
    .sidebar:not(.is-open) .sidebar-logo {
        max-width: 44px;
        height: 40px;
    }
    .sidebar:not(.is-open) .sidebar-brand-icon {
        width: 40px;
        height: 40px;
    }
    .sidebar:not(.is-open) .brand-icon {
        width: 24px;
        height: 24px;
    }

    .sidebar:not(.is-open) .sidebar-collapse-btn {
        display: none; /* hide collapse btn when collapsed; topbar menu btn takes over */
    }

    .sidebar:not(.is-open) .nav-item {
        justify-content: center;
        padding: 8px;
        /* S-SIDEBAR-COLLAPSED-ICON-FIX — zero the inter-child gap so
           any hidden-but-flex-present child (e.g. .nav-item-label
           with max-width:0) can't reserve a 10px slot that pushes
           the icon off center. */
        gap: 0;
    }
    .sidebar:not(.is-open) .nav-item-icon,
    .sidebar:not(.is-open) .nav-icon {
        margin: 0 auto;
        flex-shrink: 0;
    }

    /* S-SIDEBAR-LOCK-ALL-RESTRICTED — collapsed-mode locked items.
       The base .nav-item collapsed rule already centres the icon
       (justify-content:center, gap:0, padding:8px) and hides the
       label (opacity:0, max-width:0). The lock icon needs to escape
       the flex flow and pin to the bottom-right corner of the
       collapsed rail (next to the centred module icon) as a tiny
       indicator. */
    .sidebar:not(.is-open) .nav-lock-icon {
        position: absolute;
        bottom: 4px;
        right: 8px;
        width: 8px;
        height: 8px;
        margin: 0;
        opacity: 0.8;
    }

    .sidebar:not(.is-open) .sidebar-user {
        justify-content: center;
    }

    .sidebar:not(.is-open) .sidebar-user-actions {
        flex-direction: column;
    }

    .sidebar:not(.is-open) .collapse-icon {
        transform: rotate(180deg);
    }
}


/* ============================================================
   06. Topbar
   ============================================================ */

.topbar {
    position: sticky;
    top: 0;
    z-index: var(--z-topbar);
    height: var(--topbar-height);
    background: var(--topbar-bg);
    border-bottom: 1px solid var(--topbar-border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 20px 0 24px;
    gap: 16px;
    flex-shrink: 0;
}

.topbar-left {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}

.topbar-right {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

.topbar-title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--topbar-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* S-DESIGN-LOGO-TOPBAR — company name as breadcrumb root in topbar.
   Sized so it reads as the dominant brand element on every page;
   page title (.topbar-title) sits to the right as a secondary label
   separated by a › chevron. */
.topbar-company-name {
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--topbar-text);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 280px;
    letter-spacing: -0.01em;
    transition: color var(--transition-fast);
}
.topbar-company-name:hover { color: var(--color-primary); }

.topbar-breadcrumb-sep {
    color: var(--text-muted);
    font-size: 1rem;
    font-weight: 400;
    margin: 0 -2px;
    flex-shrink: 0;
}

@media (max-width: 767px) {
    /* On phones the topbar is tight — drop the breadcrumb so only
       the page title shows. Company name is still visible in the
       sidebar / hamburger menu for context. */
    .topbar-company-name,
    .topbar-breadcrumb-sep { display: none; }
}

/* Mobile menu toggle — hidden on desktop */
.topbar-menu-btn {
    display: none;
}

/* S-MOBILE-CHROME-CLEANUP — mobile-only search icon button.
   Hidden on desktop+tablet where .search-wrapper renders inline;
   revealed at <768px (see the mobile media block) where it opens
   the existing ⌘K global search modal. */
.topbar-search-icon-btn {
    display: none;
}

/* Search trigger */
.topbar-search-btn {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    background: var(--bg-surface-2);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-full);
    color: var(--text-tertiary);
    font-size: 0.875rem;
    transition: background var(--transition-fast), border-color var(--transition-fast),
                color var(--transition-fast);
    cursor: pointer;
}

.topbar-search-btn:hover {
    background: var(--bg-surface);
    border-color: var(--border-color-strong);
    color: var(--text-secondary);
}

.topbar-search-btn .search-icon {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

.search-hint {
    display: flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}

.search-kbd {
    display: inline-flex;
    align-items: center;
    gap: 1px;
    font-family: 'DM Mono', monospace;
    font-size: 0.75rem;
    padding: 1px 5px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color-strong);
    border-radius: var(--radius-sm);
    box-shadow: 0 1px 0 var(--border-color-strong);
    color: var(--text-tertiary);
}

/* Notifications bell */
.topbar-notifications {
    position: relative;
}

.topbar-bell-btn {
    position: relative;
}

.notification-dot {
    position: absolute;
    top: -2px;
    right: -2px;
    min-width: 18px;
    height: 18px;
    padding: 0 4px;
    background: var(--color-danger);
    color: #ffffff;
    font-size: 0.6875rem;
    font-weight: 700;
    border-radius: var(--radius-full);
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid var(--topbar-bg);
    pointer-events: none;
}

.notification-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: 360px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-xl);
    z-index: var(--z-dropdown);
    overflow: hidden;
}

.notification-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 16px 12px;
    border-bottom: 1px solid var(--border-color);
}

.notification-heading {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--text-primary);
}

.notification-list {
    max-height: 360px;
    overflow-y: auto;
}

.notification-empty {
    padding: 24px;
    text-align: center;
    color: var(--text-tertiary);
    font-size: 0.875rem;
}

/* Individual notification items — rendered by app.js */
.notification-item {
    display: flex;
    gap: 12px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-color);
    transition: background var(--transition-fast);
    text-decoration: none;
    color: inherit;
}

.notification-item:last-child { border-bottom: none; }

.notification-item:hover {
    background: var(--bg-surface-hover);
    text-decoration: none;
}

.notification-item.is-unread {
    background: var(--color-primary-light);
}

.notification-item-body {
    flex: 1;
    min-width: 0;
}

.notification-item-text {
    font-size: 0.875rem;
    color: var(--text-primary);
    line-height: 1.45;
}

.notification-item-time {
    font-size: 0.75rem;
    color: var(--text-tertiary);
    margin-top: 2px;
}

.notification-footer {
    padding: 10px 16px;
    border-top: 1px solid var(--border-color);
    text-align: center;
}

/* Mac / non-Mac shortcut hints */
.mac-only     { display: none; }
.non-mac-only { display: inline; }

/* ── Home button (between menu toggle and page title) ───────────────────────── */
.topbar-home-btn {
    color: var(--text-secondary);
    text-decoration: none;
}
.topbar-home-btn:hover {
    color: var(--text-primary);
    background: var(--bg-surface-2);
}

/* ── Theme toggle button ────────────────────────────────────────────────────── */
/* Reuses .btn-icon sizing; just a label for specificity / hover overrides.     */
.topbar-theme-btn {
    color: var(--text-secondary);
}
.topbar-theme-btn:hover {
    color: var(--text-primary);
    background: var(--bg-surface-2);
}

/* ── Quick-create "+" dropdown ──────────────────────────────────────────────── */
.topbar-create {
    position: relative;
}

.topbar-create-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 13px 5px 10px;
    background: var(--color-primary);
    color: #fff;
    border: none;
    border-radius: var(--radius-full);
    font-size: 0.8125rem;
    font-weight: 600;
    cursor: pointer;
    transition: background var(--transition-fast), box-shadow var(--transition-fast);
    white-space: nowrap;
    height: 32px;
}
.topbar-create-btn:hover {
    background: var(--color-primary-dark, color-mix(in srgb, var(--color-primary) 85%, black));
    box-shadow: 0 1px 6px rgba(0,0,0,0.18);
}
.topbar-create-btn:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 2px;
}

.topbar-create-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    min-width: 192px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-xl);
    z-index: var(--z-dropdown);
    overflow: hidden;
    padding: 6px 0;
}

.topbar-dropdown-label {
    padding: 6px 14px 4px;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-tertiary);
    margin: 0;
}

.topbar-create-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 14px;
    font-size: 0.875rem;
    color: var(--text-primary);
    text-decoration: none;
    transition: background var(--transition-fast);
}
.topbar-create-item:hover {
    background: var(--bg-surface-hover);
    text-decoration: none;
    color: var(--text-primary);
}
.topbar-create-item svg,
.topbar-create-item .nav-icon {
    color: var(--text-secondary);
    flex-shrink: 0;
}

/* ══════════════════════════════════════════════════════════════
   PERM-1 — Display settings popover (font size + density)
   The trigger sits in the topbar before the notifications bell;
   the dropdown floats below using the standard topbar dropdown
   positioning conventions.
   ══════════════════════════════════════════════════════════════ */
.topbar-display {
    position: relative;
    display: flex;
    align-items: center;
}

.topbar-display-btn {
    color: var(--text-secondary);
}
.topbar-display-btn:hover {
    color: var(--text-primary);
    background: var(--bg-surface-hover);
}

.topbar-display-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    min-width: 248px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    padding: 12px;
    z-index: 100;
}

.topbar-display-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 4px 2px;
}

.topbar-display-value {
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--text-primary);
    min-width: 48px;
    text-align: center;
}

.topbar-display-density {
    display: flex;
    gap: 6px;
    padding: 6px 2px 4px;
}

.topbar-display-chip {
    flex: 1 1 0;
    padding: 6px 8px;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--text-secondary);
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all var(--transition-fast);
}
.topbar-display-chip:hover:not(:disabled) {
    border-color: var(--color-primary);
    color: var(--text-primary);
}
.topbar-display-chip.is-active {
    background: color-mix(in srgb, var(--color-primary) 14%, transparent);
    border-color: var(--color-primary);
    color: var(--color-primary);
    font-weight: 600;
}
.topbar-display-chip:disabled {
    cursor: not-allowed;
    opacity: 0.6;
}

.topbar-display-reset {
    width: 100%;
    margin-top: 4px;
    padding: 7px 10px;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--text-secondary);
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all var(--transition-fast);
}
.topbar-display-reset:hover:not(:disabled) {
    background: var(--bg-surface-hover);
    color: var(--text-primary);
    border-color: var(--text-secondary);
}
.topbar-display-reset:disabled {
    cursor: not-allowed;
    opacity: 0.5;
}

/* ══════════════════════════════════════════════════════════════
   PERM-1 — Density variants for .page-content.
   <body data-density="..."> is set in includes/header.php from the
   user's saved preference. These rules tweak the spacing of cards,
   tables, and form controls within the main content area only —
   never the sidebar/topbar/footer/modals.
   ══════════════════════════════════════════════════════════════ */

/* COMPACT — tighter padding, smaller gaps */
body[data-density="compact"] .page-content .card-body { padding: 12px 14px; }
body[data-density="compact"] .page-content .card-header { padding: 10px 14px; }
body[data-density="compact"] .page-content .table th,
body[data-density="compact"] .page-content .table td { padding: 6px 10px; }
body[data-density="compact"] .page-content .form-group { margin-bottom: 10px; }
body[data-density="compact"] .page-content .page-header { margin-bottom: 12px; }
body[data-density="compact"] .page-content .form-control { padding: 6px 9px; }

/* COMFORTABLE — current defaults (no overrides needed) */
/* Intentionally empty so the rule cascade is explicit and easy to grep */
body[data-density="comfortable"] .page-content { /* default spacing */ }

/* SPACIOUS — looser padding, taller rows for easier scanning */
body[data-density="spacious"] .page-content .card-body { padding: 24px 26px; }
body[data-density="spacious"] .page-content .card-header { padding: 18px 26px; }
body[data-density="spacious"] .page-content .table th,
body[data-density="spacious"] .page-content .table td { padding: 14px 18px; }
body[data-density="spacious"] .page-content .form-group { margin-bottom: 22px; }
body[data-density="spacious"] .page-content .page-header { margin-bottom: 28px; }
body[data-density="spacious"] .page-content .form-control { padding: 11px 14px; }

/* ── User avatar + dropdown ─────────────────────────────────────────────────── */
.topbar-user {
    position: relative;
}

/* Base avatar circle — initials badge */
.user-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: var(--radius-full);
    background: var(--color-primary);
    color: #fff;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    border: 2px solid transparent;
    cursor: pointer;
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
    flex-shrink: 0;
    user-select: none;
    /* Reset button defaults when used as <button> */
    padding: 0;
    line-height: 1;
}
.user-avatar:hover {
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 20%, transparent);
}
.user-avatar:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 2px;
}

/* Large variant — used inside the dropdown header */
.user-avatar--lg {
    width: 42px;
    height: 42px;
    font-size: 0.9rem;
    pointer-events: none;  /* decorative inside the dropdown */
}

/* ── User trigger button (avatar + name + role) ─────────────
   NOTIF-1 follow-up: shows the logged-in user's name + role
   in the topbar next to their initials. The button itself is
   the dropdown trigger. The .user-trigger-meta block collapses
   on mobile (≤767px) to keep the topbar from overflowing. */
.user-trigger {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 4px 12px 4px 4px;
    border: 1px solid var(--border-color);
    background: var(--bg-surface);
    border-radius: var(--radius-full);
    cursor: pointer;
    color: var(--text-primary);
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast),
                background var(--transition-fast);
    font-family: inherit;
    line-height: 1;
}
.user-trigger:hover {
    border-color: var(--color-primary);
    background: var(--bg-surface-hover, var(--bg-muted));
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 15%, transparent);
}
.user-trigger:focus-visible {
    outline: 2px solid var(--border-focus, var(--color-primary));
    outline-offset: 2px;
}
.user-trigger .user-avatar {
    width: 30px;
    height: 30px;
    cursor: inherit;
    border: none;
    box-shadow: none;
}
.user-trigger:hover .user-avatar {
    border: none;
    box-shadow: none;
}
.user-trigger-meta {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    text-align: left;
    min-width: 0;
    max-width: 160px;
}
.user-trigger-name {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}
.user-trigger-role {
    font-size: 0.6875rem;
    font-weight: 500;
    color: var(--text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
@media (max-width: 767px) {
    .user-trigger {
        padding: 0;
        border: none;
        background: transparent;
        gap: 0;
    }
    .user-trigger:hover {
        background: transparent;
        box-shadow: none;
    }
    .user-trigger .user-avatar {
        width: 34px;
        height: 34px;
    }
    .user-trigger-meta {
        display: none;
    }
}

/* User dropdown panel */
.user-dropdown {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    width: 240px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-xl);
    z-index: var(--z-dropdown);
    overflow: hidden;
}

/* Header — avatar + name + role + email */
.user-dropdown-header {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 14px 16px 12px;
}

.user-dropdown-identity {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
    flex: 1;
}

.user-dropdown-name {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.user-dropdown-meta {
    display: flex;
    align-items: center;
    gap: 6px;
}

.user-dropdown-email {
    font-size: 0.75rem;
    color: var(--text-tertiary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Divider line */
.user-dropdown-divider {
    height: 1px;
    background: var(--border-color);
    margin: 4px 0;
}

/* Menu items */
.user-dropdown-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 16px;
    font-size: 0.875rem;
    color: var(--text-primary);
    text-decoration: none;
    transition: background var(--transition-fast);
}
.user-dropdown-item:hover {
    background: var(--bg-surface-hover);
    text-decoration: none;
    color: var(--text-primary);
}
.user-dropdown-item svg,
.user-dropdown-item .nav-icon {
    color: var(--text-secondary);
    flex-shrink: 0;
}

/* Sign Out — danger tint on hover */
.user-dropdown-item--danger { color: var(--color-danger); }
.user-dropdown-item--danger svg,
.user-dropdown-item--danger .nav-icon { color: var(--color-danger); }
.user-dropdown-item--danger:hover {
    background: color-mix(in srgb, var(--color-danger) 8%, transparent);
    color: var(--color-danger);
}


/* ============================================================
   07. Page Content & Panels
   ============================================================ */

.page-content {
    flex: 1;
    padding: 28px 32px 0;   /* bottom padding removed — app-footer provides spacing */
    min-width: 0;
}

/* ── Tab table scroll containers ────────────────────────────────────────────
   WHY: Keeps show-page sub-tables within the viewport height so the page
   header and action buttons stay visible. Sticky thead pins column headers
   while scrolling. .tab-filter-bar holds filter/sort controls above the table.
   .tab-table-footer shows row count + optional Load more button below.
*/
.tab-table-container {
    max-height: calc(100vh - 320px);
    overflow-y: auto;
}
.tab-table-container thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--bg-surface);
    box-shadow: 0 1px 0 var(--border-color);
}
.tab-filter-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    border-bottom: 1px solid var(--border-color);
    flex-wrap: wrap;
    background: var(--bg-surface);
}
.tab-table-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 16px;
    font-size: 0.75rem;
    color: var(--text-muted);
    border-top: 1px solid var(--border-color);
    background: var(--bg-surface);
}

/* ── App footer ──────────────────────────────────────────────────────────────
   Normal flow element at the end of .app-main. Visible only when the user
   scrolls to the bottom of the page — not sticky, not fixed.
*/
/* S-LEGAL-FOOTER-COMMERCIAL: admin footer extended with a middle slot
   for legal links. Outer flex row stays slim; inner pieces wrap on
   narrow screens so the layout degrades gracefully without overflow. */
/* S-SIDEBAR-COLLAPSED-TOOLTIP — body-positioned tooltip for collapsed
   sidebar nav items. Appended to <body> at runtime by the script in
   includes/sidebar.php; that's what lets it escape the sidebar's
   overflow:hidden clipping context (a pure-CSS tooltip can't escape
   without breaking the inner sidebar-nav scroll). position:fixed +
   coordinates calculated from each nav-item's bounding rect on hover. */
.ff-nav-tooltip {
    position: fixed;
    background: var(--bg-surface-2);
    color: var(--text-primary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    padding: 6px 12px;
    font-size: 0.8125rem;
    font-weight: 500;
    line-height: 1.3;
    white-space: nowrap;
    pointer-events: none;
    z-index: 9999;
    box-shadow: var(--shadow-md);
    transform: translateY(-50%);
    opacity: 0;
    transition: opacity 80ms ease;
    letter-spacing: -0.005em;
}
.ff-nav-tooltip.is-visible {
    opacity: 1;
}

.app-footer {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px 24px;
    padding: 10px 32px;
    border-top: 1px solid var(--border-color);
    font-size: 0.6875rem;
    color: var(--text-muted);
    margin-top: auto;
}
.app-footer-left      { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.app-footer-brand strong { color: var(--text-secondary); font-weight: 500; }
.app-footer-divider   { opacity: 0.4; }
.app-footer-legal     { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.app-footer-legal-link {
    color: var(--text-muted);
    text-decoration: none;
    transition: color var(--transition-fast);
}
.app-footer-legal-link:hover { color: var(--color-primary); }
.app-footer-right     { color: var(--text-muted); }
@media (max-width: 900px) {
    .app-footer       { flex-direction: column; gap: 8px; padding: 12px 20px; text-align: center; }
    .app-footer-legal { justify-content: center; }
}

/* Page header (title + actions row) */
.page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 28px;
    padding-bottom: 20px;
    border-bottom: 1px solid var(--border-color);
    flex-wrap: wrap;
}

.page-header-title {
    margin: 0;
    background: linear-gradient(135deg, var(--text-primary) 0%, var(--text-secondary) 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

.page-header-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

/* Card / Panel */
.card {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-xl);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    transition: box-shadow var(--transition-base), border-color var(--transition-base);
}

.card:hover {
    border-color: var(--border-color-strong);
    box-shadow: var(--shadow-md);
}

.card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px;
    border-bottom: 1px solid var(--border-color);
    gap: 12px;
    background: var(--bg-surface-2);
}

.card-title {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--text-primary);
    margin: 0;
}

.card-body {
    padding: 20px;
}

.card-footer {
    padding: 14px 20px;
    border-top: 1px solid var(--border-color);
    background: var(--bg-surface-2);
}

/* ── Spec card — elevated key/value table card ──────────────
   Used for showing structured "label: value" data in detail
   modals and profile pages. Promoted from app/admin/equipment/show.php
   so the same look can be reused across the fixed-assets module
   and any other place that needs a labeled property list. */
.spec-card {
    border: 1px solid var(--border-color-strong);
    box-shadow: 0 2px 8px rgba(0,0,0,0.06), 0 0 0 1px rgba(0,0,0,0.03);
}
.spec-card .card-header {
    background: var(--color-primary);
    border-bottom: none;
    padding: 12px 16px;
}
.spec-card .card-header .card-title {
    color: #fff;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
}
.spec-card .card-body { padding: 0; }

.spec-table {
    width: 100%;
    border-collapse: collapse;
}
.spec-table tr { border-bottom: 1px solid var(--border-color); }
.spec-table tr:last-child { border-bottom: none; }
.spec-table tr:nth-child(even) { background: var(--bg-surface-2); }
.spec-table td {
    padding: 11px 16px;
    font-size: 0.875rem;
    vertical-align: baseline;
}
.spec-table .spec-label {
    width: 160px;
    color: var(--text-tertiary);
    font-size: 0.8125rem;
    font-weight: 500;
    white-space: nowrap;
}
.spec-table .spec-value { color: var(--text-primary); font-weight: 500; }
.spec-table td.text-right { text-align: right; }

/* ── Section header inside a card or modal ──────────────────
   Slim divider with an uppercase eyebrow label. Used to break
   up long forms (Create/Edit modals) into visual groups. */
.section-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 24px 0 12px 0;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border-color);
}
.section-header:first-child { margin-top: 0; }
.section-header .section-title {
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-secondary);
    margin: 0;
}
.section-header .section-hint {
    font-size: 0.75rem;
    color: var(--text-tertiary);
    font-weight: 400;
    text-transform: none;
    letter-spacing: normal;
}

/* ============================================================
   Stats / Summary tiles
   ------------------------------------------------------------
   Two structures share these styles:
     1. Legacy:  <div class="stat-card stat-card--<color>">
                   <span class="stat-icon stat-icon--<color>">…</span>
                   <div class="stat-label">…</div>
                   <div class="stat-value">…</div>
                   <div class="stat-delta">…</div>
                 </div>
     2. Modern:  <a class="stat-card stat-card--link"> with
                 <div class="stat-card__header"> wrapping
                 <.stat-label> + <.stat-card__icon> (flex row).
   Both must comfortably fit currency values up to ~$1,234,567.89
   without truncating — that's the whole reason this block was
   re-tuned: the previous 200px minimum + 1.875rem value font +
   60px right-padding combo was clipping seven-digit dollar values.
   ============================================================ */
.stat-grid {
    display: grid;
    /* WHY: 200px minimum keeps 6-tile dashboards on a single row at
       our standard 1280–1440px content widths. After padding (30px)
       that leaves ~170px content area which fits $1,234,567.89 at
       the 1.375rem value font below with room to spare. */
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 14px;
    margin-bottom: 20px;
}

/* Invoice addresses: Bill To + Invoice Details cards side-by-side.
   WHY: Extracted from inline style so responsive rules can override it. */
.invoice-addresses {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
    margin-bottom: 24px;
}

.stat-card {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    /* WHY: padding tightened from 20/60/20/28 → 14/16/14/22.
       The big-ticket change is dropping the 60px right reservation
       (icon shrunk from 42px → 30px and is allowed to overlap the
       label row only — the value below uses the full content width). */
    padding: 14px 16px 14px 22px;
    box-shadow: var(--shadow-sm);
    position: relative;
    overflow: hidden;
    /* WHY: lets the card shrink inside CSS grid so its children
       can use min-width:0 / ellipsis without forcing the column. */
    min-width: 0;
    transition: box-shadow var(--transition-base), border-color var(--transition-base),
                transform var(--transition-base);
}

/* Left accent bar — uses per-card --stat-accent or defaults to primary */
.stat-card::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 4px;
    background: linear-gradient(
        to bottom,
        var(--stat-accent, var(--color-primary)),
        color-mix(in srgb, var(--stat-accent, var(--color-primary)) 50%, transparent)
    );
    border-radius: var(--radius-lg) 0 0 var(--radius-lg);
}

.stat-card:hover {
    box-shadow: var(--shadow-md);
    border-color: var(--border-color-strong);
    transform: translateY(-2px);
}

/* Per-card accent color variants */
.stat-card--green  { --stat-accent: #22c55e; }
.stat-card--blue   { --stat-accent: #3b82f6; }
.stat-card--amber  { --stat-accent: #f59e0b; }
.stat-card--red    { --stat-accent: #ef4444; }
.stat-card--purple { --stat-accent: #8b5cf6; }
.stat-card--teal   { --stat-accent: #14b8a6; }
.stat-card--slate  { --stat-accent: #64748b; }

/* Decorative icon container — positioned top-right (LEGACY structure).
   Modern .stat-card__header / .stat-card__icon are defined separately
   below the dashboard variants block. */
.stat-icon {
    position: absolute;
    top: 12px;
    right: 12px;
    /* WHY: shrunk 42→30 so it stops eating the value's horizontal room. */
    width: 30px;
    height: 30px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.stat-icon svg {
    width: 16px;
    height: 16px;
}
.stat-icon--green  { background: rgba(34,197,94,0.12);  color: #22c55e; }
.stat-icon--blue   { background: rgba(59,130,246,0.12); color: #60a5fa; }
.stat-icon--amber  { background: rgba(245,158,11,0.12); color: #f59e0b; }
.stat-icon--red    { background: rgba(239,68,68,0.12);  color: #f87171; }
.stat-icon--purple { background: rgba(139,92,246,0.12); color: #a78bfa; }
.stat-icon--teal   { background: rgba(20,184,166,0.12); color: #2dd4bf; }
.stat-icon--slate  { background: rgba(100,116,139,0.12);color: #94a3b8; }

.stat-label {
    font-size: 0.6875rem;            /* 11px — was 12px */
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    line-height: 1.3;
    margin-bottom: 6px;              /* was 10px */
    /* WHY: reserve horizontal room so the absolute icon at right:12 / w:30
       doesn't overlap multi-word labels like "TOTAL REVENUE YTD". */
    padding-right: 38px;
    /* Cap at 2 lines, ellipsis if it overflows. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.stat-value {
    /* WHY: dropped 1.875rem (~30px) → 1.375rem (~22px). At 22px DM Mono
       each char is ~12px, so $1,234,567.89 (13 chars) ≈ 156px which
       fits comfortably in the ~170px content area of a 200px tile. */
    font-size: 1.375rem;
    font-weight: 700;
    color: var(--text-primary);
    font-family: 'DM Mono', monospace;
    line-height: 1.2;
    margin-bottom: 4px;              /* was 8px */
    /* WHY: allow the line to shrink inside grid; never wrap mid-currency.
       If a value still won't fit (e.g. 9-figure totals) we ellipsis it
       instead of letting it crash through the tile boundary. */
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.stat-delta {
    font-size: 0.75rem;              /* 12px — was 13px */
    color: var(--text-tertiary);
    line-height: 1.3;
    /* WHY: keep deltas like "$73,617.00 outstanding" on a single line
       so they don't wrap mid-amount. Long deltas get cleanly trimmed. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Clickable stat-card KPI tiles — active ring + pointer affordance */
.stat-card[style*="cursor:pointer"],
.stat-card.stat-card--link {
    cursor: pointer;
    /* WHY: <a> tags need explicit reset so the inner text doesn't underline. */
    text-decoration: none;
    color: inherit;
    display: block;
}
.stat-card.stat-card--link:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}
.stat-card.ring-active {
    box-shadow: 0 0 0 2px var(--stat-accent, var(--color-primary)), var(--shadow-md);
    border-color: var(--stat-accent, var(--color-primary));
}


/* ============================================================
   08. Buttons
   ============================================================ */

/* Base button */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-family: inherit;
    font-weight: 500;
    border-radius: var(--radius-md);
    border: 1px solid transparent;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background var(--transition-fast), color var(--transition-fast),
                border-color var(--transition-fast), box-shadow var(--transition-fast),
                opacity var(--transition-fast);
    line-height: 1;
    vertical-align: middle;
    user-select: none;
}

.btn:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 2px;
}

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

/* Sizes */
.btn-xs {
    font-size: 0.75rem;
    padding: 4px 8px;
    height: 26px;
    border-radius: var(--radius-sm);
    gap: 4px;
}

.btn-sm {
    font-size: 0.8125rem;
    padding: 5px 12px;
    height: 32px;
}

.btn-md {
    font-size: 0.875rem;
    padding: 7px 16px;
    height: 38px;
}

.btn-lg {
    font-size: 0.9375rem;
    padding: 10px 20px;
    height: 46px;
    gap: 8px;
}

.btn-xl {                                                    /* FIX #35 */
    font-size: 1rem;
    padding: 12px 24px;
    height: 54px;
    gap: 10px;
}

/* Default .btn with no modifier = medium */
.btn:not(.btn-xs):not(.btn-sm):not(.btn-lg):not(.btn-icon):not(.btn-link) {
    font-size: 0.875rem;
    padding: 7px 16px;
    height: 38px;
}

/* Variants */
.btn-primary {
    background: var(--color-primary);
    color: #ffffff;
    border-color: var(--color-primary);
}
.btn-primary:hover {
    background: var(--color-primary-hover);
    border-color: var(--color-primary-hover);
    text-decoration: none;
    color: #ffffff;
}

.btn-secondary {
    background: var(--bg-surface);
    color: var(--text-secondary);
    border-color: var(--border-color-strong);
}
.btn-secondary:hover {
    background: var(--bg-surface-2);
    color: var(--text-primary);
    border-color: var(--border-color-strong);
    text-decoration: none;
}

.btn-danger {
    background: var(--color-danger);
    color: #ffffff;
    border-color: var(--color-danger);
}
.btn-danger:hover {
    background: #b91c1c;
    border-color: #b91c1c;
    text-decoration: none;
    color: #ffffff;
}

.btn-success {
    background: var(--color-success);
    color: #ffffff;
    border-color: var(--color-success);
}
.btn-success:hover {
    background: #16a34a;
    text-decoration: none;
    color: #ffffff;
}

.btn-warning {
    background: var(--color-warning);
    color: #0f172a;
    border-color: var(--color-warning);
}
.btn-warning:hover {
    background: #ca8a04;
    border-color: #ca8a04;
    text-decoration: none;
    color: #0f172a;
}

.btn-ghost {
    background: transparent;
    color: var(--text-secondary);
    border-color: var(--border-color);
}
.btn-ghost:hover {
    background: var(--bg-surface-2);
    color: var(--text-primary);
    border-color: var(--border-color-strong);
    text-decoration: none;
}

/* Soft-danger outline for inline table destructive actions —
   less aggressive than solid .btn-danger, appropriate for row-level Remove/Delete */
.btn-outline-danger {
    background: transparent;
    color: var(--color-danger);
    border-color: color-mix(in srgb, var(--color-danger) 35%, transparent);
}
.btn-outline-danger:hover {
    background: var(--color-danger-light);
    border-color: var(--color-danger);
    color: var(--color-danger);
    text-decoration: none;
}

/* Icon-only button */
.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: var(--radius-md);
    color: var(--text-secondary);
    border: none;
    background: transparent;
    cursor: pointer;
    transition: background var(--transition-fast), color var(--transition-fast);
    flex-shrink: 0;
}

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

.btn-icon:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 2px;
}

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

/* Link-styled button */
.btn-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: none;
    border: none;
    padding: 0;
    color: var(--color-primary);
    font-size: inherit;
    font-weight: 500;
    cursor: pointer;
    text-decoration: none;
    transition: color var(--transition-fast);
}

.btn-link:hover {
    color: var(--color-primary-hover);
    text-decoration: underline;
}

.btn-link.btn-sm { font-size: 0.8125rem; }
.btn-link.btn-xs { font-size: 0.75rem; }

/* Button with icon
   WHY: previously used `:first-child:not(:only-child)` to skip icon-only
   buttons. That selector incorrectly treated text-node-sibling SVGs as
   :only-child (CSS :only-child ignores text nodes), so buttons emitted
   as `<button> <svg> Label </button>` escaped the 16×16 sizing and
   ballooned to full button width once RESPONSIVE-1 made `.btn { width:
   100% }` on mobile. Switched to `.btn > svg` which sizes any direct
   SVG child; icon-only buttons should use the dedicated `.btn-icon`
   class which doesn't match `.btn > svg` here. The chat widget send
   button has inline `style="width:14px;height:14px"` so its inline
   styles still win. */
.btn .btn-icon-left,
.btn > svg {
    width: 16px;
    height: 16px;
}

/* Loading state */
.btn.is-loading {
    pointer-events: none;
    opacity: 0.75;
    position: relative;
}

.btn.is-loading::after {
    content: '';
    position: absolute;
    width: 14px;
    height: 14px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: ff-spin 0.6s linear infinite;
}

@keyframes ff-spin {
    to { transform: rotate(360deg); }
}


/* ============================================================
   09. Badges & Status Chips
   ============================================================ */

.badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: var(--radius-full);
    font-size: 0.75rem;
    font-weight: 600;
    white-space: nowrap;
    line-height: 1.5;
}

.badge-primary  { background: var(--color-primary-light);  color: var(--color-primary-text);  }
.badge-success  { background: var(--color-success-light);  color: var(--color-success-text);  }
.badge-warning  { background: var(--color-warning-light);  color: var(--color-warning-text);  }
.badge-danger   { background: var(--color-danger-light);   color: var(--color-danger-text);   }
.badge-info     { background: var(--color-info-light);     color: var(--color-info-text);     }
.badge-neutral  { background: var(--bg-surface-2);         color: var(--text-secondary);      border: 1px solid var(--border-color); }
.badge-purple   { background: rgba(139, 92, 246, 0.14);    color: #a78bfa;                    }

/* Dot indicator */
.badge::before {
    content: '';
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
}

.badge-no-dot::before { display: none; }

/* Lease / invoice status shorthands */
.status-active     { @extend .badge-success; }
.status-pending    { background: var(--color-warning-light); color: var(--color-warning-text); }
.status-overdue    { background: var(--color-danger-light);  color: var(--color-danger-text);  }
.status-draft      { background: var(--bg-surface-2);        color: var(--text-tertiary);       }
.status-closed     { background: var(--bg-surface-2);        color: var(--text-tertiary);       }
.status-void       { background: var(--bg-surface-2);        color: var(--text-tertiary);       }


/* ============================================================
   10. Forms
   ============================================================ */

.form-group {
    margin-bottom: 18px;
}

.form-group:last-child {
    margin-bottom: 0;
}

/* S-DESIGN-INPUTS (2026-05-03): Apple macOS aesthetic.
   Labels render in muted alpha (--label-text). Inputs are borderless
   tinted-gray pills. Focus brightens the bg and adds a 2px brand-orange
   ring via box-shadow (no border, so no layout shift on focus). */
.form-label {
    display: block;
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--label-text);
    margin-bottom: 6px;
    letter-spacing: 0.01em;
}

.form-label .required {
    color: var(--color-danger);
    margin-left: 2px;
}

/* Text inputs, selects, textareas */
/* .form-input and .form-textarea are aliases for .form-control — used in several modules */
.form-control,
.form-input,
.form-select {
    display: block;
    width: 100%;
    height: var(--input-height);
    padding: 0 12px;
    background: var(--input-bg);
    border: none;
    border-radius: 8px;
    color: var(--input-text);
    font-size: 0.9rem;
    font-family: inherit;
    line-height: 1;
    transition: background var(--transition-fast), box-shadow var(--transition-fast);
    appearance: none;
    -webkit-appearance: none;
    outline: none;
}

.form-control::placeholder,
.form-input::placeholder,
.form-select::placeholder { color: var(--input-placeholder); }

.form-control:focus,
.form-input:focus,
.form-select:focus {
    outline: none;
    background: var(--input-bg-focus);
    box-shadow: 0 0 0 2px var(--color-primary);
}

.form-control:disabled,
.form-input:disabled,
.form-select:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Invalid state — danger ring via box-shadow (no border to color). */
.form-control.is-invalid,
.form-input.is-invalid,
.form-select.is-invalid {
    box-shadow: 0 0 0 2px var(--color-danger);
}

.form-control.is-invalid:focus,
.form-input.is-invalid:focus,
.form-select.is-invalid:focus {
    box-shadow: 0 0 0 2px var(--color-danger);
}

.form-control-sm,
.form-input-sm   { height: var(--input-height-sm); font-size: 0.8125rem; padding: 0 10px; }
.form-control-lg { height: var(--input-height-lg); font-size: 1rem; padding: 0 14px; }
.form-select-sm  { height: var(--input-height-sm); font-size: 0.8125rem; padding: 0 10px; padding-right: 32px; }

/* Select arrow */
.form-select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.5' stroke='%2394a3b8'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='m19.5 8.25-7.5 7.5-7.5-7.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 16px;
    padding-right: 36px;
}

/* Textarea */
textarea.form-control,
textarea.form-input {
    height: auto;
    min-height: 100px;
    padding: 10px 12px;
    resize: vertical;
    line-height: 1.5;
}

/* Form hint / helper text */
.form-hint {
    margin-top: 5px;
    font-size: 0.8125rem;
    color: var(--text-tertiary);
}

.form-error {
    margin-top: 5px;
    font-size: 0.8125rem;
    color: var(--color-danger-text);
}

/* ============================================================
   VALID-2 — Field-level + form-level validation messaging
   ============================================================
   .field-error          per-input error shown directly below
   .form-error-banner    form-level banner (e.g. unbalanced JE)
   .form-control.ff-invalid  same as .is-invalid, added by FF_Validate
   ============================================================ */
.field-error {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin-top: 5px;
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--color-danger-text);
    line-height: 1.4;
}
.field-error .icon {
    flex-shrink: 0;
    font-size: 0.9375rem;
    line-height: 1;
    margin-top: 1px;
}
.field-error:empty { display: none; }

.form-error-banner {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 16px;
    margin-bottom: 16px;
    background: var(--badge-danger-bg);
    color: var(--badge-danger-text);
    border: 1px solid rgba(220, 38, 38, 0.3);
    border-radius: var(--radius-md);
    font-size: 0.875rem;
    line-height: 1.5;
}
.form-error-banner strong { font-weight: 600; }
.form-error-banner .icon {
    flex-shrink: 0;
    font-size: 1.125rem;
    line-height: 1;
    margin-top: 1px;
}
.form-error-banner:empty { display: none; }

.form-control.ff-invalid,
.form-input.ff-invalid,
.form-select.ff-invalid {
    box-shadow: 0 0 0 2px var(--color-danger);
}

/* Inline alert banners — used in forms and modals */
.alert {
    padding: 12px 16px;
    border-radius: var(--radius-md);
    font-size: 0.875rem;
    line-height: 1.5;
    border: 1px solid transparent;
}
.alert-danger  { background: var(--badge-danger-bg);  color: var(--badge-danger-text);  border-color: rgba(220,38,38,0.25); }
.alert-success { background: var(--badge-success-bg); color: var(--badge-success-text); border-color: rgba(22,163,74,0.25); }
.alert-warning { background: var(--badge-warning-bg); color: var(--badge-warning-text); border-color: rgba(217,119,6,0.25); }
.alert-info    { background: var(--badge-info-bg);    color: var(--badge-info-text);    border-color: rgba(8,145,178,0.25); }

/* Checkbox & Radio */
.form-check {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    cursor: pointer;
}

.form-check-input {
    width: 16px;
    height: 16px;
    border: 2px solid var(--input-border);
    border-radius: var(--radius-sm);
    background: var(--input-bg);
    cursor: pointer;
    flex-shrink: 0;
    margin-top: 2px;
    accent-color: var(--color-primary);
    transition: border-color var(--transition-fast);
}

.form-check-input[type="radio"] { border-radius: 50%; }

.form-check-input:checked { border-color: var(--color-primary); }

.form-check-label {
    font-size: 0.9rem;
    color: var(--text-primary);
    cursor: pointer;
    line-height: 1.4;
}

/* Form row / grid */
.form-row {
    display: grid;
    gap: 16px;
}

.form-row-2 { grid-template-columns: 1fr 1fr; }
.form-row-3 { grid-template-columns: 1fr 1fr 1fr; }
.form-row-4 { grid-template-columns: 1fr 1fr 1fr 1fr; }

/* Input with icon prefix */
.input-group {
    position: relative;
    display: flex;
    align-items: stretch;
}

/* S-DESIGN-INPUTS: prefix/suffix render as part of one continuous Apple
   pill with the input — same bg, no border, joined radii. */
.input-group-prefix,
.input-group-suffix {
    display: flex;
    align-items: center;
    padding: 0 12px;
    background: var(--input-bg);
    border: none;
    color: var(--text-secondary);
    font-size: 0.875rem;
    white-space: nowrap;
    flex-shrink: 0;
}

.input-group-prefix {
    border-radius: 8px 0 0 8px;
}

.input-group-suffix {
    border-radius: 0 8px 8px 0;
}

.input-group .form-control {
    flex: 1;
    border-radius: 0;
}

.input-group:has(.input-group-prefix) .form-control { border-radius: 0 8px 8px 0; }
.input-group:has(.input-group-suffix) .form-control { border-radius: 8px 0 0 8px; }
.input-group:has(.input-group-prefix):has(.input-group-suffix) .form-control { border-radius: 0; }


/* ============================================================
   11. Tables
   ============================================================ */

.table-wrapper {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-radius: var(--radius-xl);
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-sm);
}

.table,
.data-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
    background: var(--bg-surface);
}

.table thead th,
.data-table thead th {
    padding: 12px 16px;
    text-align: left;
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-tertiary);
    background: var(--bg-surface-2);
    border-bottom: 1px solid var(--border-color);
    white-space: nowrap;
}

.table thead th:first-child,
.data-table thead th:first-child { border-radius: var(--radius-xl) 0 0 0; }
.table thead th:last-child,
.data-table thead th:last-child  { border-radius: 0 var(--radius-xl) 0 0; }

.table tbody tr,
.data-table tbody tr {
    border-bottom: 1px solid var(--border-color);
    transition: background var(--transition-fast);
}

.table tbody tr:last-child,
.data-table tbody tr:last-child { border-bottom: none; }

.table tbody tr:hover,
.data-table tbody tr:hover {
    background: var(--bg-surface-hover);
}

.table tbody td,
.data-table tbody td {
    padding: 13px 16px;
    color: var(--text-primary);
    vertical-align: middle;
}

.table .text-right,
.table th.text-right,
.table td.text-right,
.data-table .text-right,
.data-table th.text-right,
.data-table td.text-right { text-align: right; }

.table .text-center,
.table th.text-center,
.table td.text-center,
.data-table .text-center,
.data-table th.text-center,
.data-table td.text-center { text-align: center; }

/* Sortable column header */
.th-sortable {
    cursor: pointer;
    user-select: none;
}

.th-sortable:hover { color: var(--text-primary); }

/* Table toolbar (search + filters + actions) */
.table-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 16px;
    flex-wrap: wrap;
}

.table-toolbar-left,
.table-toolbar-right {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

/* Pagination */
.pagination {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-top: 1px solid var(--border-color);
    font-size: 0.875rem;
    color: var(--text-secondary);
    flex-wrap: wrap;
    gap: 12px;
}

.pagination-info { white-space: nowrap; }

.pagination-controls {
    display: flex;
    align-items: center;
    gap: 4px;
}

.page-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 32px;
    height: 32px;
    padding: 0 6px;
    border-radius: var(--radius-md);
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--text-secondary);
    background: transparent;
    border: 1px solid transparent;
    cursor: pointer;
    transition: background var(--transition-fast), color var(--transition-fast);
}

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

.page-btn.is-active {
    background: var(--color-primary);
    color: #ffffff;
    border-color: var(--color-primary);
}

.page-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}


/* ============================================================
   12. Modals
   ============================================================ */

.modal-overlay {
    position: fixed;
    inset: 0;
    z-index: var(--z-modal);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}

/* ============================================================
   FF_LookupPicker — searchable dropdown w/ manual-entry fallback
   ============================================================ */
.ff-picker {
    position: relative;
}
.ff-picker-input-wrap {
    position: relative;
    display: flex;
    align-items: center;
    gap: 6px;
}
.ff-picker-input {
    flex: 1;
    min-width: 0;
}
.ff-picker-toggle {
    flex: 0 0 auto;
    padding: 4px 8px;
    font-size: 0.7rem;
    border-radius: var(--radius-sm);
    background: var(--bg-surface-2);
    border: 1px solid var(--border-color);
    color: var(--text-secondary);
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--transition-fast), color var(--transition-fast);
}
.ff-picker-toggle:hover {
    background: var(--bg-surface);
    color: var(--text-primary);
}
.ff-picker-toggle--active {
    background: var(--accent-color, #2563eb);
    color: #fff;
    border-color: var(--accent-color, #2563eb);
}
.ff-picker-clear {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    background: transparent;
    border: none;
    color: var(--text-tertiary);
    cursor: pointer;
    font-size: 1rem;
    line-height: 1;
    padding: 2px 6px;
}
.ff-picker-clear:hover { color: var(--text-primary); }
.ff-picker-dropdown {
    position: absolute;
    z-index: 10;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    max-height: 260px;
    overflow-y: auto;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
}
.ff-picker-item {
    padding: 8px 12px;
    font-size: 0.825rem;
    cursor: pointer;
    border-bottom: 1px solid var(--border-color);
    transition: background var(--transition-fast);
}
.ff-picker-item:last-child { border-bottom: none; }
.ff-picker-item:hover,
.ff-picker-item--highlight {
    background: var(--bg-surface-2);
}
.ff-picker-empty {
    padding: 10px 12px;
    font-size: 0.8125rem;
    color: var(--text-tertiary);
    text-align: center;
}
.ff-picker-loading {
    padding: 10px 12px;
    font-size: 0.8125rem;
    color: var(--text-secondary);
    text-align: center;
}
.ff-picker-selected-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 8px;
    background: var(--bg-surface-2);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-full);
    font-size: 0.7rem;
    color: var(--text-secondary);
    margin-top: 4px;
}

/*
 * .modal-backdrop serves double-duty: dark overlay + flex centering
 * container for the .modal child. Most accounting pages use this class
 * directly without a wrapping .modal-overlay. Bumping z-index from 0
 * → var(--z-modal) ensures it sits above sidebar (40) + topbar (30);
 * flex centering keeps the modal in viewport regardless of viewport
 * width or sidebar state.
 */
.modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.70);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    z-index: var(--z-modal);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}

.modal {
    position: relative;
    background: var(--bg-surface);
    border-radius: var(--radius-xl);
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-xl);
    width: 100%;
    max-width: 560px;
    max-height: calc(100vh - 48px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    /* Must sit ABOVE a sibling .modal-backdrop. Commit d43649d raised
       .modal-backdrop from z-index:0 to var(--z-modal) (60) to center the
       child-pattern accounting modals (.modal-backdrop > .modal). But the
       sibling-pattern modals (.modal-overlay > [.modal-backdrop, .modal] —
       the global email-compose modal + the footer confirm modal) then had
       the blurred backdrop (60) painting OVER the panel (old z-index:2),
       so the whole modal rendered blurred. calc(var(--z-modal) + 1) lifts
       the panel above the backdrop in the sibling case; child-pattern
       modals are unaffected (a child always paints above its parent's
       backdrop-filter regardless of z-index). */
    z-index: calc(var(--z-modal) + 1);
}

.modal-sm   { max-width: 420px; }
.modal-md   { max-width: 560px; }                           /* FIX #29 */
.modal-lg   { max-width: 720px; }
.modal-full { max-width: min(90vw, 1100px); }               /* FIX #29 */
.modal-xl   { max-width: 960px; }

.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 18px 20px 16px;
    border-bottom: 1px solid var(--border-color);
    flex-shrink: 0;
}

.modal-title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--text-primary);
    margin: 0;
}

.modal-close-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: var(--radius-md);
    color: var(--text-tertiary);
    background: transparent;
    border: none;
    cursor: pointer;
    flex-shrink: 0;
    transition: background var(--transition-fast), color var(--transition-fast);
}

.modal-close-btn:hover {
    background: var(--bg-surface-2);
    color: var(--text-primary);
}

.modal-body {
    padding: 20px;
    overflow-y: auto;
    flex: 1;
}

.modal-footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    padding: 14px 20px;
    border-top: 1px solid var(--border-color);
    background: var(--bg-surface-2);
    flex-shrink: 0;
}

/* Modal entry animation (used by Alpine x-transition) */
.modal-enter {
    transition: opacity 180ms ease, transform 180ms ease;
}
.modal-enter-start {
    opacity: 0;
    transform: scale(0.96) translateY(8px);
}
.modal-enter-end {
    opacity: 1;
    transform: scale(1) translateY(0);
}
.modal-leave {
    transition: opacity 130ms ease, transform 130ms ease;
}
.modal-leave-start {
    opacity: 1;
    transform: scale(1);
}
.modal-leave-end {
    opacity: 0;
    transform: scale(0.96);
}


/* ============================================================
   13. Toast Notifications
   ============================================================ */

/* Position: fixed top-right, 16px from edges (spec §5) */
#ff-toast-container {
    position: fixed;
    top: 16px;
    right: 16px;
    z-index: var(--z-toast);
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-width: 360px;
    width: 100%;
    pointer-events: none;
}

.toast {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 14px 16px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    pointer-events: all;
    transition: opacity 250ms ease, transform 250ms ease;
    animation: toast-in 250ms ease forwards;
}

@keyframes toast-in {
    from { opacity: 0; transform: translateX(24px); }
    to   { opacity: 1; transform: translateX(0); }
}

.toast.is-leaving {
    animation: toast-out 200ms ease forwards;
}

@keyframes toast-out {
    from { opacity: 1; transform: translateX(0); max-height: 100px; }
    to   { opacity: 0; transform: translateX(24px); max-height: 0; margin: 0; padding: 0; }
}

.toast-icon {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    margin-top: 1px;
}

.toast-body {
    flex: 1;
    min-width: 0;
}

.toast-title {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-primary);
    line-height: 1.3;
}

.toast-message {
    font-size: 0.8125rem;
    color: var(--text-secondary);
    margin-top: 2px;
    line-height: 1.4;
}

.toast-close {
    color: var(--text-tertiary);
    flex-shrink: 0;
    opacity: 0.7;
    transition: opacity var(--transition-fast);
    margin-top: 1px;
}

.toast-close:hover { opacity: 1; }

/* Colour variants — left border accent */
.toast-success { border-left: 3px solid var(--color-success); }
.toast-warning { border-left: 3px solid var(--color-warning); }
.toast-danger  { border-left: 3px solid var(--color-danger);  }
.toast-info    { border-left: 3px solid var(--color-info);    }

.toast-success .toast-icon { color: var(--color-success); }
.toast-warning .toast-icon { color: var(--color-warning); }
.toast-danger  .toast-icon { color: var(--color-danger);  }
.toast-info    .toast-icon { color: var(--color-info);    }


/* ============================================================
   14. Notification Dropdown Transitions (Alpine x-transition)
   ============================================================ */

.dropdown-enter {
    transition: opacity 150ms ease, transform 150ms ease;
}
.dropdown-enter-start {
    opacity: 0;
    transform: translateY(-6px) scale(0.98);
}
.dropdown-enter-end {
    opacity: 1;
    transform: translateY(0) scale(1);
}
.dropdown-leave {
    transition: opacity 100ms ease, transform 100ms ease;
}
.dropdown-leave-start {
    opacity: 1;
    transform: translateY(0) scale(1);
}
.dropdown-leave-end {
    opacity: 0;
    transform: translateY(-6px) scale(0.98);
}


/* ============================================================
   14b. Accounting Sub-Navigation Bar (acc-topnav)
   ============================================================
   Grouped horizontal nav rendered by includes/partials/accounting-nav.php
   on every accounting page. Top-level groups with sub-pages render as
   click-to-open dropdowns; standalone destinations render as direct links.

   Layout: flex row that wraps on narrow viewports.
   The "pin-right" modifier pushes Periods + Settings to the right side.

   WHY no overflow-x: per CSS spec, setting `overflow-x: auto` silently
   forces `overflow-y` to be non-visible too, which would CLIP the
   absolutely-positioned dropdown panels that sit below the bar. Since
   8 top-level items comfortably fit on any reasonable viewport, we use
   flex-wrap instead to handle edge cases without creating a clipping
   context.
   ============================================================ */

/* ── Container — frosted-pill shelf housing the buttons ────────────
   Apple-style depth: 1px inset highlight on top edge + soft drop
   shadow underneath gives the bar a sense of physical lift, while a
   subtle vertical gradient suggests light raking across the surface.
   Wrap behaviour kept (flex-wrap) so dropdowns can still escape
   vertically — but visual rhythm is restored by uniform button
   sizing and consistent row-gap. */
.acc-topnav {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px;
    row-gap: 6px;
    padding: 6px;
    margin-bottom: 20px;
    background:
        linear-gradient(180deg, rgba(255,255,255,0.025), rgba(255,255,255,0) 60%),
        var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 14px;
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.03),
        0 1px 2px rgba(0,0,0,0.18),
        0 6px 18px -10px rgba(0,0,0,0.35);
    /* overflow MUST remain visible so absolute-positioned dropdowns can escape */
    overflow: visible;
}

/* Wrapper around groups so the dropdown can be position:absolute */
.acc-topnav-group {
    position: relative;
    flex-shrink: 0;
}

/* The leaf link OR the dropdown trigger button — same luxe button skin.
   Apple-ish key-cap aesthetic: rounded squircle, subtle border that only
   reveals on hover, gentle inset top highlight on active to read as
   "depressed" rather than "tinted". Spring easing keeps interactions
   feeling tactile without being bouncy. */
.acc-topnav-link {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 8px 14px;
    border-radius: 10px;
    font-size: 0.8125rem;
    font-weight: 500;
    letter-spacing: -0.005em;
    white-space: nowrap;
    text-decoration: none;
    color: var(--text-secondary);
    /* Soft "key cap" tint so inactive tabs read as physical buttons sitting
       on the shelf — not as plain text links. The gradient is barely visible
       on top of bg-card; just enough to suggest a beveled surface. */
    background: linear-gradient(180deg,
        rgba(255,255,255,0.045),
        rgba(255,255,255,0) 65%
    );
    border: 1px solid rgba(255,255,255,0.04);
    cursor: pointer;
    transition:
        background 220ms cubic-bezier(0.23, 1, 0.32, 1),
        color     180ms ease,
        border-color 180ms ease,
        box-shadow 220ms cubic-bezier(0.23, 1, 0.32, 1),
        transform 120ms ease;
    flex-shrink: 0;
    font-family: inherit;
    line-height: 1.2;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.025);
}
.acc-topnav-link:hover {
    background: linear-gradient(180deg,
        rgba(255,255,255,0.085),
        rgba(255,255,255,0.015) 65%
    );
    border-color: rgba(255,255,255,0.09);
    color: var(--text-primary);
    text-decoration: none;
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.05),
        0 1px 2px rgba(0,0,0,0.2);
}
.acc-topnav-link:active {
    transform: scale(0.97);
    transition-duration: 80ms;
}
.acc-topnav-link svg {
    flex-shrink: 0;
    color: currentColor;
    opacity: 0.9;
}

/* Active state — applies to both leaf links and group triggers.
   The "lit key" treatment: brand fill, top-edge inset highlight that
   reads as a glass dome, and a soft outer shadow that lifts the button
   off the shelf. */
.acc-topnav-link.acc-topnav-active {
    background:
        linear-gradient(180deg, rgba(255,255,255,0.12), rgba(255,255,255,0) 55%),
        var(--color-primary);
    color: #fff;
    border-color: transparent;
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.22),
        inset 0 -1px 0 rgba(0,0,0,0.08),
        0 1px 2px rgba(0,0,0,0.20),
        0 4px 10px -4px var(--color-primary);
    font-weight: 600;
}
.acc-topnav-link.acc-topnav-active:hover {
    background:
        linear-gradient(180deg, rgba(255,255,255,0.14), rgba(255,255,255,0) 55%),
        var(--color-primary-hover, var(--color-primary));
    color: #fff;
}
.acc-topnav-link.acc-topnav-active svg { opacity: 1; }

/* Dropdown trigger — button is open but page is NOT the active section */
.acc-topnav-link.acc-topnav-open:not(.acc-topnav-active) {
    background: var(--bg-surface-2);
    border-color: var(--border-color);
    color: var(--text-primary);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.04);
}

/* Right-pinned items (Periods, Settings).
   pin-right only when the bar is wide enough to fit on a single row.
   On wrapped layouts the auto-margin creates an awkward gap that the
   user reads as "items thrown about" — drop it under the wrap
   threshold so wrapped buttons flow with consistent rhythm. */
.acc-topnav-pin-right {
    margin-left: auto;
}
/* When two items are both pin-right, only the first needs auto margin */
.acc-topnav-pin-right ~ .acc-topnav-pin-right {
    margin-left: 0;
}
@media (max-width: 1100px) {
    .acc-topnav-pin-right,
    .acc-topnav-pin-right ~ .acc-topnav-pin-right {
        margin-left: 0;
    }
}

/* ── Mobile layout: a uniform 2-column grid of equal buttons ───────
   On narrow viewports flex-wrap creates uneven columns because button
   widths vary (Dashboard is short, "General Ledger ▾" is long). The
   result is a ragged grid that reads as "thrown together." Switching
   to CSS Grid with 2 equal columns gives every button the same width
   and a clean rhythm — the bar reads as a deliberate control panel.

   .acc-topnav-group wraps button+dropdown, so it must stretch its
   button to 100% width to fill the grid cell.  */
@media (max-width: 767px) {
    .acc-topnav {
        display: grid !important;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 6px;
        padding: 8px;
    }
    .acc-topnav-group { width: 100%; min-width: 0; }
    .acc-topnav-link {
        width: 100%;
        justify-content: flex-start;
        padding: 10px 10px;
        gap: 6px;
        min-width: 0;
        font-size: 0.75rem;
    }
    /* Icon stays present but slightly smaller — preserves visual rhythm
       (every cell has icon + label + optional chevron) without eating
       label width when labels are long like "General Ledger". */
    .acc-topnav-link > svg {
        width: 14px;
        height: 14px;
    }
    /* Hide the chevron caret on mobile so the label always has room.
       The dropdown still opens on tap; users discover it by tapping
       the button itself (matches the iOS pattern of icon+label tabs
       without secondary affordances). */
    .acc-topnav-chevron { display: none !important; }
    /* Truncate long labels with ellipsis instead of clipping the chevron */
    .acc-topnav-link > span:not(.acc-topnav-chevron) {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        min-width: 0;
        flex: 1 1 auto;
    }
    /* Drop pin-right entirely on mobile — every cell is the same. */
    .acc-topnav-pin-right { margin-left: 0; }
    /* Dropdown panels stretch to viewport width on mobile so labels
       are readable even with long item names. */
    .acc-topnav-dropdown {
        min-width: 75vw;
        max-width: calc(100vw - 24px);
    }
    /* Chevron sits flush right inside the wide button. */
    .acc-topnav-chevron {
        margin-left: auto;
        padding-left: 4px;
        flex-shrink: 0;
    }
}

/* Chevron caret next to dropdown trigger labels */
.acc-topnav-chevron {
    display: inline-flex;
    align-items: center;
    margin-left: 1px;
    transition: transform 240ms cubic-bezier(0.23, 1, 0.32, 1);
    opacity: 0.55;
}
.acc-topnav-link:hover .acc-topnav-chevron { opacity: 0.85; }
.acc-topnav-link.acc-topnav-active .acc-topnav-chevron { opacity: 0.9; }
.acc-topnav-chevron-open {
    transform: rotate(180deg);
}

/* Dropdown panel — same shadow/radius treatment as other dropdowns */
.acc-topnav-dropdown {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    min-width: 220px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-xl);
    z-index: var(--z-dropdown);
    padding: 6px 0;
    overflow: hidden;
}
/* Right-pinned dropdowns flush right so they don't overflow off-screen */
.acc-topnav-pin-right .acc-topnav-dropdown {
    left: auto;
    right: 0;
}

.acc-topnav-dropdown-label {
    padding: 6px 14px 4px;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-tertiary);
    margin: 0;
}

.acc-topnav-dropdown-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 14px;
    font-size: 0.875rem;
    color: var(--text-primary);
    text-decoration: none;
    transition: background var(--transition-fast);
    line-height: 1.2;
}
.acc-topnav-dropdown-item:hover {
    background: var(--bg-surface-hover);
    text-decoration: none;
    color: var(--text-primary);
}
.acc-topnav-dropdown-item svg {
    color: var(--text-secondary);
    flex-shrink: 0;
}

/* Active child highlight inside an open dropdown */
.acc-topnav-dropdown-item.acc-topnav-dropdown-item-active {
    background: var(--color-primary-light, rgba(249, 115, 22, 0.12));
    color: var(--color-primary-text, var(--color-primary));
    font-weight: 600;
}
.acc-topnav-dropdown-item.acc-topnav-dropdown-item-active svg {
    color: var(--color-primary-text, var(--color-primary));
}

/* x-cloak hides Alpine elements until Alpine has finished initialising */
[x-cloak] { display: none !important; }


/* ============================================================
   15. Global Search Modal
   ============================================================ */

.search-modal {
    position: fixed;
    inset: 0;
    z-index: var(--z-modal);
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding-top: 80px;
}

.search-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}

.search-panel {
    position: relative;
    width: 100%;
    max-width: 600px;
    background: var(--bg-surface);
    border-radius: var(--radius-xl);
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-xl);
    overflow: hidden;
    z-index: 1;
}

.search-input-wrap {
    display: flex;
    align-items: center;
    padding: 0 16px;
    border-bottom: 1px solid var(--border-color);
    gap: 12px;
}

.search-panel-icon {
    width: 18px;
    height: 18px;
    color: var(--text-tertiary);
    flex-shrink: 0;
}

.search-input {
    flex: 1;
    height: 52px;
    border: none;
    background: transparent;
    color: var(--text-primary);
    font-size: 1rem;
    font-family: inherit;
    outline: none;
}

.search-input::placeholder { color: var(--text-tertiary); }

.search-esc-hint {
    flex-shrink: 0;
    font-family: 'DM Mono', monospace;
    font-size: 0.75rem;
    padding: 2px 6px;
    background: var(--bg-surface-2);
    border: 1px solid var(--border-color-strong);
    border-radius: var(--radius-sm);
    color: var(--text-tertiary);
    box-shadow: 0 1px 0 var(--border-color-strong);
}

.search-results {
    max-height: 400px;
    overflow-y: auto;
}

/* Search result items — rendered by app.js */
.search-result-group-label {
    padding: 10px 16px 4px;
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text-tertiary);
}

.search-result-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 16px;
    cursor: pointer;
    text-decoration: none;
    color: var(--text-primary);
    transition: background var(--transition-fast);
}

.search-result-item:hover,
.search-result-item.is-focused {
    background: var(--bg-surface-hover);
    text-decoration: none;
}

.search-result-icon {
    width: 32px;
    height: 32px;
    border-radius: var(--radius-md);
    background: var(--bg-surface-2);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    color: var(--text-secondary);
}

.search-result-icon svg { width: 16px; height: 16px; }

.search-result-body { flex: 1; min-width: 0; }

.search-result-title {
    font-size: 0.9rem;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.search-result-meta {
    font-size: 0.8125rem;
    color: var(--text-tertiary);
}

.search-recent {
    padding: 8px 0;
}

.search-empty {
    padding: 32px 16px;
    text-align: center;
    color: var(--text-tertiary);
    font-size: 0.9rem;
}


/* ============================================================
   16. Skeleton Loaders
   ============================================================ */

@keyframes ff-shimmer {
    0%   { background-position: -400px 0; }
    100% { background-position: 400px 0; }
}

.skeleton {
    background: linear-gradient(
        90deg,
        var(--bg-surface-2) 25%,
        var(--bg-surface-hover) 50%,
        var(--bg-surface-2) 75%
    );
    background-size: 800px 100%;
    animation: ff-shimmer 1.4s ease infinite;
    border-radius: var(--radius-sm);
}

.skeleton-text {
    height: 14px;
    border-radius: var(--radius-sm);
    margin-bottom: 8px;
}

.skeleton-text:last-child { margin-bottom: 0; }
.skeleton-text-sm { height: 11px; }
.skeleton-text-lg { height: 20px; }

.skeleton-title {
    height: 22px;
    width: 60%;
    margin-bottom: 12px;
    border-radius: var(--radius-sm);
}

.skeleton-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    flex-shrink: 0;
}

.skeleton-btn {
    height: 36px;
    width: 100px;
    border-radius: var(--radius-md);
}

/* Table row skeleton */
.skeleton-row {
    display: grid;
    align-items: center;
    gap: 16px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--border-color);
}


/* ============================================================
   17. Utilities
   ============================================================ */

/* Spacing */
.mt-0  { margin-top: 0; }       .mb-0  { margin-bottom: 0; }
.mt-1  { margin-top: 4px; }     .mb-1  { margin-bottom: 4px; }
.mt-2  { margin-top: 8px; }     .mb-2  { margin-bottom: 8px; }
.mt-3  { margin-top: 12px; }    .mb-3  { margin-bottom: 12px; }
.mt-4  { margin-top: 16px; }    .mb-4  { margin-bottom: 16px; }
.mt-5  { margin-top: 20px; }    .mb-5  { margin-bottom: 20px; }
.mt-6  { margin-top: 24px; }    .mb-6  { margin-bottom: 24px; }

.gap-1 { gap: 4px; }   .gap-2 { gap: 8px; }   .gap-3 { gap: 12px; }
.gap-4 { gap: 16px; }  .gap-5 { gap: 20px; }  .gap-6 { gap: 24px; }

/* Flex */
.d-flex         { display: flex; }
.flex-col       { flex-direction: column; }
.flex-wrap      { flex-wrap: wrap; }
.align-center   { align-items: center; }
.align-start    { align-items: flex-start; }
.justify-center { justify-content: center; }
.justify-end    { justify-content: flex-end; }
.justify-between { justify-content: space-between; }
.flex-1         { flex: 1; min-width: 0; }

/* Grid */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px; }

/* Text */
.text-left    { text-align: left; }
.text-center  { text-align: center; }
.text-right   { text-align: right; }
.font-mono    { font-family: 'DM Mono', monospace; }
.font-medium  { font-weight: 500; }
.font-semibold { font-weight: 600; }
.font-bold    { font-weight: 700; }
.truncate     { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Display */
.d-none   { display: none !important; }
.d-block  { display: block !important; }
.invisible { visibility: hidden; }

/* Misc */
.w-full   { width: 100%; }
.mw-none  { max-width: none; }
.rounded  { border-radius: var(--radius-md); }
.rounded-lg { border-radius: var(--radius-lg); }
.rounded-full { border-radius: var(--radius-full); }
.shadow   { box-shadow: var(--shadow-sm); }
.border   { border: 1px solid var(--border-color); }
.divider  { border-top: 1px solid var(--border-color); margin: 16px 0; }

/* Currency / number display */
.currency {
    font-family: 'DM Mono', monospace;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Empty state */
.empty-state {
    text-align: center;
    padding: 48px 24px;
    color: var(--text-tertiary);
}

.empty-state-icon {
    width: 48px;
    height: 48px;
    margin: 0 auto 16px;
    opacity: 0.4;
}

.empty-state-title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--text-secondary);
    margin-bottom: 6px;
}

.empty-state-text {
    font-size: 0.875rem;
    margin-bottom: 20px;
}

/* Focus visible — global accessible focus ring */
:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 2px;
}


/* ============================================================
   18. Alpine.js Helpers & Transitions
   ============================================================ */

/* Hide elements until Alpine initialises — prevents flash */
[x-cloak] { display: none !important; }

/* Smooth tab/panel transitions — used by Alpine x-transition:enter (x-show)
   and .ff-tab-animated keyframe animation (x-if template insertion) */
.ff-tab-enter        { transition: opacity 120ms ease-out; }
.ff-tab-enter-from   { opacity: 0; }
.ff-tab-enter-to     { opacity: 1; }

@keyframes ff-tab-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.ff-tab-animated { animation: ff-tab-fade-in 120ms ease-out; }

/* Icon placeholder when SVG file not found */
.icon-missing {
    display: inline-block;
    width: 18px;
    height: 18px;
    background: var(--bg-surface-2);
    border-radius: var(--radius-sm);
    vertical-align: middle;
}

/* Generic fade transition used by Alpine */
.fade-enter { transition: opacity 200ms ease; }
.fade-enter-start { opacity: 0; }
.fade-enter-end   { opacity: 1; }
.fade-leave       { transition: opacity 150ms ease; }
.fade-leave-start { opacity: 1; }
.fade-leave-end   { opacity: 0; }

/* Slide-down */
.slide-down-enter { transition: opacity 200ms ease, transform 200ms ease; }
.slide-down-enter-start { opacity: 0; transform: translateY(-8px); }
.slide-down-enter-end   { opacity: 1; transform: translateY(0); }
.slide-down-leave       { transition: opacity 150ms ease, transform 150ms ease; }
.slide-down-leave-start { opacity: 1; transform: translateY(0); }
.slide-down-leave-end   { opacity: 0; transform: translateY(-8px); }


/* ============================================================
   19. Responsive / Mobile
   ============================================================ */

@media (max-width: 1023px) {
    /* On mobile, sidebar becomes a fixed overlay */
    .sidebar {
        position: fixed;
        top: 0;
        left: 0;
        height: 100%;
        transform: translateX(-100%);
        transition: transform var(--transition-slow), width var(--transition-slow);
        width: var(--sidebar-width);
    }

    .sidebar.is-open {
        transform: translateX(0);
        box-shadow: var(--shadow-xl);
    }

    /* App main takes full width on mobile */
    .app-main {
        width: 100%;
    }

    /* S-MOBILE-CHROME-CLEANUP: removed the .topbar-menu-btn display
       override here. The legacy menu button stays display:none across
       all breakpoints — .hamburger-btn (declared at line ~5608) is the
       sole topbar hamburger and is visible only at <768px. On tablet
       (768-1023) the sidebar is a permanent 64px rail so no toggle is
       needed; on desktop the sidebar's own .sidebar-collapse-btn
       (chevron) handles the open/collapsed toggle. */

    /* Search hint text condensed on mobile */
    .search-hint span:not(.search-kbd) {
        display: none;
    }

    /* Full-width search modal on small screens */
    .search-modal { padding: 0; align-items: flex-start; }
    .search-panel { border-radius: 0 0 var(--radius-xl) var(--radius-xl); }

    /* Page content padding reduced */
    .page-content { padding: 20px 16px; }

    /* Form row stacks on mobile */
    .form-row-2,
    .form-row-3,
    .form-row-4 { grid-template-columns: 1fr; }

    /* Grid stacks. The `> *` reset is required because some pages set
       `style="grid-column: span 2"` inline on cards that should stretch
       across both desktop columns. With grid-template-columns:1fr that
       inline span forces the browser to auto-create a second implicit
       column, breaking the stack — items end up at 50px / 253px instead
       of 100% width. Forcing every child back to grid-column:auto keeps
       the single-column stack intact. */
    .grid-2, .grid-3 { grid-template-columns: 1fr; }
    .grid-2 > *,
    .grid-3 > * { grid-column: auto !important; }

    /* Notification dropdown full width */
    .notification-dropdown {
        width: calc(100vw - 32px);
        right: -8px;
    }
}

/* Overlay backdrop when mobile sidebar is open */
.sidebar-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: calc(var(--z-sidebar) - 1);
}

@media (max-width: 1023px) {
    .sidebar-overlay.is-visible { display: block; }
}

/* Tablet adjustments */
@media (min-width: 768px) and (max-width: 1023px) {
    .form-row-2 { grid-template-columns: 1fr 1fr; }
    .grid-2     { grid-template-columns: 1fr 1fr; }
}

/* Mac-only shortcut hints */
@media (pointer: fine) {
    /* Detected via JS in app.js and class added to <html> */
}

html.is-mac .mac-only     { display: inline; }
html.is-mac .non-mac-only { display: none; }

/* Print
   PRINT-DARK-FIX: Force light-theme colors during print regardless of the
   user's `data-theme` preference. Without this override, a dark-theme user
   prints white text (--text-primary: #ffffff) onto white paper because
   Chrome's default print setting "Background graphics" is OFF — the dark
   card backgrounds are dropped but the white text stays white, leaving
   the page visually empty. We override the CSS variables themselves so
   every consumer (cards, stats, tables, headers, links) gets readable
   ink-on-paper colors automatically. */
@media print {
    /* Force light-theme palette for both :root and the dark-theme scope */
    :root,
    [data-theme="dark"] {
        --bg-body:            #ffffff !important;
        --bg-page:            #ffffff !important;
        --bg-surface:         #ffffff !important;
        --bg-surface-2:       #ffffff !important;
        --bg-card:            #ffffff !important;
        --bg-muted:           #f5f5f5 !important;
        --bg-secondary:       #ffffff !important;
        --bg-input:           #ffffff !important;
        --bg-hover:           #ffffff !important;
        --bg-selected:        #ffffff !important;
        --bg-surface-hover:   #ffffff !important;

        --text-primary:       #000000 !important;
        --text-secondary:     #333333 !important;
        --text-tertiary:      #555555 !important;
        --text-muted:         #555555 !important;
        --text-disabled:      #888888 !important;
        --text-inverse:       #ffffff !important;

        --border-color:        #cccccc !important;
        --border-color-strong: #999999 !important;
        --border-strong:       #999999 !important;
    }

    /* Force every element to ink-on-paper colors as a defensive backstop
       for elements that hard-code white text (e.g. inline `style="color:#fff"`)
       or that override --text-primary. Then individual selectors below
       restore brand accents that should remain coloured. */
    html, body { background: #ffffff !important; color: #000000 !important; }

    /* S-INVOICE-DISPLAY-COMPREHENSIVE T1 fix (2026-05-11): extend hide list
       with global overlay containers. The `.search-modal` modal is rendered
       on every admin page via includes/footer.php and uses Alpine x-show to
       toggle visibility. If the modal is open at print time (or Alpine fails
       to fire before print captures the DOM), its `.search-overlay` child
       paints rgba(0,0,0,0.5) over the entire viewport, producing a dark
       semi-transparent overlay across the printed invoice. Same pattern
       applies to `.modal-overlay` (void/delete/confirm/email modals via
       footer.php) and `.modal-backdrop` (child element). The `.sidebar-overlay`
       is the mobile sidebar dim — only painted when the sidebar is open at
       print time. Hide all of them defensively — they should never appear
       on a printed billing artifact. */
    .sidebar, .topbar, #ff-toast-container, .chat-widget,
    .search-modal, .search-overlay,
    .modal-overlay, .modal-backdrop,
    .sidebar-overlay { display: none !important; }
    .app-main { margin-left: 0 !important; }
    .page-content { padding: 0; }
    .card { border: 1px solid #ccc; box-shadow: none !important; background: #ffffff !important; color: #000000 !important; }

    /* PRINT-TABLE-FIX: Force tables back to proper table layout.
       WHY: app.js auto-adds .table-stack to every table in the app so that
       on mobile (max-width:767px) each row renders as a stacked label/value
       card. But when the browser prints to letter paper, the paper width
       (~720px after ~0.5in margins) falls BELOW the 767px breakpoint, so
       every table on every printed page collapses into a vertical stack —
       an 8-column line-items table becomes 8 block rows per item, blowing
       a one-page invoice out to four pages of wasted whitespace. Force
       display:table / table-row / table-cell in print so tables stay
       horizontal regardless of the mobile query. */
    .table-stack,
    .table-stack.table,
    table.table {
        display: table !important;
        width: 100% !important;
        border-collapse: collapse !important;
    }
    .table-stack thead, table.table thead { display: table-header-group !important; }
    .table-stack tbody, table.table tbody { display: table-row-group !important; }
    .table-stack tfoot, table.table tfoot { display: table-footer-group !important; }
    .table-stack tr, table.table tr {
        display: table-row !important;
        margin: 0 !important;
        padding: 0 !important;
        border: none !important;
        background: transparent !important;
    }
    .table-stack td, .table-stack th,
    table.table td, table.table th {
        display: table-cell !important;
        vertical-align: top !important;
    }
    /* Kill the ::before pseudo-label that table-stack uses on mobile */
    .table-stack td::before { content: none !important; display: none !important; }
    /* Undo the mobile min-width that forces horizontal scroll */
    .table-wrapper, .table-responsive { overflow: visible !important; }
    table.table, table.data-table { min-width: 0 !important; }
}

/* ============================================================
   20. Dashboard & Page-Specific Components
   ============================================================ */

/* Stat card variants */
.stat-card--link {
    cursor: pointer;
    text-decoration: none;
    display: block;
    transition: box-shadow var(--transition-base), transform var(--transition-base);
}
.stat-card--link:hover {
    box-shadow: var(--shadow-md);
    transform: translateY(-1px);
    text-decoration: none;
}
.stat-card--danger::before  { background: var(--color-danger); }
.stat-card--warning::before { background: var(--color-warning); }
.stat-card--error {
    border-left: 3px solid var(--color-danger);
    opacity: 0.7;
}

/* Inline skeleton for stat card value area */
.stat-skeleton {
    height: 32px;
    border-radius: var(--radius-sm);
    background: var(--bg-surface-2);
    animation: ff-shimmer 1.5s ease infinite;
    background-size: 800px 100%;
    background-image: linear-gradient(90deg, var(--bg-surface-2) 25%, var(--bg-surface-hover) 50%, var(--bg-surface-2) 75%);
    width: 60%;
    margin: 4px 0;
}

/* Chart loading placeholder */
.chart-skeleton {
    width: 100%;
    border-radius: var(--radius-sm);
    background: var(--bg-surface-2);
    animation: ff-shimmer 1.5s ease infinite;
    background-size: 800px 100%;
    background-image: linear-gradient(90deg, var(--bg-surface-2) 25%, var(--bg-surface-hover) 50%, var(--bg-surface-2) 75%);
}

/* 2/3 + 1/3 grid layout */
.grid-2-1 {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 24px;
}
@media (max-width: 1023px) {
    .grid-2-1 { grid-template-columns: 1fr; }
}

/* ════════════════════════════════════════════════════════════
   S-DASHBOARD-CHART-POLISH — dashboard chart + widget layout.

   Existing pages used .card with optional .card--accent-* modifiers,
   producing inconsistent 3px coloured top borders on the dashboard.
   These new classes give every chart card / widget card a uniform
   appearance and properly contain the ApexCharts SVG so it can flex
   to fit when the sidebar collapses/expands.
   ════════════════════════════════════════════════════════════ */

/* Dashboard row grid wrappers — semantic aliases over .grid-2 / .grid-2-1.
   Kept separate so dashboard.php doesn't accidentally inherit unrelated
   adjustments to those generic utility classes from other modules. */
.dashboard-grid {
    display: grid;
    gap: 20px;
}
.dashboard-grid--charts  { grid-template-columns: 2fr 1fr; gap: 20px; }
.dashboard-grid--equal   { grid-template-columns: 1fr 1fr; gap: 20px; }
.dashboard-grid--widgets { grid-template-columns: 1fr 1fr; gap: 20px; }


/* Chart card — the uniform wrapper around every chart panel.
   Flex column so card-body can fill remaining height and the chart
   inside it (.chart-wrap) can shrink past content height via min-height:0. */
.chart-card {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    background: var(--bg-card);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}
.chart-card .card-header {
    padding: 16px 20px 12px;
    border-bottom: 1px solid var(--border-color);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}
.chart-card .card-header h3,
.chart-card .card-header .card-title {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-primary);
    margin: 0;
    letter-spacing: 0;
}
.chart-card .card-body {
    flex: 1;
    display: flex;
    flex-direction: column;
    padding: 16px 20px;
}

/* Chart wrap — sits inside .card-body and holds the ApexCharts target.
   min-height:0 is the critical flex-shrink unlock that lets the chart
   reflow to a smaller width when the sidebar expands and reclaims space. */
.chart-wrap {
    flex: 1;
    min-height: 0;
    position: relative;
}
.chart-wrap > div { width: 100% !important; }

/* ApexCharts inline overflow:hidden was clipping tooltip + datalabel
   overflow into the next card. Visible at the wrap level is fine because
   the parent .chart-card already has overflow:hidden for the skeleton. */
.chart-wrap .apexcharts-canvas { overflow: visible !important; }

/* Dashboard list widgets (recent activity, pickups, etc.) — uniform shell. */
.dashboard-widget {
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    background: var(--bg-card);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}

/* ── Dashboard widget table density ───────────────────────────────
   S-DASHBOARD-CHART-POLISH (follow-up): when two widget tables sit
   side-by-side in dashboard-grid--widgets, each card only has
   ~510px of width at a 1280px viewport with the sidebar expanded.
   The default .table padding (13/16px) plus monospace contract
   numbers like "MTTS-9JJ3A-2026" push the table past that, forcing
   the .table-wrapper's overflow-x:auto scrollbar to engage.

   These rules tighten the cell metrics enough that the table fits
   natively at common viewport widths, AND make the fallback
   scrollbar visible (not the system-default near-invisible track)
   so users know to scroll when content truly doesn't fit. */
.dashboard-widget .table,
.dashboard-widget .data-table { font-size: 0.8125rem; }

.dashboard-widget .table thead th,
.dashboard-widget .data-table thead th {
    padding: 10px 12px;
    font-size: 0.625rem;
    letter-spacing: 0.06em;
}

.dashboard-widget .table tbody td,
.dashboard-widget .data-table tbody td {
    padding: 10px 12px;
}

/* Contract anchor truncation — when the column is still narrower than
   the natural mono text width, hide the trailing characters with an
   ellipsis rather than clipping from the left (which would hide the
   prefix that distinguishes "CN-…" from "MTTS-…"). */
.dashboard-widget .table tbody td .font-mono {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
}

/* Visible horizontal scrollbar inside dashboard widget tables — the
   underlying .table-wrapper already has overflow-x:auto; this styles
   the scrollbar so users can actually see they're able to scroll. */
.dashboard-widget .table-wrapper { scrollbar-width: thin; }
.dashboard-widget .table-wrapper::-webkit-scrollbar { height: 8px; }
.dashboard-widget .table-wrapper::-webkit-scrollbar-track {
    background: var(--bg-surface-2);
}
.dashboard-widget .table-wrapper::-webkit-scrollbar-thumb {
    background: var(--border-color-strong, var(--border-color));
    border-radius: 4px;
}
.dashboard-widget .table-wrapper::-webkit-scrollbar-thumb:hover {
    background: var(--text-tertiary);
}

/* Drop the trailing "View" action column when the widget sits inside
   the side-by-side dashboard-grid--widgets row. At ~510px per card the
   column gets clipped on the right; the contract number in the first
   column is already a styled link to the same detail page so the View
   button is duplicate navigation. Scoped to --widgets only so the
   full-width Active Leases table at the top of the dashboard keeps its
   per-row View button intact. */
.dashboard-grid--widgets .dashboard-widget .table thead th:last-child,
.dashboard-grid--widgets .dashboard-widget .table tbody td:last-child {
    display: none;
}

/* ── Responsive: tablet ── */
@media (max-width: 1023px) {
    .dashboard-grid--charts,
    .dashboard-grid--equal,
    .dashboard-grid--widgets { grid-template-columns: 1fr; }
}

/* ── Responsive: mobile ── */
@media (max-width: 767px) {
    .dashboard-grid { gap: 12px; }
    .chart-card .card-body { padding: 12px 14px; }
}

/* Activity feed — timeline design */
.activity-feed {
    list-style: none;
    margin: 0;
    padding: 8px 16px 4px;
}
.activity-item {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 10px 0;
    position: relative;
}
/* Vertical timeline line between items */
.activity-item:not(:last-child)::after {
    content: '';
    position: absolute;
    left: 3px;
    top: 24px;
    bottom: -4px;
    width: 2px;
    background: var(--border-color);
    opacity: 0.7;
}
.activity-dot {
    flex-shrink: 0;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    margin-top: 5px;
    position: relative;
    z-index: 1;
    box-shadow: 0 0 0 3px var(--bg-surface);
}
/* Module-specific dot colors */
.activity-dot--customers   { background: var(--color-primary); }
.activity-dot--equipment   { background: var(--color-success); }
.activity-dot--leases      { background: #8b5cf6; }
.activity-dot--invoices    { background: var(--color-warning); }
.activity-dot--payments    { background: var(--color-success); }
.activity-dot--compliance  { background: var(--color-danger); }
.activity-dot--maintenance { background: #f97316; }
.activity-dot--users       { background: #06b6d4; }
.activity-body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.activity-desc {
    font-size: 0.875rem;
    color: var(--text-primary);
    line-height: 1.4;
}
.activity-meta {
    font-size: 0.75rem;
    color: var(--text-tertiary);
}

/* Utility: padding shorthand */
.p-4 { padding: 16px; }

/* Utility: muted text color */
.text-muted { color: var(--text-tertiary); }

/* Inline hyperlink style — subtle underline so links are obvious in tables */
.link {
    color: var(--color-primary);
    text-decoration: underline;
    text-decoration-color: color-mix(in srgb, var(--color-primary) 35%, transparent);
    text-underline-offset: 2px;
    text-decoration-thickness: 1px;
    transition: text-decoration-color 0.15s;
}
.link:hover {
    text-decoration-color: var(--color-primary);
}

/* ── Tab bar — modern segmented-pill style ─────────────────
   WHY display:flex (not inline-flex): inline-flex sizes to its
   content width, so a long tab list will overflow the parent and
   stretch the page. Block-level flex respects max-width:100%.

   WHY flex-wrap:wrap (not nowrap + horizontal scroll): we'd
   rather have a long tab list flow onto a second row inside the
   same pill frame than make the user scroll a hidden region.
   row-gap gives a small breathing space between wrapped rows. */
/* ── Tab Bar — same luxe "key-cap shelf" treatment as accounting nav.
   The container is a frosted shelf; each .tab-btn renders like a
   physical button with subtle border-on-hover, inset highlight on
   active, and spring transitions for tactile feel. */
.tab-bar {
    display: flex;
    flex-wrap: wrap;
    width: 100%;
    gap: 4px;
    row-gap: 6px;
    padding: 6px;
    background:
        linear-gradient(180deg, rgba(255,255,255,0.025), rgba(255,255,255,0) 60%),
        var(--bg-surface-2);
    border: 1px solid var(--border-color);
    border-radius: 14px;
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.03),
        0 1px 2px rgba(0,0,0,0.18),
        0 6px 18px -10px rgba(0,0,0,0.35);
    margin-bottom: 1.5rem;
}

.tab-btn {
    padding: 8px 16px;
    background: linear-gradient(180deg,
        rgba(255,255,255,0.045),
        rgba(255,255,255,0) 65%
    );
    border: 1px solid rgba(255,255,255,0.04);
    border-radius: 10px;
    cursor: pointer;
    font-size: 0.8125rem;
    font-weight: 500;
    letter-spacing: -0.005em;
    white-space: nowrap;
    color: var(--text-secondary);
    transition:
        color 180ms ease,
        background 220ms cubic-bezier(0.23, 1, 0.32, 1),
        border-color 180ms ease,
        box-shadow 220ms cubic-bezier(0.23, 1, 0.32, 1),
        transform 120ms ease;
    font-family: inherit;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    position: relative;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.025);
}
.tab-btn:hover {
    color: var(--text-primary);
    background: linear-gradient(180deg,
        rgba(255,255,255,0.085),
        rgba(255,255,255,0.015) 65%
    );
    border-color: rgba(255,255,255,0.09);
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.05),
        0 1px 2px rgba(0,0,0,0.2);
}
.tab-btn:active { transform: scale(0.97); transition-duration: 80ms; }
.tab-btn.is-active,
.tab-btn[aria-selected="true"] {
    background:
        linear-gradient(180deg, rgba(255,255,255,0.12), rgba(255,255,255,0) 55%),
        var(--color-primary);
    color: #fff;
    font-weight: 600;
    border-color: transparent;
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.22),
        inset 0 -1px 0 rgba(0,0,0,0.08),
        0 1px 2px rgba(0,0,0,0.20),
        0 4px 10px -4px var(--color-primary);
}
.tab-btn.is-active:hover,
.tab-btn[aria-selected="true"]:hover {
    background:
        linear-gradient(180deg, rgba(255,255,255,0.14), rgba(255,255,255,0) 55%),
        var(--color-primary-hover, var(--color-primary));
    color: #fff;
}
.tab-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 6px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-full);
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--text-tertiary);
    transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
}
.tab-btn.is-active .tab-badge,
.tab-btn[aria-selected="true"] .tab-badge {
    background: rgba(255,255,255,0.22);
    border-color: rgba(255,255,255,0.1);
    color: #fff;
}

/* ── Breadcrumb ──────────────────────────────────────────── */
.breadcrumb {
    display: flex;
    align-items: center;
    gap: 2px;
    font-size: 0.8125rem;
    color: var(--text-tertiary);
    margin-bottom: 10px;
    flex-wrap: wrap;
}
.breadcrumb a {
    color: var(--text-secondary);
    text-decoration: none;
    padding: 2px 4px;
    border-radius: var(--radius-sm);
    transition: color var(--transition-fast), background var(--transition-fast);
}
.breadcrumb a:hover {
    color: var(--text-primary);
    background: var(--bg-surface-2);
    text-decoration: none;
}
.breadcrumb-sep {
    color: var(--text-tertiary);
    opacity: 0.4;
    font-size: 0.75rem;
    padding: 0 2px;
    user-select: none;
}
.breadcrumb-current {
    color: var(--text-primary);
    font-weight: 500;
    padding: 2px 4px;
}

/* ── Stat card icons (MODERN structure used by main dashboard) ── */
.stat-card__header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    /* WHY: shrunk 12 → 6 to match the tightened .stat-label margin
       in the legacy block above so both structures look the same. */
    margin-bottom: 6px;
    gap: 8px;
}
.stat-card__icon {
    /* WHY: shrunk 38→30 to match the legacy .stat-icon size and
       free up horizontal room for the value below. */
    width: 30px;
    height: 30px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.stat-card__icon svg { width: 16px; height: 16px; }
.stat-card__icon--primary { background: var(--color-primary-light);  color: var(--color-primary-text); }
.stat-card__icon--success { background: var(--color-success-light);  color: var(--color-success-text); }
.stat-card__icon--warning { background: var(--color-warning-light);  color: var(--color-warning-text); }
.stat-card__icon--danger  { background: var(--color-danger-light);   color: var(--color-danger-text);  }
.stat-card__icon--info    { background: var(--color-info-light);     color: var(--color-info-text);    }
.stat-card__icon--purple  { background: rgba(139,92,246,0.14);       color: #a78bfa;                   }

/* ── Chart card accent borders ───────────────────────────── */
.card--accent-primary { border-top: 3px solid var(--color-primary); }
.card--accent-success { border-top: 3px solid var(--color-success); }
.card--accent-warning { border-top: 3px solid var(--color-warning); }
.card--accent-danger  { border-top: 3px solid var(--color-danger);  }
.card--accent-info    { border-top: 3px solid var(--color-info);    }
.card--accent-purple  { border-top: 3px solid #8b5cf6;              }

/* ── Summary strip (above tables) ───────────────────────── */
.summary-strip {
    display: flex;
    align-items: center;
    gap: 0;
    margin-bottom: 14px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-xl);
    padding: 12px 20px;
    flex-wrap: wrap;
    box-shadow: var(--shadow-xs);
}
.summary-strip__item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 20px 4px 0;
    margin-right: 20px;
    border-right: 1px solid var(--border-color);
}
.summary-strip__item:last-child {
    border-right: none;
    margin-right: 0;
    padding-right: 0;
}
.summary-strip__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}
.summary-strip__value {
    font-weight: 700;
    font-family: 'DM Mono', monospace;
    color: var(--text-primary);
    font-size: 0.9375rem;
}
.summary-strip__label {
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

/* Skip navigation — WCAG 2.4.1 bypass blocks (S025) */
.skip-nav {
    position: absolute;
    top: -100%;
    left: 1rem;
    z-index: 9999;
    padding: 0.5rem 1rem;
    background: var(--color-primary, #2563eb);
    color: #fff;
    border-radius: 0 0 0.375rem 0.375rem;
    font-size: 0.875rem;
    font-weight: 600;
    text-decoration: none;
    transition: top 0.15s ease;
}
.skip-nav:focus {
    top: 0;
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* ── Utility classes ──────────────────────────────────────────── */
.line-through { text-decoration: line-through; }            /* FIX #34: void badges */
.font-mono    { font-family: 'DM Mono', monospace; }        /* FIX #33: amounts/dates */

/* ── Detail grid — labelled key/value pairs in cards (S009) ─── */
/* Used on payment show, lease show, customer show detail cards.  */
dl.detail-grid {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 6px 16px;
    margin: 0;
    font-size: 0.875rem;
    line-height: 1.5;
}
dl.detail-grid dt {
    color: var(--text-secondary);
    font-weight: 500;
    padding: 2px 0;
    white-space: nowrap;
}
dl.detail-grid dd {
    margin: 0;
    color: var(--text-primary);
    padding: 2px 0;
    word-break: break-word;
}

/* ============================================================
   SECTION 30 — CUSTOMER PORTAL STYLES (S024)
   Separate layout for customer self-service portal.
   Uses same CSS variable system as admin but with distinct layout.
   ============================================================ */

/* ── Portal Layout Shell ────────────────────────────────────── */
.portal-layout {
    display: flex;
    min-height: 100vh;
    background: var(--bg-page);
}
.portal-sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 260px;
    background: var(--bg-card);
    border-right: 1px solid var(--border-color);
    display: flex;
    flex-direction: column;
    z-index: 40;
    transition: transform 0.25s ease;
}
.portal-sidebar.is-closed {
    transform: translateX(-100%);
}
.portal-main {
    margin-left: 260px;
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    transition: margin-left 0.25s ease;
}
.portal-main.sidebar-hidden {
    margin-left: 0;
}

/* ── Portal Sidebar Brand ───────────────────────────────────── */
.portal-brand {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 20px 20px 16px;
    border-bottom: 1px solid var(--border-color);
}
.portal-brand-icon {
    width: 36px;
    height: 36px;
    border-radius: 10px;
    background: var(--color-accent);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.portal-brand-icon svg {
    width: 20px;
    height: 20px;
}
.portal-brand-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.portal-brand-name {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.portal-brand-label {
    font-size: 0.6875rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: 500;
}

/* ── Portal Sidebar Nav ─────────────────────────────────────── */
.portal-nav {
    flex: 1;
    padding: 12px 10px;
    overflow-y: auto;
}
.portal-nav-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 14px;
    border-radius: 8px;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--text-secondary);
    text-decoration: none;
    transition: all 0.15s ease;
    margin-bottom: 2px;
}
.portal-nav-item:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}
.portal-nav-item.is-active {
    background: var(--color-accent);
    color: #fff;
    font-weight: 600;
}
.portal-nav-item.is-active svg {
    opacity: 1;
}
.portal-nav-icon {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    opacity: 0.7;
}
.portal-nav-item.is-active .portal-nav-icon {
    opacity: 1;
}
.portal-nav-badge {
    margin-left: auto;
    background: var(--badge-danger-bg);
    color: var(--badge-danger-text);
    font-size: 0.6875rem;
    font-weight: 600;
    padding: 1px 7px;
    border-radius: 10px;
    min-width: 18px;
    text-align: center;
}
.portal-nav-item.is-active .portal-nav-badge {
    background: rgba(255,255,255,0.2);
    color: #fff;
}
.portal-nav-divider {
    height: 1px;
    background: var(--border-color);
    margin: 8px 14px;
}

/* ── Portal Sidebar Footer (User Section) ───────────────────── */
.portal-sidebar-footer {
    padding: 14px 16px;
    border-top: 1px solid var(--border-color);
    display: flex;
    align-items: center;
    gap: 10px;
}
.portal-user-avatar {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--color-accent);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    font-weight: 600;
    flex-shrink: 0;
}
.portal-user-info {
    flex: 1;
    min-width: 0;
}
.portal-user-name {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--text-primary);
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.portal-user-company {
    font-size: 0.6875rem;
    color: var(--text-muted);
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ── Portal Topbar ──────────────────────────────────────────── */
.portal-topbar {
    position: sticky;
    top: 0;
    z-index: 30;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 24px;
    height: 56px;
    background: var(--bg-card);
    border-bottom: 1px solid var(--border-color);
}
.portal-topbar-left {
    display: flex;
    align-items: center;
    gap: 12px;
}
.portal-topbar-title {
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--text-primary);
    margin: 0;
}
.portal-topbar-right {
    display: flex;
    align-items: center;
    gap: 8px;
}
.portal-mobile-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 8px;
    border: none;
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
}
.portal-mobile-toggle:hover {
    background: var(--bg-hover);
}
.portal-mobile-toggle svg {
    width: 22px;
    height: 22px;
}

/* ── Portal Content ─────────────────────────────────────────── */
.portal-content {
    flex: 1;
    padding: 24px;
    max-width: 1200px;
    width: 100%;
    margin: 0 auto;
}
/* S-LEGAL-FOOTER-COMMERCIAL: customer portal footer — 2-column
   commercial layout. Branding (logo + tagline + Avi attribution) on
   the left, legal + support link columns on the right, copyright +
   version pill across the bottom. Wraps to single column under 768px. */
.portal-footer {
    background: var(--bg-surface-2, #1e293b);
    border-top: 1px solid var(--border-color);
    margin-top: auto;
    color: var(--text-muted);
}
.portal-footer-inner {
    max-width: 1200px;
    margin: 0 auto;
    padding: 40px 32px 24px;
    display: flex;
    justify-content: space-between;
    gap: 40px;
    flex-wrap: wrap;
}
.portal-footer-brand   { max-width: 320px; }
.portal-footer-logo    { display: flex; align-items: center; gap: 10px; }
.portal-footer-logo-img { max-height: 40px; max-width: 200px; object-fit: contain; }
.portal-footer-name    { font-size: 1.0625rem; font-weight: 600; color: var(--text-primary); }
.portal-footer-tagline { color: var(--text-muted); font-size: 0.875rem; margin: 12px 0 4px; line-height: 1.5; }
.portal-footer-sub     { font-size: 0.75rem; color: var(--text-muted); margin: 0; }
.portal-footer-sub strong { color: var(--text-secondary); font-weight: 500; }
.portal-footer-links   { display: flex; gap: 48px; flex-wrap: wrap; }
.portal-footer-col     { display: flex; flex-direction: column; gap: 10px; min-width: 140px; }
.portal-footer-col h4  {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    margin: 0 0 4px;
}
.portal-footer-col a   {
    font-size: 0.875rem;
    color: var(--text-secondary);
    text-decoration: none;
    transition: color var(--transition-fast);
}
.portal-footer-col a:hover { color: var(--color-primary); }
.portal-footer-bottom  {
    max-width: 1200px;
    margin: 0 auto;
    padding: 16px 32px;
    border-top: 1px solid var(--border-color);
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.6875rem;
    color: var(--text-muted);
}
@media (max-width: 768px) {
    .portal-footer-inner  { flex-direction: column; padding: 32px 20px 20px; }
    .portal-footer-links  { gap: 32px; }
    .portal-footer-bottom { flex-direction: column; gap: 6px; text-align: center; padding: 14px 20px; }
}

/* ── Portal Overdue Banner ──────────────────────────────────── */
.portal-alert-banner {
    padding: 10px 24px;
    font-size: 0.8125rem;
    font-weight: 500;
    display: flex;
    align-items: center;
    gap: 8px;
}
.portal-alert-banner svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
}
.portal-alert-banner--danger {
    background: var(--badge-danger-bg);
    color: var(--badge-danger-text);
    border-bottom: 1px solid var(--color-danger);
}
.portal-alert-banner--warning {
    background: var(--badge-warning-bg);
    color: var(--badge-warning-text);
    border-bottom: 1px solid var(--color-warning);
}

/* ── Portal KPI Tiles ───────────────────────────────────────── */
.portal-kpi-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    margin-bottom: 24px;
}
.portal-kpi-card {
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    padding: 20px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    text-decoration: none;
    transition: all 0.15s ease;
    position: relative;
    overflow: hidden;
}
.portal-kpi-card:hover {
    border-color: var(--color-accent);
    box-shadow: var(--shadow-md);
    transform: translateY(-1px);
}
.portal-kpi-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
}
.portal-kpi-card--blue::before { background: var(--color-accent); }
.portal-kpi-card--green::before { background: var(--color-success); }
.portal-kpi-card--red::before { background: var(--color-danger); }
.portal-kpi-card--amber::before { background: var(--color-warning); }
.portal-kpi-card--purple::before { background: #8b5cf6; }

.portal-kpi-label {
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.portal-kpi-value {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--text-primary);
    font-family: 'DM Mono', monospace;
    line-height: 1.2;
}
.portal-kpi-sub {
    font-size: 0.75rem;
    color: var(--text-secondary);
}

/* ── Portal Section Headings ────────────────────────────────── */
.portal-section {
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    overflow: hidden;
    margin-bottom: 20px;
}
.portal-section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px;
    border-bottom: 1px solid var(--border-color);
}
.portal-section-title {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--text-primary);
    margin: 0;
    display: flex;
    align-items: center;
    gap: 8px;
}
.portal-section-title svg {
    width: 18px;
    height: 18px;
    color: var(--text-muted);
}
.portal-section-body {
    padding: 20px;
}
.portal-section-body--flush {
    padding: 0;
}

/* ── Portal Tables ──────────────────────────────────────────── */
.portal-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.8125rem;
}
.portal-table th {
    text-align: left;
    padding: 10px 16px;
    font-weight: 600;
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    background: var(--bg-muted);
    border-bottom: 1px solid var(--border-color);
    white-space: nowrap;
}
.portal-table td {
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-color);
    color: var(--text-primary);
    vertical-align: middle;
}
.portal-table tr:last-child td {
    border-bottom: none;
}
.portal-table tr:hover td {
    background: var(--bg-hover);
}
.portal-table .font-mono {
    font-family: 'DM Mono', monospace;
}
.portal-table .text-right {
    text-align: right;
}
.portal-table .text-center {
    text-align: center;
}
.portal-table-link {
    color: var(--color-accent);
    text-decoration: none;
    font-weight: 500;
}
.portal-table-link:hover {
    text-decoration: underline;
}

/* ── Portal Tab Navigation ──────────────────────────────────── */
/* WHY display:flex + flex-wrap (not inline-flex):
   inline-flex sizes to its content width and would overflow the
   viewport when the tab list is long. Block flex with wrapping
   keeps the bar inside its container and lets long tab lists
   flow onto a second row. */
.portal-tabs {
    display: flex;
    flex-wrap: wrap;
    width: 100%;
    background: var(--bg-muted);
    border-radius: 10px;
    padding: 4px;
    gap: 2px;
    row-gap: 6px;
    margin-bottom: 16px;
}
.portal-tab-btn {
    padding: 7px 16px;
    border-radius: 7px;
    border: none;
    background: transparent;
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--text-secondary);
    cursor: pointer;
    transition: all 0.15s ease;
    white-space: nowrap;
}
.portal-tab-btn:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
}
.portal-tab-btn.is-active {
    background: var(--color-accent);
    color: #fff;
    font-weight: 600;
    box-shadow: var(--shadow-sm);
}
.portal-tab-count {
    font-size: 0.6875rem;
    margin-left: 4px;
    opacity: 0.75;
}

/* ── Portal Cards Grid (Equipment) ──────────────────────────── */
.portal-cards-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: 16px;
}
.portal-equip-card {
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    padding: 20px;
    transition: all 0.15s ease;
}
.portal-equip-card:hover {
    border-color: var(--color-accent);
    box-shadow: var(--shadow-md);
}
.portal-equip-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    margin-bottom: 14px;
}
.portal-equip-unit {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text-primary);
}
.portal-equip-type {
    font-size: 0.8125rem;
    color: var(--text-secondary);
    margin-top: 2px;
}
.portal-equip-meta {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    font-size: 0.8125rem;
    margin-bottom: 14px;
}
.portal-equip-meta-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.portal-equip-meta-label {
    font-size: 0.6875rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    font-weight: 500;
}
.portal-equip-meta-value {
    font-weight: 600;
    color: var(--text-primary);
}

/* ── Mileage Progress Bar ───────────────────────────────────── */
.portal-mileage-bar {
    margin-top: 8px;
}
.portal-mileage-header {
    display: flex;
    justify-content: space-between;
    font-size: 0.75rem;
    color: var(--text-secondary);
    margin-bottom: 6px;
}
.portal-mileage-track {
    height: 8px;
    background: var(--bg-muted);
    border-radius: 4px;
    overflow: hidden;
    position: relative;
}
.portal-mileage-fill {
    height: 100%;
    border-radius: 4px;
    transition: width 0.5s ease;
    background: var(--color-success);
}
.portal-mileage-fill--warning {
    background: var(--color-warning);
}
.portal-mileage-fill--danger {
    background: var(--color-danger);
}

/* ── Portal Detail Page ─────────────────────────────────────── */
.portal-detail-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    margin-bottom: 24px;
    gap: 16px;
    flex-wrap: wrap;
}
.portal-detail-title {
    font-size: 1.375rem;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0 0 4px;
}
.portal-detail-subtitle {
    font-size: 0.875rem;
    color: var(--text-secondary);
}
.portal-detail-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}
.portal-detail-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 20px;
    margin-bottom: 24px;
}

/* ── Portal Detail Info Card ────────────────────────────────── */
.portal-info-card {
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    overflow: hidden;
}
.portal-info-card-header {
    padding: 14px 18px;
    font-weight: 600;
    font-size: 0.8125rem;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    background: var(--bg-muted);
    border-bottom: 1px solid var(--border-color);
}
.portal-info-list {
    padding: 0;
    margin: 0;
    list-style: none;
}
.portal-info-list li {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 18px;
    border-bottom: 1px solid var(--border-color);
    font-size: 0.8125rem;
}
.portal-info-list li:last-child {
    border-bottom: none;
}
.portal-info-label {
    color: var(--text-secondary);
    font-weight: 500;
}
.portal-info-value {
    color: var(--text-primary);
    font-weight: 600;
    text-align: right;
}

/* ── Portal Timeline ────────────────────────────────────────── */
.portal-timeline {
    padding: 20px;
}
.portal-timeline-item {
    display: flex;
    gap: 12px;
    padding-bottom: 20px;
    position: relative;
}
.portal-timeline-item:last-child {
    padding-bottom: 0;
}
.portal-timeline-item:not(:last-child)::after {
    content: '';
    position: absolute;
    left: 11px;
    top: 26px;
    bottom: 0;
    width: 2px;
    background: var(--border-color);
}
.portal-timeline-dot {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--bg-muted);
    border: 2px solid var(--border-color);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    z-index: 1;
}
.portal-timeline-dot svg {
    width: 12px;
    height: 12px;
    color: var(--text-muted);
}
.portal-timeline-dot--blue { border-color: var(--color-accent); background: #eff6ff; }
.portal-timeline-dot--green { border-color: var(--color-success); background: #dcfce7; }
.portal-timeline-dot--amber { border-color: var(--color-warning); background: #fef3c7; }
[data-theme="dark"] .portal-timeline-dot--blue { background: #1e2a3a; }
[data-theme="dark"] .portal-timeline-dot--green { background: #052e16; }
[data-theme="dark"] .portal-timeline-dot--amber { background: #451a03; }
.portal-timeline-content {
    flex: 1;
    min-width: 0;
}
.portal-timeline-title {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--text-primary);
}
.portal-timeline-date {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-top: 2px;
}

/* ── Portal Service Request Thread ──────────────────────────── */
.portal-thread {
    padding: 20px;
}
.portal-thread-message {
    padding: 16px;
    border-radius: 10px;
    margin-bottom: 12px;
    font-size: 0.8125rem;
    line-height: 1.6;
}
.portal-thread-message--customer {
    background: var(--bg-muted);
    margin-left: 24px;
}
.portal-thread-message--admin {
    background: #eff6ff;
    border: 1px solid #bfdbfe;
    margin-right: 24px;
}
[data-theme="dark"] .portal-thread-message--admin {
    background: #1e2a3a;
    border-color: #2e3a4a;
}
.portal-thread-author {
    font-weight: 600;
    margin-bottom: 6px;
    display: flex;
    align-items: center;
    gap: 8px;
}
.portal-thread-time {
    font-weight: 400;
    font-size: 0.75rem;
    color: var(--text-muted);
}

/* ── Portal Activity Feed ───────────────────────────────────── */
.portal-activity-list {
    padding: 0;
    margin: 0;
    list-style: none;
}
.portal-activity-item {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 20px;
    border-bottom: 1px solid var(--border-color);
    font-size: 0.8125rem;
}
.portal-activity-item:last-child {
    border-bottom: none;
}
.portal-activity-icon {
    width: 32px;
    height: 32px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.portal-activity-icon svg {
    width: 16px;
    height: 16px;
}
.portal-activity-icon--blue { background: #eff6ff; color: var(--color-accent); }
.portal-activity-icon--green { background: #dcfce7; color: var(--color-success); }
.portal-activity-icon--amber { background: #fef3c7; color: var(--color-warning); }
.portal-activity-icon--red { background: #fee2e2; color: var(--color-danger); }
[data-theme="dark"] .portal-activity-icon--blue { background: #1e2a3a; }
[data-theme="dark"] .portal-activity-icon--green { background: #052e16; }
[data-theme="dark"] .portal-activity-icon--amber { background: #451a03; }
[data-theme="dark"] .portal-activity-icon--red { background: #450a0a; }
.portal-activity-text {
    flex: 1;
    min-width: 0;
}
.portal-activity-desc {
    color: var(--text-primary);
    line-height: 1.4;
}
.portal-activity-time {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-top: 2px;
}

/* ── Portal Empty State ─────────────────────────────────────── */
.portal-empty {
    text-align: center;
    padding: 48px 20px;
}
.portal-empty svg {
    width: 48px;
    height: 48px;
    color: var(--text-muted);
    margin-bottom: 12px;
}
.portal-empty-title {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 4px;
}
.portal-empty-text {
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

/* ── Portal Login Page ──────────────────────────────────────── */
.portal-login-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-page);
    padding: 20px;
}
.portal-login-card {
    width: 100%;
    max-width: 420px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 16px;
    padding: 40px 36px;
    box-shadow: var(--shadow-lg);
}
.portal-login-brand {
    text-align: center;
    margin-bottom: 32px;
}
.portal-login-logo {
    width: 48px;
    height: 48px;
    border-radius: 12px;
    background: var(--color-accent);
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 12px;
}
.portal-login-logo svg {
    width: 26px;
    height: 26px;
}
.portal-login-title {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0 0 4px;
}
.portal-login-subtitle {
    font-size: 0.8125rem;
    color: var(--text-secondary);
    margin: 0;
}
.portal-form-group {
    margin-bottom: 16px;
}
/* S-DESIGN-INPUTS: portal mirrors admin Apple aesthetic. */
.portal-form-label {
    display: block;
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--label-text);
    margin-bottom: 6px;
    letter-spacing: 0.01em;
}
.portal-form-input {
    width: 100%;
    padding: 10px 14px;
    border: none;
    border-radius: 8px;
    font-size: 0.875rem;
    color: var(--input-text);
    background: var(--input-bg);
    transition: background 0.15s ease, box-shadow 0.15s ease;
    outline: none;
    font-family: inherit;
    box-sizing: border-box;
}
.portal-form-input:focus {
    background: var(--input-bg-focus);
    box-shadow: 0 0 0 2px var(--color-primary);
}
.portal-form-input::placeholder {
    color: var(--input-placeholder);
}
.portal-form-textarea {
    resize: vertical;
    min-height: 100px;
}
.portal-form-select {
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%236b6b66' d='M3 4.5L6 8l3-3.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 12px;
    padding-right: 32px;
}
.portal-form-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 20px;
}
.portal-form-check {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.8125rem;
    color: var(--text-secondary);
}
.portal-form-check input[type="checkbox"] {
    width: 16px;
    height: 16px;
    border-radius: 4px;
    accent-color: var(--color-accent);
}
.portal-form-link {
    font-size: 0.8125rem;
    color: var(--color-accent);
    text-decoration: none;
    font-weight: 500;
}
.portal-form-link:hover {
    text-decoration: underline;
}
.portal-login-btn {
    width: 100%;
    padding: 11px 20px;
    border-radius: 8px;
    border: none;
    background: var(--color-accent);
    color: #fff;
    font-size: 0.875rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.15s ease;
    font-family: inherit;
}
.portal-login-btn:hover {
    background: var(--color-accent-hover);
}
.portal-login-btn:active {
    transform: scale(0.98);
}
.portal-login-error {
    background: var(--badge-danger-bg);
    color: var(--badge-danger-text);
    padding: 10px 14px;
    border-radius: 8px;
    font-size: 0.8125rem;
    font-weight: 500;
    margin-bottom: 16px;
    display: flex;
    align-items: center;
    gap: 8px;
}
.portal-login-error svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
}
.portal-login-success {
    background: var(--badge-success-bg);
    color: var(--badge-success-text);
    padding: 10px 14px;
    border-radius: 8px;
    font-size: 0.8125rem;
    font-weight: 500;
    margin-bottom: 16px;
}

/* ── Portal Filter/Search Bar ───────────────────────────────── */
.portal-filters {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}
/* S-DESIGN-INPUTS: portal search/filter use Apple pill aesthetic. */
.portal-search-input {
    flex: 1;
    min-width: 200px;
    max-width: 320px;
    padding: 8px 12px 8px 34px;
    border: none;
    border-radius: 8px;
    font-size: 0.8125rem;
    color: var(--input-text);
    background: var(--input-bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.5' stroke='%239c9c96'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z'/%3E%3C/svg%3E") no-repeat 10px center / 16px;
    outline: none;
    transition: background 0.15s ease, box-shadow 0.15s ease;
}
.portal-search-input::placeholder { color: var(--input-placeholder); }
.portal-search-input:focus {
    background-color: var(--input-bg-focus);
    box-shadow: 0 0 0 2px var(--color-primary);
}
.portal-filter-select {
    padding: 8px 32px 8px 12px;
    border: none;
    border-radius: 8px;
    font-size: 0.8125rem;
    color: var(--input-text);
    background: var(--input-bg);
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%236b6b66' d='M3 4.5L6 8l3-3.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 12px;
    outline: none;
    cursor: pointer;
    transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
.portal-filter-select:focus {
    background-color: var(--input-bg-focus);
    box-shadow: 0 0 0 2px var(--color-primary);
}

/* ── Portal Pagination ──────────────────────────────────────── */
.portal-pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 16px;
}
.portal-pagination-btn {
    padding: 6px 12px;
    border-radius: 6px;
    border: 1px solid var(--border-color);
    background: var(--bg-card);
    color: var(--text-secondary);
    font-size: 0.8125rem;
    cursor: pointer;
    transition: all 0.15s ease;
}
.portal-pagination-btn:hover {
    border-color: var(--color-accent);
    color: var(--color-accent);
}
.portal-pagination-btn.is-active {
    background: var(--color-accent);
    color: #fff;
    border-color: var(--color-accent);
}
.portal-pagination-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* ── Portal Responsive ──────────────────────────────────────── */
@media (max-width: 1024px) {
    .portal-sidebar {
        transform: translateX(-100%);
    }
    .portal-sidebar.is-open {
        transform: translateX(0);
    }
    .portal-main {
        margin-left: 0;
    }
    .portal-mobile-toggle {
        display: flex;
    }
}
@media (max-width: 768px) {
    .portal-kpi-grid {
        grid-template-columns: repeat(2, 1fr);
    }
    .portal-content {
        padding: 16px;
    }
    .portal-detail-grid {
        grid-template-columns: 1fr;
    }
    .portal-cards-grid {
        grid-template-columns: 1fr;
    }
    .portal-topbar {
        padding: 0 16px;
    }
    .portal-equip-meta {
        grid-template-columns: 1fr;
    }
    .portal-filters {
        flex-direction: column;
        align-items: stretch;
    }
    .portal-search-input {
        max-width: none;
    }
}
@media (max-width: 480px) {
    .portal-kpi-grid {
        grid-template-columns: 1fr;
    }
    .portal-login-card {
        padding: 28px 20px;
    }
    /* portal-tabs already wraps via flex-wrap; no scroll needed. */
}

/* ── Portal Mobile Overlay ──────────────────────────────────── */
.portal-sidebar-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.4);
    z-index: 35;
}
@media (max-width: 1024px) {
    .portal-sidebar-overlay.is-visible {
        display: block;
    }
}


/* ═══════════════════════════════════════════════════════════════
   RESPONSIVE-1 — SESSION 2026-04-08
   Tablet + mobile responsive rules and theme-toggle visibility fix.
   STRICTLY ADDITIVE — does not modify any existing selectors.
   Breakpoints:
     Desktop : 1024px+  (unchanged)
     Tablet  : 768..1023px  (sidebar collapses to icon rail)
     Mobile  : ≤767px  (sidebar slides in, hamburger shown)
   ═══════════════════════════════════════════════════════════════ */

/* ── FIX 1 — Theme toggle icon visibility ─────────────────────
   Bordered pill with contrasting background so sun/moon icons
   never blend into the topbar. Icon sized to 20×20 per spec.
   WHY svg descendant selector: heroicon() is per-name cached so
   the svg inside .topbar-theme-btn may inherit the sidebar's
   .theme-icon class — we target svg directly to be class-agnostic
   and never fight the existing sidebar-scoped display rules. */
.topbar-theme-btn {
    border: 1px solid var(--border-color-strong);
    background-color: var(--bg-surface-2);
    color: var(--text-primary);
    min-width: 36px;
    min-height: 36px;
    /* WHY: skip background transition so the background recomputes
       instantly from --bg-surface-2 on data-theme change. The inherited
       .btn-icon transition otherwise caches the start value and the
       button visually stays on the previous theme's surface tint. */
    transition: border-color var(--transition-fast), color var(--transition-fast);
}
.topbar-theme-btn svg {
    width: 20px !important;
    height: 20px !important;
    color: var(--text-primary);
    stroke: currentColor;
    stroke-width: 2;
    display: block !important;
}
.topbar-theme-btn:hover {
    border-color: var(--color-primary);
    background-color: var(--bg-surface-hover);
}
.topbar-theme-btn:hover svg {
    color: var(--color-primary);
}
[data-theme="light"] .topbar-theme-btn svg { color: var(--text-primary); }
[data-theme="dark"]  .topbar-theme-btn svg { color: var(--text-primary); }

/* ── FIX 2 — Shared utility classes (new, non-conflicting) ─── */

/* KPI grid — auto columns that collapse gracefully */
.kpi-grid,
.stat-grid--4 {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 16px;
}
.stat-grid--3 {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 16px;
}
.stat-grid--2 {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
}

/* Form responsive grid */
.form-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 16px;
}
.form-group--full { grid-column: 1 / -1; }

/* Table-responsive wrapper (additive — complements existing .table-wrapper) */
.table-responsive {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-radius: var(--radius-xl);
}

/* ── Hamburger button (mobile only) ─────────────────────────── */
.hamburger-btn {
    display: none;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: var(--radius-md);
    border: 1px solid var(--border-color);
    background: var(--bg-surface-2);
    color: var(--text-primary);
    cursor: pointer;
    flex-shrink: 0;
}
.hamburger-btn:hover {
    background: var(--bg-surface-hover);
    border-color: var(--color-primary);
}
.hamburger-btn .nav-icon {
    width: 22px;
    height: 22px;
}

/* ═══════════════════════════════════════════════════════════════
   TABLET — 768..1023px
   Sidebar collapses to an always-visible 64px icon rail.
   Overrides existing max-width:1023px rules via later source order.
   ═══════════════════════════════════════════════════════════════ */
@media (min-width: 768px) and (max-width: 1023px) {
    .sidebar {
        position: fixed;
        top: 0;
        left: 0;
        width: var(--sidebar-width-collapsed);
        height: 100%;
        transform: translateX(0);
        /* SIDEBAR-SCROLL-1: was `overflow: visible` — which killed sidebar-nav
           scrolling because the outer element refused to clip, so the inner
           scroll container never had a bounded parent to scroll against.
           Clip here; inner .sidebar-nav still scrolls via its own overflow. */
        overflow: hidden;
    }
    .sidebar .sidebar-brand-name,
    .sidebar .nav-item-label,
    .sidebar .nav-group-arrow,
    .sidebar .sidebar-user-info {
        opacity: 0;
        pointer-events: none;
        max-width: 0;
        visibility: hidden;
    }

    /* Section separators + nav-children must fully collapse out of flow
       in tablet icon-rail mode. opacity/visibility/max-width alone leaves
       block-level height behind: ~34px per .nav-section-label, plus the
       full natural height of any .nav-group.is-open > .nav-children
       (~40px × N children) since base CSS forces display:flex on the
       open group. Mirrors the desktop collapsed rule at line ~988.
       Specificity note: `.nav-group .nav-children` (0,3,0) is needed to
       match `.nav-group.is-open > .nav-children` (0,3,0) so source order
       wins — `.sidebar .nav-children` alone (0,2,0) loses to the open
       rule defined earlier in the file. */
    .sidebar .nav-section-label,
    .sidebar .nav-group .nav-children {
        display: none;
    }
    /* S-SIDEBAR-COLLAPSED-BADGE-DOT — pin notification badges to the
       top-right of the nav item as a small iOS-style dot. Mirrors the
       desktop collapsed rule at line ~947. position:absolute removes
       the badge from the flex flow so it cannot reserve a gap slot. */
    .sidebar .nav-badge {
        position: absolute;
        top: 4px;
        right: 8px;
        min-width: 16px;
        height: 16px;
        padding: 0 4px;
        font-size: 0.5625rem;
        line-height: 1;
        opacity: 1;
        pointer-events: auto;
        max-width: none;
        visibility: visible;
        z-index: 1;
    }
    .sidebar .sidebar-brand {
        justify-content: center;
        padding: 0 8px;
        /* S-DESIGN-LOGO-BIGGER: tablet sidebar is always icon-only,
           so the brand area should match topbar height (no L-step). */
        height: var(--topbar-height);
    }
    .sidebar .sidebar-logo {
        max-width: 44px;
        height: 40px;
    }
    .sidebar .sidebar-brand-icon {
        width: 40px;
        height: 40px;
    }
    .sidebar .brand-icon {
        width: 24px;
        height: 24px;
    }
    .sidebar .sidebar-collapse-btn {
        display: none;
    }
    .sidebar .nav-item {
        justify-content: center;
        padding: 10px 8px;
        /* S-SIDEBAR-COLLAPSED-ICON-FIX — zero inter-child gap so the
           hidden .nav-item-label can't reserve a 10px slot that
           pushes the icon off center. */
        gap: 0;
    }
    .sidebar .nav-item-icon,
    .sidebar .nav-icon {
        margin: 0 auto;
        flex-shrink: 0;
    }
    .sidebar .sidebar-user {
        justify-content: center;
    }
    .sidebar .sidebar-user-actions {
        flex-direction: column;
    }

    /* Main content sits to the right of the 64px rail */
    .app-main {
        margin-left: var(--sidebar-width-collapsed);
    }

    /* Hamburger hidden on tablet — rail is always visible */
    .topbar-menu-btn,
    .hamburger-btn {
        display: none;
    }

    /* KPI + stat grids collapse to 2 columns */
    .kpi-grid,
    .stat-grid--4,
    .stat-grid--3 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* WHY: at tablet widths (768-1023px) many pages have 6-7 action buttons
       that overflow the single-row header. Give the actions bar full width so
       buttons wrap to a second line rather than overflowing the container. */
    .page-header-actions {
        flex-wrap: wrap;
        width: 100%;
    }
}

/* ═══════════════════════════════════════════════════════════════
   MOBILE — ≤767px
   Sidebar hidden by default; slides in via hamburger toggle.
   Overlay + body-no-scroll handled by Alpine state.
   ═══════════════════════════════════════════════════════════════ */
@media (max-width: 767px) {
    /* Hamburger visible; hide desktop search bar */
    .hamburger-btn {
        display: inline-flex;
    }
    .topbar-search-btn {
        display: none;
    }
    /* Keep existing .topbar-menu-btn logic too (inherited) */
    .topbar {
        padding: 0 12px;
    }
    .topbar-left {
        gap: 6px;
    }
    .topbar-right {
        gap: 4px;
    }
    .topbar-title {
        font-size: 1rem;
        font-weight: 600;
    }

    /* ════════════════════════════════════════════════════════════
       S-MOBILE-CHROME-CLEANUP — mobile topbar simplification

       Goal: only show what's essential on a phone-width topbar.
       Keep visible:
         hamburger · page title · + (icon-only pill) · 🔍 · 🔔 · avatar
       Hide on mobile (still available on desktop/tablet):
         home button, theme toggle, A+ display, sound toggle,
         team chat, AI sparkles, inline search input
       Rationale: AI + chat live in the sidebar nav / floating bubble;
       theme + display + sound are once-set preferences that don't
       need to be on the topbar of a phone; search collapses to an
       icon that opens the existing ⌘K modal full-screen.
       ════════════════════════════════════════════════════════════ */

    /* + New: drop the text label, keep just the "+" icon for a
       compact pill that still hints at the quick-create dropdown. */
    .topbar-create-btn__label { display: none; }
    .topbar-create-btn {
        padding: 8px;
        min-width: 36px;
        justify-content: center;
    }

    /* Hide the inline search input; show the magnifying-glass icon
       that opens the existing ⌘K global search modal. */
    .search-wrapper { display: none; }
    .topbar-search-icon-btn { display: inline-flex; }

    /* Hide secondary topbar controls — they live elsewhere or are
       once-set preferences not needed on every page-load on mobile. */
    .topbar-home-btn,
    .topbar-theme-btn,
    .topbar-display,
    .topbar-display-btn,
    .sound-toggle-btn,
    .topbar-chat-btn,
    .topbar-ai-btn,
    .topbar-company-name,
    .topbar-breadcrumb-sep {
        display: none !important;
    }
    .topbar-home-btn {
        display: none;
    }

    /* Sidebar overlay (new div injected from header.php) */
    .sidebar-overlay {
        display: none;
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.5);
        z-index: calc(var(--z-sidebar) - 1);
    }
    .sidebar-overlay.is-visible {
        display: block;
    }

    /* KPI + stat grids collapse to single column */
    .kpi-grid,
    .stat-grid--4,
    .stat-grid--3,
    .stat-grid--2 {
        grid-template-columns: 1fr;
    }

    /* QBO Dashboard / Customers / Drift KPI rows opt INTO a 2x2 mobile
       layout (instead of the system default 1x4 stacked column). The
       4 cards on these pages are compact enough — short numeric values
       + 1-2 lines of supporting text — that a 2x2 layout reads better
       than a 1x4 tall stack at mobile widths. Other modules can opt in
       by adding the same modifier; operator surfaced 2026-05-21. */
    .kpi-grid--qbo {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* Invoice address cards stack vertically on mobile */
    .invoice-addresses {
        grid-template-columns: 1fr;
    }

    /* Forms collapse to a single column */
    .form-grid {
        grid-template-columns: 1fr;
    }
    .form-group--full { grid-column: 1; }
    .form-row,
    .form-row-2,
    .form-row-3,
    .form-row-4 {
        grid-template-columns: 1fr;
    }

    /* Form actions — stack, reverse, full width */
    .form-actions {
        flex-direction: column-reverse;
        gap: 8px;
        align-items: stretch;
    }
    .form-actions .btn {
        width: 100%;
    }

    /* Page header — stack title above actions */
    .page-header {
        flex-direction: column;
        align-items: flex-start;
        gap: 12px;
    }
    .page-header-actions {
        width: 100%;
        flex-wrap: wrap;
    }
    .page-header .btn,
    .page-header-actions .btn {
        width: 100%;
    }

    /* Modals — bottom-sheet style */
    .modal-overlay {
        align-items: flex-end;
    }
    .modal {
        width: 100%;
        max-width: 100%;
        margin: 0;
        border-radius: 16px 16px 0 0;
        max-height: 90vh;
        overflow-y: auto;
    }

    /* Tabs — horizontal scroll, hide scrollbar */
    .tab-nav,
    .tabs,
    .tabs-list {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        flex-wrap: nowrap;
    }
    .tab-nav::-webkit-scrollbar,
    .tabs::-webkit-scrollbar,
    .tabs-list::-webkit-scrollbar { display: none; }
    .tab-btn,
    .tab-item,
    .tab {
        white-space: nowrap;
        flex-shrink: 0;
    }

    /* Filter bars — stack vertically */
    .filter-bar,
    .table-toolbar {
        flex-direction: column;
        align-items: stretch;
    }
    .filter-bar select,
    .filter-bar input,
    .filter-bar .btn,
    .table-toolbar-left,
    .table-toolbar-right {
        width: 100%;
    }
    .table-toolbar-left .form-control,
    .table-toolbar-right .form-control,
    .table-toolbar-left .btn,
    .table-toolbar-right .btn {
        width: 100%;
    }

    /* Ensure every table scrolls horizontally on mobile — safety net
       for tables whose surrounding markup was not updated this pass. */
    .table-wrapper,
    .table-responsive,
    .card > .table,
    .card > .data-table {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    /* 640px min-width is the desktop safety floor that lets a table
       horizontally scroll inside a narrow wrapper. Excluded: tables that
       have been transformed into mobile cards (.table-stack) or spec
       key/value tables (no <thead>) — those flow to viewport width and
       would only get clipped at 640px since the parent .card has
       overflow:hidden. Override to min-width:0 for them. */
    table.table,
    table.data-table {
        min-width: 640px;
    }
    table.table.table-stack,
    .card .table:not(.table-stack):not([data-labelled]) {
        min-width: 0 !important;
        width: 100% !important;
    }

    /* Larger tap targets on mobile */
    .btn {
        min-height: 44px;
    }
    .btn-xs,
    .btn-sm {
        min-height: 36px;
    }
    .btn-icon,
    .action-btn,
    .nav-item,
    .pagination-btn,
    .page-btn,
    .hamburger-btn {
        min-height: 44px;
    }

    /* Page content padding tightened (existing rule already does 20/16; keep) */
    .page-content {
        padding: 16px 12px;
    }

    /* Notification dropdown — already full-width via existing rules */
}

/* ═══════════════════════════════════════════════════════════════
   TABLE-STACK — responsive horizontal CAROUSEL of card-rows.
   app.js auto-applies .table-stack + reads data-label from <th>, so
   every table in the app picks up this treatment automatically on
   narrow viewports.

   The mobile experience matches the .carousel-card pattern on the
   main dashboard (Active Leases / Pending Activations): each <tr>
   becomes a swipeable card with label-above-value rows, and the
   tbody becomes the horizontal scroll track with scroll-snap so
   each card lands flush at the start.

   Cells stay block-stacked inside the card (label eyebrow + value
   beneath) because that pattern survives the widest variety of <td>
   children — anchors with secondary <div>s, conditional badges in
   <template x-if>, <span>s with x-text — and avoids Safari/iOS
   formatting-context quirks where a flexbox child of <table> is
   silently ignored.
   ═══════════════════════════════════════════════════════════════ */
@media (max-width: 767px) {
    /* Make the TABLE itself the horizontal carousel container.
       WHY not tbody: iOS Safari's UA stylesheet enforces
       `tbody { display: table-row-group }` and ignores author
       `display:flex !important` in many contexts. The reliable
       workaround is to flex the <table> directly and collapse
       <tbody> via `display:contents` so its <tr> children become
       direct flex children of the table. */
    .table-stack {
        display: flex !important;
        flex-direction: row !important;
        flex-wrap: nowrap !important;
        gap: 12px !important;
        width: 100% !important;
        overflow-x: auto !important;
        overflow-y: visible !important;
        -webkit-overflow-scrolling: touch;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
        padding: 4px 20px 8px 0 !important;
        scroll-padding-left: 4px;
        margin: 0 !important;
        border-collapse: separate !important;
        border-spacing: 0 !important;
    }
    .table-stack::-webkit-scrollbar { display: none; }
    .table-stack thead  { display: none !important; }
    .table-stack tbody  { display: contents !important; }
    .table-stack tfoot  { display: contents !important; }

    /* Each row is a carousel card flex-item, directly under the
       <table> flex container thanks to tbody/tfoot display:contents.
       Dimensions and border mirror .carousel-card on the main
       dashboard so the visual language is consistent. */
    .table-stack tr {
        display: flex !important;
        flex-direction: column !important;
        flex: 0 0 78vw !important;
        max-width: 320px !important;
        min-width: 220px !important;
        scroll-snap-align: start;
        margin: 0 !important;
        padding: 18px 20px !important;
        border: 1px solid var(--border-color) !important;
        border-radius: 14px !important;
        background: var(--bg-card) !important;
        box-shadow:
            inset 0 1px 0 rgba(255,255,255,0.025),
            0 1px 2px rgba(0,0,0,0.18);
        transition: border-color 200ms ease, box-shadow 200ms ease;
        box-sizing: border-box;
    }
    .table-stack tr:hover {
        border-color: var(--color-primary);
    }

    /* tfoot row visually marked as a summary card with brand-tinted
       top border. tfoot itself is display:contents above. */
    .table-stack tfoot tr {
        border-top: 2px solid var(--color-primary) !important;
    }

    /* Each cell becomes a stacked label-above-value row inside the card.
       !important is required because .table tbody td (specificity
       0,1,2) beats .table-stack td (0,1,1) and would otherwise hold
       the desktop padding + table-cell display. */
    .table-stack td {
        display: block !important;
        padding: 6px 0 !important;
        border: none !important;
        text-align: left !important;
        font-size: 0.875rem;
        color: var(--text-primary);
        white-space: normal !important;
        overflow-wrap: anywhere;
        word-break: break-word;
        min-width: 0;
    }
    .table-stack td:first-child { padding-top: 0 !important; }
    .table-stack td:last-child  { padding-bottom: 0 !important; }

    /* Skip cells that have no label — typically the trailing actions <td>
       which has an empty <th>. Render with a hairline divider so action
       buttons sit visually separated from the card data. */
    .table-stack td:not([data-label]),
    .table-stack td[data-label=""] {
        padding-top: 12px !important;
        margin-top: 4px;
        border-top: 1px solid var(--border-color) !important;
    }
    .table-stack td:not([data-label]):first-child,
    .table-stack td[data-label=""]:first-child {
        border-top: 0 !important;
        margin-top: 0;
    }

    /* The label sits above the value as a small uppercase eyebrow —
       same typography as .cc-footer-label on the dashboard carousel. */
    .table-stack td[data-label]:not([data-label=""])::before {
        content: attr(data-label);
        display: block;
        margin-bottom: 3px;
        font-size: 0.625rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.08em;
        color: var(--text-muted);
    }

    /* Reset any text-right/text-center alignment that desktop tables use —
       on mobile every cell reads top-down, left-aligned. */
    .table-stack td.text-right,
    .table-stack td.text-center { text-align: left !important; }

    /* Empty-state row (single <td colspan="N">No results</td>) gets
       full carousel-card width so the "no data" message doesn't look
       like a misaligned narrow card. */
    .table-stack tbody tr:only-child td[colspan] {
        text-align: center !important;
        padding: 12px 0 !important;
    }

    /* ── SPEC TABLES (key/value, no <thead>) ─────────────────────────
       Show pages render two-column key/value layouts as `<table class="table">`
       with no <thead> — the first <td> is the label, second is the value.
       The auto-labeller skips these (it requires <thead><th>), so on mobile
       the table keeps its desktop width (~640px) and gets clipped by the
       parent card's overflow, leaving only the left column visible.

       Detect them via :not([data-labelled]) + :not(.table-stack) and stack
       each row's two cells the same way as auto-stack tables. */
    .card .table:not(.table-stack):not([data-labelled]),
    .card .table:not(.table-stack):not([data-labelled]) tbody {
        display: block !important;
        width: 100% !important;
    }
    .card .table:not(.table-stack):not([data-labelled]) tr {
        display: block !important;
        padding: 8px 0 !important;
        border: none !important;
        border-bottom: 1px solid var(--border-color) !important;
    }
    .card .table:not(.table-stack):not([data-labelled]) tr:last-child {
        border-bottom: none !important;
    }
    .card .table:not(.table-stack):not([data-labelled]) td {
        display: block !important;
        padding: 2px 0 !important;
        border: none !important;
        text-align: left !important;
        white-space: normal !important;
        overflow-wrap: anywhere;
        word-break: break-word;
    }
    /* First cell = label (small uppercase eyebrow). Detect via the
       .text-secondary class that every spec-table uses for the label
       column, and fall back to :first-child for tables that don't. */
    .card .table:not(.table-stack):not([data-labelled]) td:first-child,
    .card .table:not(.table-stack):not([data-labelled]) td.text-secondary {
        font-size: 0.6875rem !important;
        font-weight: 600 !important;
        text-transform: uppercase;
        letter-spacing: 0.06em;
        color: var(--text-tertiary) !important;
        margin-bottom: 2px;
    }
}

/* ═══════════════════════════════════════════════════════════════
   EQUIPMENT LIST — explicit mobile card view
   WHY: the auto-stack CSS transform (table → stacked cards) has a
   timing race with Alpine x-for. Instead, the equipment index uses
   two separate templates: .eq-table-desktop (hidden ≤767px) and
   .eq-cards-mobile (hidden ≥768px). Values are plain x-text bindings
   so there is no dependency on data-label injection timing.
   ═══════════════════════════════════════════════════════════════ */

/* Desktop table: hidden on mobile */
.eq-table-desktop { display: block; }

/* Mobile card list: hidden on desktop */
.eq-cards-mobile  { display: none; }

@media (max-width: 767px) {
    .eq-table-desktop { display: none !important; }
    .eq-cards-mobile  { display: block; padding: 12px; }
}

/* Individual unit card */
.eq-mobile-card {
    display: block;
    text-decoration: none;
    color: inherit;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    padding: 14px 16px;
    margin-bottom: 10px;
    transition: background var(--transition-fast), box-shadow var(--transition-fast);
}
.eq-mobile-card:hover,
.eq-mobile-card:active {
    background: var(--bg-surface-hover);
    box-shadow: var(--shadow-sm);
    text-decoration: none;
    color: inherit;
}

/* Header row: unit number (left) + status badge (right) */
.eq-mc-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 10px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--border-color);
}
.eq-mc-unit {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text-primary);
}

/* Key / value rows */
.eq-mc-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    padding: 4px 0;
    font-size: 0.8125rem;
}
.eq-mc-label {
    color: var(--text-tertiary);
    font-weight: 600;
    flex-shrink: 0;
    white-space: nowrap;
}
.eq-mc-value {
    color: var(--text-primary);
    text-align: right;
    min-width: 0;
    word-break: break-word;
}

/* ═══════════════════════════════════════════════════════════════
   TABLET — kpi + stat grids for tablet
   ═══════════════════════════════════════════════════════════════ */
@media (min-width: 768px) and (max-width: 1023px) {
    .stat-grid--2 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .form-grid {
        grid-template-columns: repeat(2, 1fr);
    }
    .page-content {
        padding: 18px 14px;
    }
}


/* ═══════════════════════════════════════════════════════════════
   SEARCH-1 — SESSION 2026-04-08
   Inline topbar search widget (replaces the legacy button pattern).
   All selectors scoped under .search-wrapper so they never collide
   with the existing modal search panel (.search-panel .search-input).
   ═══════════════════════════════════════════════════════════════ */

.search-wrapper {
    position: relative;
    flex: 1 1 auto;
    max-width: 420px;
    min-width: 0;
}

.search-wrapper .search-input-wrap {
    position: relative;
    display: flex;
    align-items: center;
    padding: 0;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-full);
    background: var(--bg-surface-2);
    transition: border-color var(--transition-fast),
                background var(--transition-fast),
                box-shadow var(--transition-fast);
    gap: 0;
    height: 36px;
}

.search-wrapper .search-input-wrap:focus-within {
    border-color: var(--color-primary);
    background: var(--bg-surface);
    box-shadow: 0 0 0 3px var(--color-primary-light);
}

.search-wrapper .search-input-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border: none;
    background: transparent;
    color: var(--text-tertiary);
    cursor: pointer;
    border-radius: var(--radius-full) 0 0 var(--radius-full);
    flex-shrink: 0;
}
.search-wrapper .search-input-icon:hover {
    color: var(--text-primary);
}
.search-wrapper .search-input-icon .search-icon {
    width: 16px;
    height: 16px;
}

.search-wrapper .search-input {
    flex: 1 1 auto;
    height: 34px;
    padding: 0 8px 0 0;
    border: none;
    background: transparent;
    color: var(--text-primary);
    font-size: 0.875rem;
    font-family: inherit;
    outline: none;
    min-width: 0;
}
.search-wrapper .search-input::placeholder {
    color: var(--text-tertiary);
}

.search-wrapper .search-kbd--inline {
    display: inline-flex;
    align-items: center;
    font-family: 'DM Mono', monospace;
    font-size: 0.6875rem;
    padding: 2px 6px;
    margin-right: 6px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color-strong);
    border-radius: var(--radius-sm);
    color: var(--text-tertiary);
    flex-shrink: 0;
    white-space: nowrap;
}

/* CSS spinner — uses currentColor so it theme-adapts */
.search-wrapper .search-spinner {
    width: 14px;
    height: 14px;
    margin-right: 8px;
    border: 2px solid var(--border-color);
    border-top-color: var(--color-primary);
    border-radius: 50%;
    animation: ff-search-spin 0.8s linear infinite;
    flex-shrink: 0;
}
@keyframes ff-search-spin {
    to { transform: rotate(360deg); }
}

/* ── Dropdown ────────────────────────────────────────────────── */
.search-wrapper .search-dropdown {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-xl);
    z-index: var(--z-dropdown);
    max-height: 480px;
    overflow-y: auto;
    padding: 4px 0;
}

.search-wrapper .search-group + .search-group {
    border-top: 1px solid var(--border-color);
    margin-top: 4px;
    padding-top: 4px;
}

.search-wrapper .search-group-label {
    padding: 8px 14px 4px;
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text-tertiary);
}

.search-wrapper .search-result-item {
    display: block;
    padding: 8px 14px;
    text-decoration: none;
    color: var(--text-primary);
    transition: background var(--transition-fast);
}
.search-wrapper .search-result-item:hover {
    background: var(--bg-surface-hover);
    text-decoration: none;
}

.search-wrapper .search-result-main {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.search-wrapper .search-result-title {
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    flex: 1 1 auto;
}

.search-wrapper .search-result-sub {
    font-size: 0.75rem;
    color: var(--text-tertiary);
    margin-top: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.search-wrapper .search-empty,
.search-wrapper .search-loading {
    padding: 20px 16px;
    text-align: center;
    color: var(--text-tertiary);
    font-size: 0.8125rem;
}

.search-wrapper .search-see-all {
    display: block;
    width: 100%;
    padding: 10px 14px;
    text-align: center;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--color-primary);
    background: transparent;
    border: none;
    border-top: 1px solid var(--border-color);
    cursor: pointer;
    margin-top: 4px;
}
.search-wrapper .search-see-all:hover {
    background: var(--bg-surface-hover);
}

/* ── Responsive ──────────────────────────────────────────────── */
@media (min-width: 768px) and (max-width: 1023px) {
    /* On tablet the topbar is compact — shrink the search max-width
       and drop the keyboard hint so the input still fits. */
    .search-wrapper {
        max-width: 240px;
    }
    .search-wrapper .search-kbd--inline {
        display: none;
    }
}

@media (max-width: 767px) {
    /* Mobile: hide the inline search entirely — the hamburger gives
       enough real estate. Users can still invoke ⌘K via the modal
       if they're on a keyboard-connected tablet. */
    .search-wrapper {
        display: none;
    }
}


/* ═══════════════════════════════════════════════════════════════
   THEME-1 — SESSION 2026-04-08
   Spacing tokens (theme-agnostic) + scrollbar styling.
   These rules are strictly additive — they introduce new tokens
   in :root and lightweight global rules; existing selectors are
   unchanged unless explicitly overridden below.
   ═══════════════════════════════════════════════════════════════ */

:root {
    /* New spacing tokens — used by .page-content / .card / .section /
       .kpi-grid / table cells. Defined here (not in [data-theme=*])
       because spacing is theme-agnostic. */
    --section-gap:    28px;
    --card-gap:       20px;
    --card-padding:   24px;
    --page-padding:   28px;
    --table-cell-px:  16px;
    --table-cell-py:  12px;
}

/* Apply spacing tokens to layout primitives. Source order > existing
   .page-content / .card rules above so these win the cascade. */
.page-content,
.main-content {
    padding: var(--page-padding);
}
.card,
.card-body {
    padding: var(--card-padding);
}
.section + .section {
    margin-top: var(--section-gap);
}
.kpi-grid,
.stat-grid--4,
.stat-grid--3,
.stat-grid--2 {
    gap: var(--card-gap);
}
table th,
table td {
    padding: var(--table-cell-py) var(--table-cell-px);
}

/* ── Global scrollbar styling (Firefox + WebKit) ─────────────────
   Variables fall back to the previous look in light mode where
   --scrollbar-bg / --scrollbar-thumb are not defined (browser
   uses its native scrollbar). Dark mode uses the warm palette. */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--scrollbar-thumb, #4a4845)
                     var(--scrollbar-bg, transparent);
}
*::-webkit-scrollbar { width: 6px; height: 6px; }
*::-webkit-scrollbar-track {
    background: var(--scrollbar-bg, transparent);
}
*::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb, #4a4845);
    border-radius: 3px;
}

/* ============================================================
   NOTIF-1 — Notifications system (bell, dropdown, page)
   ============================================================
   Lives in its own block at the end so it can override the
   legacy .topbar-bell-btn / .notification-* rules above when
   the topbar markup migrates to .notif-* (NOTIF-1).
   ============================================================ */

.notif-wrapper {
    position: relative;
}

.notif-bell-btn {
    position: relative;
}
.notif-bell-btn.has-unread {
    color: var(--color-accent, #3b82f6);
}
.notif-badge {
    position: absolute;
    top: -4px;
    right: -4px;
    min-width: 18px;
    height: 18px;
    padding: 0 4px;
    border-radius: 9px;
    background: var(--color-danger, #dc2626);
    color: #ffffff;
    font-size: 10px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid var(--bg-page, #0f0f0f);
    pointer-events: none;
    line-height: 1;
}

.notif-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: 380px;
    background: var(--bg-card, var(--bg-surface, #1a1a1a));
    border: 1px solid var(--border-color, #2e2e2e);
    border-radius: var(--radius-xl, 12px);
    box-shadow: var(--shadow-lg, 0 4px 16px rgba(0, 0, 0, .4));
    z-index: 500;
    max-height: 520px;
    overflow-y: auto;
}
.notif-dropdown-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 16px;
    border-bottom: 1px solid var(--border-color, #2e2e2e);
    position: sticky;
    top: 0;
    background: var(--bg-card, var(--bg-surface, #1a1a1a));
    z-index: 1;
}
.notif-dropdown-title {
    font-weight: 600;
    font-size: 14px;
    color: var(--text-primary, #e8e8e4);
}
.notif-mark-all {
    font-size: 12px;
    color: var(--color-accent, #3b82f6);
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
}
.notif-mark-all:hover {
    text-decoration: underline;
}

.notif-loading,
.notif-empty {
    padding: 28px 16px;
    text-align: center;
    color: var(--text-muted, #6b6b66);
    font-size: 13px;
}
.notif-empty p {
    margin: 8px 0 0;
}

.notif-item {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 16px;
    text-decoration: none;
    color: var(--text-primary, #e8e8e4);
    border-bottom: 1px solid var(--border-color, #2e2e2e);
    transition: background 0.15s;
    position: relative;
}
.notif-item:last-child {
    border-bottom: none;
}
.notif-item:hover {
    background: var(--bg-muted, var(--bg-surface-hover, #242424));
    text-decoration: none;
}
.notif-item--unread {
    background: var(--bg-selected, #1e2a3a);
    border-left: 3px solid var(--color-accent, #3b82f6);
}
.notif-item--unread:hover {
    background: var(--bg-hover, #2a2a2a);
}

.notif-icon {
    width: 32px;
    height: 32px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background: var(--bg-muted, #242424);
    color: var(--text-secondary, #9c9c96);
}
.notif-icon svg {
    width: 18px;
    height: 18px;
}
.notif-icon--leases       { background: rgba(59, 130, 246, 0.15); color: #60a5fa; }
.notif-icon--invoices     { background: rgba(168, 85, 247, 0.15); color: #c084fc; }
.notif-icon--payments     { background: rgba(34, 197, 94, 0.15);  color: #4ade80; }
.notif-icon--customers    { background: rgba(148, 163, 184, 0.15); color: #94a3b8; }
.notif-icon--equipment    { background: rgba(59, 130, 246, 0.15); color: #60a5fa; }
.notif-icon--compliance   { background: rgba(250, 204, 21, 0.15); color: #facc15; }
.notif-icon--maintenance  { background: rgba(148, 163, 184, 0.15); color: #94a3b8; }
.notif-icon--damage       { background: rgba(239, 68, 68, 0.15);  color: #f87171; }
.notif-icon--reservations { background: rgba(59, 130, 246, 0.15); color: #60a5fa; }
.notif-icon--samsara      { background: rgba(14, 165, 233, 0.15); color: #38bdf8; }
.notif-icon--accounting   { background: rgba(168, 85, 247, 0.15); color: #c084fc; }
.notif-icon--system       { background: rgba(148, 163, 184, 0.15); color: #94a3b8; }
.notif-icon--info         { background: rgba(14, 165, 233, 0.15); color: #38bdf8; }
.notif-icon--warning      { background: rgba(245, 158, 11, 0.20); color: #fbbf24; }
.notif-icon--danger       { background: rgba(239, 68, 68, 0.20);  color: #f87171; }

.notif-content {
    flex: 1;
    min-width: 0;
}
.notif-title {
    font-size: 13px;
    font-weight: 500;
    line-height: 1.4;
    margin-bottom: 2px;
    color: var(--text-primary, #e8e8e4);
}
.notif-item--unread .notif-title {
    font-weight: 600;
}
.notif-message {
    font-size: 12px;
    color: var(--text-secondary, #9c9c96);
    line-height: 1.4;
    margin-bottom: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.notif-time {
    font-size: 11px;
    color: var(--text-muted, #6b6b66);
    font-family: var(--font-mono, ui-monospace, monospace);
}
.notif-unread-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--color-accent, #3b82f6);
    flex-shrink: 0;
    margin-top: 6px;
}

.notif-dropdown-footer {
    display: block;
    padding: 12px 16px;
    text-align: center;
    font-size: 13px;
    color: var(--color-accent, #3b82f6);
    text-decoration: none;
    border-top: 1px solid var(--border-color, #2e2e2e);
    position: sticky;
    bottom: 0;
    background: var(--bg-card, var(--bg-surface, #1a1a1a));
}
.notif-dropdown-footer:hover {
    background: var(--bg-muted, var(--bg-surface-hover, #242424));
    text-decoration: none;
}

/* ── Full notifications page ──────────────────────────────── */
.notif-page-list {
    list-style: none;
    margin: 0;
    padding: 0;
}
.notif-page-item {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 16px 20px;
    border-bottom: 1px solid var(--border-color, #2e2e2e);
    position: relative;
}
.notif-page-item:last-child {
    border-bottom: none;
}
.notif-page-item--unread {
    background: var(--bg-selected, #1e2a3a);
    border-left: 3px solid var(--color-accent, #3b82f6);
}
.notif-page-content {
    flex: 1;
    min-width: 0;
}
.notif-page-title {
    font-size: 14px;
    font-weight: 500;
    color: var(--text-primary, #e8e8e4);
    margin-bottom: 4px;
}
.notif-page-item--unread .notif-page-title {
    font-weight: 600;
}
.notif-page-message {
    font-size: 13px;
    color: var(--text-secondary, #9c9c96);
    line-height: 1.5;
    margin-bottom: 6px;
}
.notif-page-meta {
    font-size: 11px;
    color: var(--text-muted, #6b6b66);
    font-family: var(--font-mono, ui-monospace, monospace);
}
.notif-page-actions {
    display: flex;
    gap: 8px;
    flex-shrink: 0;
    align-items: center;
}
.notif-page-empty {
    padding: 64px 24px;
    text-align: center;
    color: var(--text-muted, #6b6b66);
}
.notif-page-empty .nav-icon {
    width: 48px;
    height: 48px;
    margin: 0 auto 12px;
    color: var(--text-muted, #6b6b66);
}
.notif-page-empty-title {
    font-size: 16px;
    font-weight: 500;
    color: var(--text-primary, #e8e8e4);
    margin: 0 0 4px;
}
.notif-page-empty-sub {
    font-size: 13px;
    color: var(--text-muted, #6b6b66);
    margin: 0;
}

/* ── Page-header helpers used by both /notifications pages ─── */
.notif-page-header-text {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
/* Generic page subtitle — also used by other admin pages
   (documents, analytics, reports). Was previously rendered
   without a CSS rule. */
.page-subtitle {
    margin: 0;
    font-size: 0.8125rem;
    color: var(--text-secondary, #9c9c96);
    font-weight: 400;
}

/* ── Filter card on /notifications ─────────────────────────── */
.notif-filter-card {
    margin-bottom: 20px;
}
.notif-filter-form {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    align-items: flex-end;
}
.notif-filter-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 140px;
}
.notif-filter-field--grow {
    flex: 1 1 220px;
    min-width: 220px;
}
.notif-filter-field .form-label {
    font-size: 0.75rem;
    margin: 0;
    color: var(--text-secondary, #9c9c96);
    font-weight: 500;
}
.notif-filter-actions {
    display: flex;
    gap: 8px;
    align-items: center;
}

/* ── List card body should have zero padding so items hug edges ─ */
.notif-list-body {
    padding: 0 !important;
}

/* ── Pagination footer ─────────────────────────────────────── */
.notif-page-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 16px;
    flex-wrap: wrap;
    gap: 8px;
}
.notif-page-footer-text {
    font-size: 0.8125rem;
}
.notif-page-footer-actions {
    display: flex;
    gap: 6px;
}

/* ── Mobile: full-width dropdown under topbar ──────────────── */
@media (max-width: 767px) {
    .notif-dropdown {
        position: fixed;
        top: 60px;
        left: 0;
        right: 0;
        width: 100%;
        border-radius: 0;
        max-height: calc(100vh - 60px);
    }
    .notif-page-item {
        flex-wrap: wrap;
    }
    .notif-page-actions {
        width: 100%;
        justify-content: flex-end;
        margin-top: 8px;
    }
    .notif-filter-form {
        flex-direction: column;
        align-items: stretch;
    }
    .notif-filter-field,
    .notif-filter-field--grow {
        min-width: 0;
        width: 100%;
    }
}


/* ============================================================
   EMAIL-1 — Global Email Compose Modal
   Used by includes/partials/email-compose-modal.php
   ============================================================ */

#ff-email-compose .modal-icon {
    width: 18px;
    height: 18px;
    display: inline-block;
    vertical-align: middle;
    margin-right: 6px;
}
#ff-email-compose .modal-title {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Quick contact chips ----------------------------------------- */
.email-chip-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
}
.email-chip-label {
    font-size: 11px;
    color: var(--text-secondary);
    margin-right: 4px;
}
.email-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    border: 1px solid var(--border-color);
    background: var(--bg-muted);
    color: var(--text-primary);
    border-radius: 999px;
    font-size: 11.5px;
    cursor: pointer;
    transition: background var(--transition-fast), border-color var(--transition-fast);
}
.email-chip:hover {
    background: var(--bg-hover);
    border-color: var(--color-accent);
}
.email-chip-meta {
    color: var(--text-secondary);
    font-weight: 400;
}
.email-chip-tag {
    margin-left: 4px;
    padding: 1px 6px;
    background: var(--badge-info-bg);
    color: var(--badge-info-text);
    border-radius: 999px;
    font-size: 9.5px;
    font-weight: 600;
    text-transform: uppercase;
}

/* Variables panel --------------------------------------------- */
.email-variables-panel {
    margin-top: 8px;
    padding: 10px;
    background: var(--bg-muted);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
}
.email-variables-label {
    font-size: 11px;
    color: var(--text-secondary);
    margin-bottom: 6px;
}
.email-variables-list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.email-variable-chip {
    display: inline-block;
    padding: 4px 10px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    color: var(--color-accent);
    font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
    font-size: 11px;
    cursor: pointer;
    transition: background var(--transition-fast), border-color var(--transition-fast);
}
.email-variable-chip:hover {
    background: var(--bg-hover);
    border-color: var(--color-accent);
}

/* Attachment list --------------------------------------------- */
.email-attachment-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 8px;
}
.email-attachment-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    background: var(--bg-muted);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    font-size: 12.5px;
}
.email-attachment-icon {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    color: var(--text-secondary);
}
.email-attachment-name {
    flex: 1;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.email-attachment-size {
    color: var(--text-secondary);
    font-size: 11px;
    flex-shrink: 0;
}
.email-attachment-remove {
    background: transparent;
    border: none;
    cursor: pointer;
    padding: 2px;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    flex-shrink: 0;
}
.email-attachment-remove:hover {
    background: var(--bg-hover);
    color: var(--color-danger);
}
.email-attachment-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.email-attachment-actions .btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.email-attachment-actions .btn-icon {
    width: 14px;
    height: 14px;
}

/* Picker drawers ---------------------------------------------- */
.email-picker-drawer {
    margin-top: 8px;
    background: var(--bg-muted);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    overflow: hidden;
}
.email-picker-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px 12px;
    background: var(--bg-card);
    border-bottom: 1px solid var(--border-color);
    font-size: 12px;
    font-weight: 600;
    color: var(--text-primary);
}
.email-picker-search {
    padding: 8px 12px;
    border-bottom: 1px solid var(--border-color);
}
.email-picker-list {
    max-height: 220px;
    overflow-y: auto;
    padding: 4px;
}
.email-picker-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background var(--transition-fast);
}
.email-picker-item:hover {
    background: var(--bg-hover);
}
.email-picker-icon {
    width: 18px;
    height: 18px;
    color: var(--text-secondary);
    flex-shrink: 0;
}
.email-picker-item-body {
    flex: 1;
    min-width: 0;
}
.email-picker-item-name {
    font-size: 12.5px;
    color: var(--text-primary);
    font-weight: 500;
}
.email-picker-item-meta {
    font-size: 11px;
    color: var(--text-secondary);
    display: flex;
    align-items: center;
    gap: 6px;
}
.email-picker-add {
    font-size: 11px;
    color: var(--color-accent);
    font-weight: 600;
}
.email-picker-empty {
    padding: 16px;
    text-align: center;
    color: var(--text-secondary);
    font-size: 12px;
}

/* Live preview frame ------------------------------------------ */
.email-preview-frame {
    margin-top: 12px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    overflow: hidden;
    background: #f5f5f4;
}
.email-preview-label {
    padding: 8px 12px;
    background: var(--bg-muted);
    color: var(--text-secondary);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border-bottom: 1px solid var(--border-color);
    display: flex;
    align-items: center;
}
.email-preview-body {
    padding: 16px;
    color: #1c1c1a;
    background: #ffffff;
    font-size: 13px;
    line-height: 1.6;
    max-height: 320px;
    overflow-y: auto;
}

/* History tab on customer / invoice show pages ---------------- */
.email-history-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.email-history-item {
    display: grid;
    grid-template-columns: auto 1fr auto auto;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-card);
}
.email-history-item .badge {
    flex-shrink: 0;
}
.email-history-subject {
    font-weight: 500;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 13px;
}
.email-history-meta {
    font-size: 11px;
    color: var(--text-secondary);
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 2px;
}
.email-history-actions {
    flex-shrink: 0;
}


/* ============================================================
   MEDIA-1 — Sound mute toggle (topbar)
   Matches the visual language of .chat-topbar-btn so the
   group of topbar icons stays cohesive.
   ============================================================ */
/* S-MOBILE-CHROME-CLEANUP: normalised to match .btn-icon — transparent
   surface + hover-only background fill. The previous solid bg-card +
   1px border made this button look visually distinct from theme / A+ /
   bell / avatar in the topbar group, breaking visual consistency. */
.sound-toggle-btn {
  position: relative;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
  border: none;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
  flex-shrink: 0;
}
.sound-toggle-btn:hover {
  background: var(--bg-surface-2);
  color: var(--text-primary);
}
.sound-toggle-btn.is-muted {
  color: var(--text-muted);
  opacity: 0.6;
}
.sound-toggle-btn .nav-icon {
  width: 18px;
  height: 18px;
}


/* ============================================================
   CHAT-1 — Team Chat styles
   chat-topbar-btn, chat-badge, chat-layout, chat-sidebar,
   chat-main, chat-compose, chat-message, chat-widget
   ============================================================ */

/* ── Topbar chat icon ──────────────────────────────────────── */
/* S-MOBILE-CHROME-CLEANUP: normalised to match .btn-icon — transparent
   surface + hover-only fill. Previously had solid bg-card + 1px border
   that made chat + AI topbar buttons look like distinct boxed elements
   in the topbar group while theme / A+ / bell / avatar rendered flat. */
.chat-topbar-btn {
  position: relative;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
  border: none;
  background: transparent;
  color: var(--text-secondary);
  text-decoration: none;
  transition: background var(--transition-fast), color var(--transition-fast);
  flex-shrink: 0;
}
.chat-topbar-btn:hover {
  background: var(--bg-surface-2);
  color: var(--text-primary);
}
.chat-topbar-btn.has-unread {
  color: var(--color-accent);
}
.chat-badge {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 9px;
  background: var(--color-danger);
  color: #fff;
  font-size: 10px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--bg-page);
  pointer-events: none;
}

/* ── Full chat page layout ────────────────────────────────── */
.chat-page-content {
  padding: 0 !important;
  height: calc(100vh - 56px); /* 56px = topbar height */
  overflow: hidden;
}
.chat-layout {
  display: flex;
  height: 100%;
  background: var(--bg-page);
}

/* ── Left sidebar ────────────────────────────────────────── */
.chat-sidebar {
  width: 240px;
  flex-shrink: 0;
  background: var(--bg-sidebar);
  color: #c8c7c4;
  display: flex;
  flex-direction: column;
  border-right: 1px solid rgba(255,255,255,0.06);
  overflow-y: auto;
}
.chat-sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 14px 10px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.chat-sidebar-title {
  font-size: 15px;
  font-weight: 700;
  color: #fff;
}
.chat-sidebar-section {
  padding: 12px 0 4px;
}
.chat-sidebar-label {
  padding: 0 14px 4px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.07em;
  color: rgba(255,255,255,0.4);
  text-transform: uppercase;
}
.chat-sidebar-item {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 5px 14px;
  background: none;
  border: none;
  color: rgba(255,255,255,0.72);
  font-size: 13px;
  cursor: pointer;
  text-align: left;
  border-radius: 0;
  transition: background 0.1s, color 0.1s;
}
.chat-sidebar-item:hover,
.chat-sidebar-item.is-active {
  background: rgba(255,255,255,0.08);
  color: #fff;
}
.chat-sidebar-item.has-unread {
  color: #fff;
  font-weight: 600;
}
.chat-channel-hash {
  color: rgba(255,255,255,0.4);
  font-size: 14px;
  width: 14px;
  text-align: center;
  flex-shrink: 0;
}
.chat-dm-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #22c55e;
  flex-shrink: 0;
}
.chat-sidebar-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chat-unread-badge {
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 9px;
  background: var(--color-danger);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.chat-sidebar-browse {
  display: block;
  width: 100%;
  padding: 4px 14px;
  background: none;
  border: none;
  color: rgba(255,255,255,0.4);
  font-size: 12px;
  cursor: pointer;
  text-align: left;
}
.chat-sidebar-browse:hover { color: rgba(255,255,255,0.8); }

/* ── Main chat area ──────────────────────────────────────── */
.chat-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--bg-card);
}
.chat-empty-state {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  color: var(--text-muted);
}
.chat-empty-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
}
.chat-empty-sub { font-size: 13px; color: var(--text-secondary); }

.chat-channel-view {
  display: flex;
  flex-direction: column;
  height: 100%;
}

/* Channel header */
.chat-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border-color);
  background: var(--bg-card);
  flex-shrink: 0;
}
.chat-header-info {
  display: flex;
  align-items: center;
  gap: 6px;
}
.chat-header-hash {
  font-size: 18px;
  color: var(--text-muted);
}
.chat-header-name {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-primary);
}
.chat-header-desc {
  font-size: 12px;
  color: var(--text-secondary);
  margin-left: 4px;
}
.chat-header-actions { display: flex; gap: 4px; }

/* Search bar */
.chat-search-bar {
  border-bottom: 1px solid var(--border-color);
  padding: 8px 16px;
  background: var(--bg-muted);
  flex-shrink: 0;
  position: relative;
}
.chat-search-input {
  width: 100%;
  height: 32px;
  padding: 0 12px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  background: var(--bg-input);
  color: var(--text-primary);
  font-size: 13px;
}
.chat-search-results {
  position: absolute;
  left: 16px; right: 16px;
  top: 100%;
  z-index: 50;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  max-height: 300px;
  overflow-y: auto;
}
.chat-search-result {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 8px;
  align-items: center;
  padding: 8px 12px;
  cursor: pointer;
  border-bottom: 1px solid var(--border-color);
}
.chat-search-result:hover { background: var(--bg-hover); }
.chat-search-result-user { font-size: 11px; font-weight: 600; color: var(--text-secondary); }
.chat-search-result-msg  { font-size: 12px; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-search-result-time { font-size: 10px; color: var(--text-muted); }

/* Messages area */
.chat-messages-area {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.chat-load-more {
  text-align: center;
  padding: 8px 0 16px;
}
.chat-loading {
  padding: 16px 0;
}
.chat-channel-empty {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: 13px;
  padding: 32px;
}

/* Individual message */
.chat-message {
  display: flex;
  gap: 10px;
  padding: 4px 8px;
  border-radius: 6px;
  position: relative;
}
.chat-message:hover {
  background: var(--bg-hover);
}
.chat-message:hover .chat-message-actions {
  display: flex;
}
.chat-message--highlight {
  background: rgba(59,130,246,0.12) !important;
  transition: background 0.3s;
}
.chat-message--system {
  background: var(--bg-muted);
  border-left: 3px solid var(--border-strong);
  padding-left: 12px;
  margin: 4px 0;
}

/* Avatar */
.chat-avatar {
  width: 36px;
  height: 36px;
  border-radius: 8px;
  background: var(--color-accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  flex-shrink: 0;
  margin-top: 2px;
}

/* Message body */
.chat-message-body { flex: 1; min-width: 0; }
.chat-message-header {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 2px;
}
.chat-message-author {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-primary);
}
.chat-message-time {
  font-size: 11px;
  color: var(--text-muted);
}
.chat-edited-marker {
  font-size: 10px;
  color: var(--text-muted);
  font-style: italic;
}
.chat-message-text {
  font-size: 13px;
  color: var(--text-primary);
  line-height: 1.5;
  word-break: break-word;
}
.chat-message-deleted {
  font-size: 12px;
  color: var(--text-muted);
  font-style: italic;
}
.chat-mention {
  color: var(--color-accent);
  font-weight: 500;
}
.chat-link {
  color: var(--color-accent);
  text-decoration: underline;
}

/* Reply context */
.chat-reply-context {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 8px;
  margin-bottom: 4px;
  background: var(--bg-muted);
  border-left: 3px solid var(--color-accent);
  border-radius: 0 4px 4px 0;
  font-size: 11px;
}
.chat-reply-name { font-weight: 600; color: var(--text-primary); }
.chat-reply-text { color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 300px; }

/* Attachment card in message */
.chat-attachment-card {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
  padding: 10px 12px;
  background: var(--bg-muted);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  max-width: 380px;
}
.chat-attachment-icon { font-size: 20px; flex-shrink: 0; }
.chat-attachment-body { flex: 1; min-width: 0; }
.chat-attachment-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chat-attachment-sub {
  font-size: 11px;
  color: var(--text-secondary);
  margin-top: 1px;
}
.chat-attachment-link { flex-shrink: 0; }

/* Reactions */
.chat-reactions {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 4px;
}
.chat-reaction-btn {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 7px;
  border: 1px solid var(--border-color);
  border-radius: 12px;
  background: var(--bg-muted);
  font-size: 12px;
  cursor: pointer;
  transition: all 0.15s;
}
.chat-reaction-btn:hover { background: var(--bg-hover); border-color: var(--color-accent); }
.chat-reaction-btn.mine  { background: rgba(59,130,246,0.1); border-color: var(--color-accent); }
.chat-reaction-add {
  padding: 2px 6px;
  border: 1px dashed var(--border-color);
  border-radius: 12px;
  background: none;
  font-size: 11px;
  cursor: pointer;
  color: var(--text-muted);
}
.chat-reaction-add:hover { border-color: var(--color-accent); color: var(--color-accent); }

/* Message hover actions */
.chat-message-actions {
  display: none;
  position: absolute;
  top: 4px;
  right: 8px;
  gap: 2px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  padding: 2px 4px;
  box-shadow: var(--shadow-md);
  z-index: 10;
}
.chat-action-btn {
  padding: 3px 5px;
  background: none;
  border: none;
  cursor: pointer;
  border-radius: 4px;
  font-size: 13px;
  line-height: 1;
  color: var(--text-secondary);
}
.chat-action-btn:hover { background: var(--bg-hover); }
.chat-action-btn--danger:hover { background: var(--badge-danger-bg); }

/* Emoji picker */
.chat-emoji-picker {
  position: fixed;
  z-index: 200;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  padding: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  max-width: 200px;
  box-shadow: var(--shadow-lg);
  bottom: 120px;
  right: 16px;
}
.chat-emoji-btn {
  font-size: 20px;
  padding: 4px;
  background: none;
  border: none;
  cursor: pointer;
  border-radius: 4px;
}
.chat-emoji-btn:hover { background: var(--bg-hover); }

/* ── Compose area ────────────────────────────────────────── */
.chat-compose {
  border-top: 1px solid var(--border-color);
  padding: 10px 16px 12px;
  background: var(--bg-card);
  flex-shrink: 0;
  position: relative;
}
.chat-reply-banner {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  margin-bottom: 8px;
  background: var(--bg-muted);
  border-left: 3px solid var(--color-accent);
  border-radius: 0 6px 6px 0;
  font-size: 12px;
  color: var(--text-secondary);
}
.chat-reply-banner--edit { border-color: var(--color-warning); }
.chat-reply-preview {
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 300px;
}
.chat-reply-cancel {
  margin-left: auto;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-muted);
  font-size: 13px;
  padding: 0 4px;
}
.chat-reply-cancel:hover { color: var(--color-danger); }

/* Pending attachments */
.chat-pending-attachments {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 8px;
}
.chat-pending-att {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 4px 8px;
  background: var(--bg-muted);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  font-size: 12px;
}
.chat-pending-att-icon { font-size: 14px; }
.chat-pending-att-name { color: var(--text-primary); max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-pending-att-remove {
  background: none; border: none; cursor: pointer;
  color: var(--text-muted); font-size: 12px; padding: 0 2px;
}
.chat-pending-att-remove:hover { color: var(--color-danger); }

/* Mention dropdown */
.chat-mention-dropdown {
  position: absolute;
  bottom: 100%;
  left: 16px;
  right: 16px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  z-index: 100;
  max-height: 200px;
  overflow-y: auto;
}
.chat-mention-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 12px;
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  font-size: 13px;
  color: var(--text-primary);
}
.chat-mention-item:hover { background: var(--bg-hover); }
.chat-mention-avatar {
  width: 24px;
  height: 24px;
  border-radius: 4px;
  background: var(--color-accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 700;
  flex-shrink: 0;
}

/* Record picker */
.chat-record-picker {
  position: absolute;
  bottom: 100%;
  left: 16px;
  right: 16px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  z-index: 100;
  padding: 10px;
}
.chat-record-types {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.chat-record-type-btn {
  padding: 5px 10px;
  background: var(--bg-muted);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  font-size: 12px;
  cursor: pointer;
  color: var(--text-primary);
}
.chat-record-type-btn:hover { background: var(--bg-hover); border-color: var(--color-accent); }
.chat-record-search-header {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
}
.chat-record-search-input {
  flex: 1;
  height: 30px;
  padding: 0 10px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  background: var(--bg-input);
  color: var(--text-primary);
  font-size: 12px;
}
.chat-record-results {
  max-height: 180px;
  overflow-y: auto;
}
.chat-record-result {
  display: flex;
  flex-direction: column;
  width: 100%;
  padding: 6px 10px;
  background: none;
  border: none;
  border-bottom: 1px solid var(--border-color);
  cursor: pointer;
  text-align: left;
}
.chat-record-result:hover { background: var(--bg-hover); }
.chat-record-result-title { font-size: 13px; font-weight: 500; color: var(--text-primary); }
.chat-record-result-sub { font-size: 11px; color: var(--text-secondary); }
.chat-record-empty { padding: 12px; font-size: 12px; color: var(--text-muted); text-align: center; }

/* Compose input row */
.chat-compose-row {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  background: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  padding: 6px 8px;
  transition: border-color 0.15s;
}
.chat-compose-row:focus-within { border-color: var(--color-accent); }
.chat-compose-input {
  flex: 1;
  border: none;
  background: none;
  color: var(--text-primary);
  font-size: 13px;
  outline: none;
  line-height: 1.5;
  min-height: 22px;
  max-height: 160px;
  padding: 0;
  font-family: inherit;
}
.chat-compose-actions { display: flex; align-items: center; gap: 4px; }
.chat-attach-btn { color: var(--text-muted); }
.chat-attach-btn:hover { color: var(--color-accent); }
.chat-send-btn { padding: 6px 10px !important; height: 32px; }
.chat-compose-hint {
  margin-top: 5px;
  font-size: 10px;
  color: var(--text-muted);
}
.chat-compose-hint kbd {
  font-size: 10px;
  padding: 1px 4px;
  background: var(--bg-muted);
  border: 1px solid var(--border-color);
  border-radius: 3px;
  font-family: monospace;
}

/* ── Right info panel ────────────────────────────────────── */
.chat-info-panel {
  width: 280px;
  flex-shrink: 0;
  background: var(--bg-card);
  border-left: 1px solid var(--border-color);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}
.chat-info-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border-color);
  font-weight: 700;
  font-size: 14px;
}
.chat-info-desc {
  padding: 10px 14px;
  font-size: 12px;
  color: var(--text-secondary);
  border-bottom: 1px solid var(--border-color);
}
.chat-info-section { padding: 10px 14px; }
.chat-info-label {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 8px;
}
.chat-info-member {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  border-bottom: 1px solid var(--border-color);
  font-size: 12px;
}
.chat-info-member-avatar {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: var(--color-accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 700;
  flex-shrink: 0;
}
.chat-info-member-name { flex: 1; color: var(--text-primary); font-weight: 500; }
.chat-info-member-role { flex-shrink: 0; }

/* Browse channel modal items */
.chat-browse-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border-color);
}
.chat-browse-info { flex: 1; min-width: 0; }
.chat-browse-name { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.chat-browse-desc { font-size: 11px; color: var(--text-secondary); display: block; margin-top: 1px; }
.chat-browse-count { font-size: 10px; color: var(--text-muted); }

/* DM user picker */
.chat-dm-user-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 0;
  background: none;
  border: none;
  border-bottom: 1px solid var(--border-color);
  cursor: pointer;
  text-align: left;
  font-size: 13px;
  color: var(--text-primary);
}
.chat-dm-user-item:hover { color: var(--color-accent); }
.chat-dm-user-avatar {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: var(--color-accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  flex-shrink: 0;
}

/* ── Mini chat widget ────────────────────────────────────── */
.chat-widget {
  position: fixed;
  bottom: 20px;
  right: 20px;
  z-index: 300;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 12px;
}
.chat-widget-panel {
  width: 320px;
  height: 480px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: 16px;
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.chat-widget-enter { transition: all 0.2s ease; }
.chat-widget-enter-start { opacity: 0; transform: translateY(12px) scale(0.95); }
.chat-widget-enter-end   { opacity: 1; transform: translateY(0) scale(1); }
.chat-widget-leave { transition: all 0.15s ease; }
.chat-widget-leave-start { opacity: 1; transform: translateY(0); }
.chat-widget-leave-end   { opacity: 0; transform: translateY(8px); }

.chat-widget-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  background: var(--bg-sidebar);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  flex-shrink: 0;
  border-radius: 16px 16px 0 0;
}
.chat-widget-channels {
  flex: 1;
  overflow-y: auto;
  padding: 8px 0;
}
.chat-widget-section-label {
  padding: 4px 14px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.07em;
  color: var(--text-muted);
  text-transform: uppercase;
}
.chat-widget-channel-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 6px 14px;
  background: none;
  border: none;
  cursor: pointer;
  font-size: 12px;
  color: var(--text-primary);
  border-radius: 0;
}
.chat-widget-channel-item:hover { background: var(--bg-hover); }
.chat-widget-unread {
  min-width: 16px;
  height: 16px;
  padding: 0 3px;
  border-radius: 8px;
  background: var(--color-danger);
  color: #fff;
  font-size: 9px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}
.chat-widget-messages {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.chat-widget-message {}
.chat-widget-msg-header {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin-bottom: 2px;
}
.chat-widget-msg-author { font-size: 11px; font-weight: 700; color: var(--text-primary); }
.chat-widget-msg-time   { font-size: 10px; color: var(--text-muted); }
.chat-widget-msg-text   { font-size: 12px; color: var(--text-primary); line-height: 1.4; word-break: break-word; }
.chat-widget-msg-deleted { font-size: 11px; color: var(--text-muted); font-style: italic; }
.chat-widget-compose {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  padding: 8px 10px;
  border-top: 1px solid var(--border-color);
  flex-shrink: 0;
}
.chat-widget-input {
  flex: 1;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  background: var(--bg-input);
  color: var(--text-primary);
  font-size: 12px;
  padding: 5px 8px;
  outline: none;
  font-family: inherit;
  min-height: 30px;
  max-height: 80px;
}
.chat-widget-input:focus { border-color: var(--color-accent); }

/* Widget toggle button */
.chat-widget-toggle {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--color-accent);
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  box-shadow: var(--shadow-lg);
  transition: all 0.2s;
  position: relative;
  flex-shrink: 0;
}
.chat-widget-toggle:hover { background: var(--color-accent-hover); transform: scale(1.05); }
.chat-widget-toggle.has-unread { background: var(--color-danger); }
.chat-widget-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 9px;
  background: #fff;
  color: var(--color-danger);
  font-size: 10px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--color-danger);
  pointer-events: none;
}

/* Hide widget on full chat page */
.chat-page-content ~ * #ff-chat-widget,
body:has(.chat-page-content) #ff-chat-widget {
  display: none !important;
}

/* ============================================================
   MSGR-1 — Customer Messenger (admin side)
   Builds on .chat-* layout primitives. Adds Facebook-style
   thread rows, contact picker rows, and the admin/portal side
   labels that distinguish "Team" vs "Customer" messages.
   ============================================================ */
.msgr-thread-item {
  padding: 8px 12px !important;
  gap: 10px;
  align-items: flex-start !important;
}
.msgr-thread-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--color-accent);
  color: #fff;
  font-weight: 700;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  text-transform: uppercase;
}
.msgr-thread-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.msgr-thread-top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 6px;
}
.msgr-thread-name {
  font-weight: 600;
  font-size: 13px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
  min-width: 0;
}
.msgr-thread-time {
  font-size: 11px;
  color: rgba(255,255,255,0.4);
  flex-shrink: 0;
}
.msgr-thread-preview {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.msgr-thread-item.has-unread .msgr-thread-name,
.msgr-thread-item.has-unread .msgr-thread-preview {
  color: #fff;
  font-weight: 600;
}

/* Side labels — small "Team" / "Customer" pill on each message */
.msgr-side-label {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-left: 4px;
}
.msgr-side-label--admin {
  background: rgba(59,130,246,0.15);
  color: #3b82f6;
}
.msgr-side-label--portal {
  background: rgba(34,197,94,0.15);
  color: #22c55e;
}

/* Highlight portal customer messages with a faint left rail so admins
   can scan a long thread and see customer replies at a glance. */
.msgr-message--portal {
  background: rgba(34,197,94,0.04);
  border-left: 2px solid rgba(34,197,94,0.4);
}

/* ── New thread modal — contact picker rows ─────────────── */
.msgr-contact-list {
  max-height: 50vh;
  overflow-y: auto;
  padding-right: 4px;
}
.msgr-contact-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 12px;
  background: none;
  border: 1px solid transparent;
  border-radius: 8px;
  cursor: pointer;
  text-align: left;
  transition: background 0.1s, border-color 0.1s;
}
.msgr-contact-item:hover {
  background: var(--bg-hover);
  border-color: var(--border-color);
}
.msgr-contact-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--color-accent);
  color: #fff;
  font-weight: 700;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  text-transform: uppercase;
}
.msgr-contact-body {
  flex: 1;
  min-width: 0;
}
.msgr-contact-name {
  font-weight: 600;
  font-size: 14px;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.msgr-contact-sub {
  font-size: 12px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.msgr-contact-badge {
  flex-shrink: 0;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 10px;
  background: rgba(59,130,246,0.15);
  color: #3b82f6;
}
.msgr-contact-badge--user {
  background: rgba(168,85,247,0.15);
  color: #a855f7;
}

/* ============================================================
   MSGR-1 — Portal Messenger (customer side)
   Lighter, simpler 2-column layout. No dark sidebar.
   Customers can read + reply but not start new threads.
   ============================================================ */
.portal-msgr-page {
  padding: 0 !important;
  margin: 0 !important;
  max-width: none !important;
  width: 100%;
  height: calc(100vh - 56px); /* topbar */
  overflow: hidden;
}
.portal-content:has(> .portal-msgr-page) {
  padding: 0;
  max-width: none;
}
.portal-msgr-layout {
  display: flex;
  height: 100%;
  background: var(--bg-page);
}

/* ── Left sidebar — thread list ─────────────────────────── */
.portal-msgr-sidebar {
  width: 320px;
  flex-shrink: 0;
  background: var(--bg-card);
  border-right: 1px solid var(--border-color);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.portal-msgr-sidebar-header {
  padding: 18px 20px;
  border-bottom: 1px solid var(--border-color);
}
.portal-msgr-sidebar-title {
  font-size: 16px;
  font-weight: 700;
  color: var(--text-primary);
}
.portal-msgr-thread-list {
  flex: 1;
  overflow-y: auto;
  padding: 6px 0;
}
.portal-msgr-thread-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  width: 100%;
  padding: 12px 18px;
  background: none;
  border: none;
  border-left: 3px solid transparent;
  cursor: pointer;
  text-align: left;
  transition: background 0.1s, border-color 0.1s;
}
.portal-msgr-thread-item:hover {
  background: var(--bg-hover);
}
.portal-msgr-thread-item.is-active {
  background: var(--bg-hover);
  border-left-color: var(--color-accent);
}
.portal-msgr-thread-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--color-accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.portal-msgr-thread-avatar svg {
  width: 22px;
  height: 22px;
}
.portal-msgr-thread-avatar--lg {
  width: 44px;
  height: 44px;
}
.portal-msgr-thread-avatar--lg svg {
  width: 24px;
  height: 24px;
}
.portal-msgr-thread-body {
  flex: 1;
  min-width: 0;
}
.portal-msgr-thread-top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 2px;
}
.portal-msgr-thread-name {
  font-weight: 600;
  font-size: 14px;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
}
.portal-msgr-thread-time {
  font-size: 11px;
  color: var(--text-muted);
  flex-shrink: 0;
}
.portal-msgr-thread-preview {
  font-size: 13px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.portal-msgr-thread-prefix {
  color: var(--text-secondary);
  font-weight: 500;
}
.portal-msgr-thread-item.has-unread .portal-msgr-thread-name,
.portal-msgr-thread-item.has-unread .portal-msgr-thread-preview {
  color: var(--text-primary);
  font-weight: 600;
}
.portal-msgr-unread-badge {
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 10px;
  background: var(--color-danger);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-top: 10px;
}

/* ── Right pane — active thread ─────────────────────────── */
.portal-msgr-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--bg-page);
}
.portal-msgr-empty-state {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  text-align: center;
  padding: 40px;
}
.portal-msgr-empty-title {
  font-size: 17px;
  font-weight: 600;
  color: var(--text-primary);
  margin: 0;
}
.portal-msgr-empty-sub {
  font-size: 13px;
  color: var(--text-muted);
  margin: 0;
}
.portal-msgr-empty {
  padding: 32px 20px;
  text-align: center;
}

.portal-msgr-thread-view {
  display: flex;
  flex-direction: column;
  height: 100%;
}
.portal-msgr-thread-header {
  padding: 14px 20px;
  border-bottom: 1px solid var(--border-color);
  background: var(--bg-card);
  flex-shrink: 0;
}
.portal-msgr-thread-header-info {
  display: flex;
  align-items: center;
  gap: 14px;
}
.portal-msgr-thread-header-name {
  font-size: 16px;
  font-weight: 700;
  color: var(--text-primary);
}
.portal-msgr-thread-header-sub {
  font-size: 12px;
  color: var(--text-muted);
}

.portal-msgr-messages-area {
  flex: 1;
  overflow-y: auto;
  padding: 24px 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.portal-msgr-load-more {
  text-align: center;
  margin-bottom: 12px;
}
.portal-msgr-thread-empty {
  text-align: center;
  color: var(--text-muted);
  padding: 32px;
}

/* Message bubbles — Facebook Messenger style. Customer's own
   messages on the right, support team's messages on the left. */
.portal-msgr-message {
  display: flex;
  width: 100%;
  margin-bottom: 4px;
}
.portal-msgr-message--mine {
  justify-content: flex-end;
}
.portal-msgr-message--theirs {
  justify-content: flex-start;
}
.portal-msgr-message-bubble {
  max-width: 75%;
  padding: 9px 14px;
  border-radius: 18px;
  position: relative;
  word-wrap: break-word;
  font-size: 14px;
  line-height: 1.4;
}
.portal-msgr-message--mine .portal-msgr-message-bubble {
  background: var(--color-accent);
  color: #fff;
  border-bottom-right-radius: 4px;
}
.portal-msgr-message--theirs .portal-msgr-message-bubble {
  background: var(--bg-card);
  color: var(--text-primary);
  border: 1px solid var(--border-color);
  border-bottom-left-radius: 4px;
}
.portal-msgr-message-author {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 3px;
}
.portal-msgr-message-text {
  white-space: pre-wrap;
}
.portal-msgr-message-deleted {
  font-style: italic;
  opacity: 0.6;
  font-size: 13px;
}
.portal-msgr-message-time {
  font-size: 10px;
  margin-top: 4px;
  opacity: 0.7;
}
.portal-msgr-message--mine .portal-msgr-message-time {
  text-align: right;
}

/* Compose footer — sticky to the bottom of the messages pane */
.portal-msgr-compose {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  padding: 14px 20px;
  border-top: 1px solid var(--border-color);
  background: var(--bg-card);
  flex-shrink: 0;
}
.portal-msgr-compose-input {
  flex: 1;
  resize: none;
  overflow: hidden;
  border: 1px solid var(--border-color);
  border-radius: 20px;
  padding: 10px 16px;
  font-family: inherit;
  font-size: 14px;
  background: var(--bg-page);
  color: var(--text-primary);
  outline: none;
  min-height: 40px;
  max-height: 160px;
  transition: border-color 0.15s;
}
.portal-msgr-compose-input:focus {
  border-color: var(--color-accent);
}
.portal-msgr-send-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

/* Mobile — collapse sidebar to a top picker */
@media (max-width: 768px) {
  .portal-msgr-layout {
    flex-direction: column;
  }
  .portal-msgr-sidebar {
    width: 100%;
    max-height: 35vh;
    border-right: none;
    border-bottom: 1px solid var(--border-color);
  }
  .portal-msgr-message-bubble {
    max-width: 85%;
  }
}


/* ============================================================
   FF_RecordPicker — reusable search-as-you-type record selector
   Used by admin forms (invoices, leases, payments, maintenance,
   reservations, inspections, mileage, damage claims, credit notes)
   to replace static <select> dropdowns with a debounced autocomplete.
   ============================================================ */

.ff-picker                 { position: relative; width: 100%; }
.ff-picker-input           { width: 100%; padding-right: 36px; }
.ff-picker-input.is-selected {
    background-color: var(--bg-muted, rgba(0,0,0,.02));
    font-weight: 500;
}
.ff-picker-clear {
    position: absolute;
    right: 10px;
    top: 50%;
    transform: translateY(-50%);
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-muted);
    padding: 2px 6px;
    font-size: 14px;
    line-height: 1;
    border-radius: 4px;
}
.ff-picker-clear:hover {
    background: var(--bg-muted, rgba(0,0,0,.05));
    color: var(--text-primary);
}

.ff-picker-dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    margin-top: 4px;
    background: var(--bg-surface, #fff);
    border: 1px solid var(--border-color, #e0e0e0);
    border-radius: 8px;
    box-shadow: 0 6px 20px rgba(0,0,0,.12);
    z-index: 1000;
    max-height: 320px;
    overflow-y: auto;
}
.ff-picker-dropdown::-webkit-scrollbar { width: 6px; }
.ff-picker-dropdown::-webkit-scrollbar-thumb { background: var(--border-color, #e0e0e0); border-radius: 3px; }

.ff-picker-option {
    padding: 10px 14px;
    cursor: pointer;
    border-bottom: 1px solid var(--border-color, #f0f0f0);
    transition: background .08s;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.ff-picker-option:last-child { border-bottom: none; }
.ff-picker-option:hover,
.ff-picker-option.is-highlighted {
    background: var(--bg-muted, #f5f5f5);
}
.ff-picker-option-label {
    font-size: 14px;
    font-weight: 500;
    color: var(--text-primary);
}
.ff-picker-option-sub {
    font-size: 12px;
    color: var(--text-muted);
}
.ff-picker-option-badge {
    display: inline-block;
    font-size: 10px;
    padding: 1px 6px;
    border-radius: 3px;
    background: var(--bg-muted);
    color: var(--text-secondary);
    margin-left: 6px;
    vertical-align: middle;
}

.ff-picker-empty {
    padding: 14px;
    text-align: center;
    font-size: 13px;
    color: var(--text-muted);
}
.ff-picker-loading {
    padding: 10px 14px;
    font-size: 13px;
    color: var(--text-muted);
    display: flex;
    align-items: center;
    gap: 8px;
}
.ff-picker-loading::before {
    content: '';
    width: 12px;
    height: 12px;
    border: 2px solid var(--border-color);
    border-top-color: var(--color-accent);
    border-radius: 50%;
    animation: ff-picker-spin .8s linear infinite;
}
@keyframes ff-picker-spin {
    to { transform: rotate(360deg); }
}

/* ════════════════════════════════════════════════════════════════════
   UI-AUDIT-1 — Missing utility classes
   ────────────────────────────────────────────────────────────────────
   Source-scan audit turned up ~50 class names referenced in PHP files
   that had no CSS rule anywhere (not in app.css, not in inline <style>
   blocks). Some of them silently did nothing (heading variants, badge
   color modifiers); others caused visibly unstyled UI (modal close
   buttons, form-section wrappers, invalid-feedback error text).
   Rather than churn 100+ template files to rename classes, we define
   the missing selectors here so the templates start rendering correctly.
   WHY here and not inline: centralising them keeps the design tokens
   consistent and prevents per-page drift.
   ════════════════════════════════════════════════════════════════════ */

/* ── N1 — Heading utility classes ──────────────────────────────
   <h1 class="h4"> should render at h4 size, etc. CSS previously
   only defined the element selectors (h4 {}), so the class was inert. */
.h1 { font-size: 1.5rem;   line-height: 1.25; font-weight: 700; }
.h2 { font-size: 1.25rem;  line-height: 1.3;  font-weight: 700; }
.h3 { font-size: 1.125rem; line-height: 1.35; font-weight: 600; }
.h4 { font-size: 1rem;     line-height: 1.4;  font-weight: 600; }
.h5 { font-size: 0.9375rem;line-height: 1.4;  font-weight: 600; }
.h6 { font-size: 0.875rem; line-height: 1.4;  font-weight: 600; }

/* ── N2 — Form validation feedback ──────────────────────────────
   Bootstrap-style .invalid-feedback displayed under an invalid input.
   Used by rates/create.php and any form that wants inline per-field
   error text. */
.invalid-feedback {
    display: block;
    width: 100%;
    margin-top: 4px;
    font-size: 0.75rem;
    color: var(--color-danger-text);
    line-height: 1.4;
}
.valid-feedback {
    display: block;
    width: 100%;
    margin-top: 4px;
    font-size: 0.75rem;
    color: var(--color-success-text);
    line-height: 1.4;
}

/* ── N3 — Form section wrappers ──────────────────────────────
   Used by maintenance_work_orders/create.php to group related
   form fields under a subheading. Matches the existing .card look
   but without the outer border so it can nest inside a card. */
.form-section {
    margin-bottom: 24px;
    padding-bottom: 16px;
    border-bottom: 1px solid var(--border-color);
}
.form-section:last-child {
    border-bottom: 0;
    padding-bottom: 0;
    margin-bottom: 0;
}
.form-section-title {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--text-primary);
    margin: 0 0 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border-color);
}

/* ── Form control static (read-only display cell) ──────────────
   Bootstrap-style "form-control-static" — renders a value where an
   input would normally live without the input chrome. */
.form-control-static {
    display: block;
    padding: 8px 12px;
    font-family: inherit;
    font-size: 0.875rem;
    color: var(--text-primary);
    background: transparent;
    border: 0;
    min-height: 38px;
    line-height: 1.5;
}

/* ── N5 — Bare .btn-outline (used only in settings/system.php) ──
   The main outline variant we use elsewhere is .btn-outline-danger.
   Plain .btn-outline is a neutral outline button. */
.btn-outline {
    background: transparent;
    color: var(--text-primary);
    border: 1px solid var(--border-color-strong);
}
.btn-outline:hover {
    background: var(--bg-surface-2);
    border-color: var(--text-tertiary);
}

/* ── N7 — Additional badge variants ──────────────────────────────
   Some pages (accounting/fixed-assets, users/*, profile) use colour
   names we hadn't defined as badge variants. Add them as aliases of
   the semantic ones (blue=info, green=success, red=danger). */
.badge-blue   { background: var(--color-info-light);    color: var(--color-info-text);    }
.badge-green  { background: var(--color-success-light); color: var(--color-success-text); }
.badge-red    { background: var(--color-danger-light);  color: var(--color-danger-text);  }
.badge-yellow { background: var(--color-warning-light); color: var(--color-warning-text); }
.badge-gray   { background: rgba(148, 163, 184, 0.12);  color: var(--text-secondary);     }

/* Pill-shaped badge (fully rounded) — used on profile/users pages. */
.badge-pill {
    border-radius: 999px;
    padding-left: 10px;
    padding-right: 10px;
}

/* Smaller badge variant for inline list display. */
.badge-sm {
    font-size: 0.6875rem;
    padding: 1px 6px;
    line-height: 1.4;
}

/* ── Missing table utility classes ──────────────────────────────
   .table-hover — row hover highlight (4 files use this).
   .table-sm    — compact vertical padding.
   .table-row-link — make whole <tr> look clickable when used with @click.
   .table-pagination — style for pagination control row under a table. */
.table-hover tbody tr:hover {
    background: var(--bg-surface-hover);
    transition: background-color var(--transition-fast);
}
.table-sm th,
.table-sm td {
    padding-top: 6px;
    padding-bottom: 6px;
    font-size: 0.8125rem;
}
.table-row-link {
    cursor: pointer;
}
.table-row-link:hover {
    background: var(--bg-surface-hover);
}
.table-pagination {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 16px;
    border-top: 1px solid var(--border-color);
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

/* ── Breadcrumb ─────────────────────────────────────────────────
   Generic breadcrumb item — used across several detail pages. */
.breadcrumb {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.8125rem;
    color: var(--text-tertiary);
    margin-bottom: 12px;
}
.breadcrumb-item {
    color: var(--text-tertiary);
    text-decoration: none;
}
.breadcrumb-item:hover {
    color: var(--text-secondary);
}
.breadcrumb-item + .breadcrumb-item::before {
    content: '/';
    margin: 0 6px;
    color: var(--text-tertiary);
}
.breadcrumb-item.is-active {
    color: var(--text-primary);
    font-weight: 500;
}

/* ── Toolbar row (generic flex row with left/right groups) ─────
   Used by filter bars on list pages that didn't adopt the
   .table-toolbar naming. Alias .toolbar → flexible spacer layout. */
.toolbar {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}
.toolbar-left {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1 1 auto;
    min-width: 0;
}
.toolbar-right {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
}

/* Filter-bar BEM variants (2 files used these modifier names). */
.filter-bar__left  { display: flex; align-items: center; gap: 8px; }
.filter-bar__right { display: flex; align-items: center; gap: 8px; margin-left: auto; }

/* ── Sort link (clickable table header) ────────────────────────── */
.sort-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--text-secondary);
    text-decoration: none;
    font-weight: 600;
    cursor: pointer;
}
.sort-link:hover { color: var(--text-primary); }
.sort-link.is-active { color: var(--text-primary); }

/* ── Tab button (non-FF flavoured tab trigger) ─────────────────
   Alias for the .tab-btn pattern already used elsewhere so a single
   legacy template keeps working. */
.tab-button {
    background: transparent;
    border: 0;
    padding: 8px 14px;
    font-size: 0.875rem;
    color: var(--text-secondary);
    cursor: pointer;
    border-bottom: 2px solid transparent;
    transition: color var(--transition-fast), border-color var(--transition-fast);
}
.tab-button:hover { color: var(--text-primary); }
.tab-button.is-active {
    color: var(--color-primary);
    border-bottom-color: var(--color-primary);
    font-weight: 600;
}
.tab-count {
    display: inline-block;
    margin-left: 4px;
    padding: 1px 6px;
    font-size: 0.6875rem;
    background: var(--bg-surface-2);
    color: var(--text-tertiary);
    border-radius: 999px;
}

/* ── Spinner (text-mode loading indicator) ─────────────────────
   Used in 11 files. Small inline spinning circle. */
.spinner {
    display: inline-block;
    width: 16px;
    height: 16px;
    border: 2px solid var(--border-color);
    border-top-color: var(--color-primary);
    border-radius: 50%;
    animation: ff-picker-spin 0.8s linear infinite;
    vertical-align: middle;
}
.spinner-sm { width: 12px; height: 12px; border-width: 2px; }
.spinner-lg { width: 28px; height: 28px; border-width: 3px; }

/* ── Skeleton loading cell ─────────────────────────────────────
   For placeholder rows while data is loading. */
.skeleton-cell {
    display: inline-block;
    width: 100%;
    height: 14px;
    background: linear-gradient(90deg,
        var(--bg-surface-2) 0%,
        var(--bg-surface-hover) 50%,
        var(--bg-surface-2) 100%);
    background-size: 200% 100%;
    border-radius: 4px;
    animation: ff-skeleton-shimmer 1.2s ease-in-out infinite;
}
@keyframes ff-skeleton-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* ── Notif list card (inbox-style list row) ─────────────────── */
.notif-list-card {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md, 8px);
    padding: 0;
}

/* ── Detail grid / field-value pair ────────────────────────────
   Used in a few show pages that render "Label: Value" rows without
   going through the <dl> pattern. */
.detail-grid {
    display: grid;
    grid-template-columns: minmax(140px, 220px) 1fr;
    gap: 8px 16px;
    font-size: 0.875rem;
}
.field-value {
    color: var(--text-primary);
    font-weight: 500;
}
.spec-label {
    color: var(--text-secondary);
    font-weight: 500;
}
.spec-value {
    color: var(--text-primary);
    font-weight: 500;
}

/* ── Text helpers that were missing ──────────────────────────── */
.text-info  { color: var(--color-info-text);  }
.text-link  { color: var(--color-primary-text); text-decoration: none; }
.text-link:hover { text-decoration: underline; }

/* Toast error alias (some templates still use .toast-error — the
   primary variant we ship is .toast-danger). */
.toast-error { /* alias */ }
.toast-error .toast-icon { color: var(--color-danger-text); }

/* ── Page title helper ─────────────────────────────────────── */
.page-title {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0 0 8px;
}

/* ── Photo thumbnail square ─────────────────────────────────── */
.photo-thumb {
    width: 80px;
    height: 80px;
    object-fit: cover;
    border-radius: var(--radius-md, 8px);
    border: 1px solid var(--border-color);
    background: var(--bg-surface-2);
}

/* ── Generic stepper step wrapper (non-FF flavour) ─────────── */
.step {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

/* ── Activity-log section header helper ─────────────────────── */
.activity-log-section {
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid var(--border-color);
}

/* ── Inline role form (settings/users inline role dropdown) ─── */
.inline-role-form {
    display: inline-block;
}
.inline-role-form select {
    min-width: 140px;
}

/* ── Email compose chips / rate explanation card ──────────── */
.rate-explanation-body {
    padding: 12px 16px;
    background: var(--bg-surface-2);
    border-radius: var(--radius-md, 8px);
    font-size: 0.8125rem;
    color: var(--text-secondary);
    line-height: 1.5;
}

/* ────────── UI-AUDIT-1 END ────────── */


/* ============================================================
   S-LEASE-UNITS — Apple-style segmented control tokens
   ────────────────────────────────────────────────────────────
   Convention: FleetForge defaults to dark mode at :root, with
   [data-theme="light"] overriding for light mode (opposite of
   the Apple spec literal text, but matches FleetForge's existing
   token system). Active pill is a grayscale "elevated" surface
   (white pill on light track / mid-gray pill on dark track) —
   no brand orange (D-D).
   ============================================================ */

:root {
    --segment-track-bg:        rgba(118, 118, 128, 0.24);
    --segment-active-bg:        #636366;
    --segment-active-shadow:    0 3px 8px rgba(0, 0, 0, 0.32),
                                0 1px 2px rgba(0, 0, 0, 0.18);
    --segment-active-text:      rgba(255, 255, 255, 1);
    --segment-inactive-text:    rgba(235, 235, 245, 0.6);
}

[data-theme="light"] {
    --segment-track-bg:        rgba(118, 118, 128, 0.12);
    --segment-active-bg:        #FFFFFF;
    --segment-active-shadow:    0 3px 8px rgba(0, 0, 0, 0.12),
                                0 1px 2px rgba(0, 0, 0, 0.04);
    --segment-active-text:      rgba(0, 0, 0, 1);
    --segment-inactive-text:    rgba(60, 60, 67, 0.6);
}

/* The control itself */
.ff-segment-control {
    position: relative;
    display: inline-flex;
    width: 320px;
    height: 44px;
    background: var(--segment-track-bg);
    border-radius: 9px;
    padding: 2px;
    user-select: none;
}

.ff-segment-control__pill {
    position: absolute;
    top: 2px;
    left: 2px;
    width: calc(50% - 2px);
    height: calc(100% - 4px);
    background: var(--segment-active-bg);
    border-radius: 7px;
    box-shadow: var(--segment-active-shadow);
    transition: transform 0.25s cubic-bezier(0.4, 0.0, 0.2, 1);
    z-index: 0;
    pointer-events: none;
}

.ff-segment-control__pill--right {
    transform: translateX(100%);
}

.ff-segment-control__option {
    position: relative;
    z-index: 1;
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 500;
    letter-spacing: -0.01em;
    cursor: pointer;
    transition: color 0.15s ease;
    color: var(--segment-inactive-text);
    border-radius: 7px;
    outline: none;
}

.ff-segment-control__option--active {
    color: var(--segment-active-text);
}

.ff-segment-control__option:focus-visible {
    box-shadow: 0 0 0 2px var(--color-primary);
}

/* Secondary unit fields render slightly muted; full opacity on hover/focus */
.ff-field-secondary {
    opacity: 0.85;
    transition: opacity 0.15s ease;
}

.ff-field-secondary:hover,
.ff-field-secondary:focus-within {
    opacity: 1;
}

/* Lightweight collapsible (used for "Conversion factor" panel).
   x-show toggles display; we avoid the @alpinejs/collapse plugin. */
.ff-collapsible-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: none;
    color: var(--text-secondary);
    font-size: 0.875rem;
    font-weight: 500;
    cursor: pointer;
    padding: 4px 0;
}

.ff-collapsible-toggle:hover {
    color: var(--text-primary);
}

.ff-collapsible-chevron {
    display: inline-block;
    font-size: 0.75rem;
    transition: transform 0.15s ease;
}

.ff-collapsible-chevron--open {
    transform: rotate(90deg);
}

.ff-collapsible-content {
    margin-top: 12px;
    padding: 16px;
    background: var(--bg-muted);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md, 8px);
}

.ff-link-button {
    background: none;
    border: none;
    color: var(--color-primary-text);
    font-size: 0.8125rem;
    cursor: pointer;
    padding: 0;
}

.ff-link-button:hover {
    text-decoration: underline;
}

/* Dual-unit "Per-unit rate" / "Allowance" wrapper labels */
.ff-dual-label {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 8px;
    letter-spacing: -0.005em;
}

.ff-dual-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    margin-bottom: 24px;
}

@media (max-width: 540px) {
    .ff-segment-control { width: 100%; max-width: 320px; }
    .ff-dual-grid { grid-template-columns: 1fr; gap: 12px; }
}

/* show.php read-only variant — primary prominent, secondary muted */
.ff-show-primary {
    font-family: var(--font-mono, 'DM Mono', monospace);
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--text-primary);
    letter-spacing: -0.01em;
}

.ff-show-secondary {
    font-family: var(--font-mono, 'DM Mono', monospace);
    font-size: 0.8125rem;
    color: var(--text-muted);
    margin-top: 2px;
}

.ff-show-caption {
    font-size: 0.75rem;
    color: var(--text-muted);
    font-family: var(--font-mono, 'DM Mono', monospace);
    margin-top: 12px;
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.ff-badge-custom {
    display: inline-block;
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--color-warning-text, #b45309);
    background: var(--color-warning-light, #fef3c7);
    padding: 2px 8px;
    border-radius: 4px;
    letter-spacing: 0.02em;
}
/* ────────── S-LEASE-UNITS END ────────── */

/* ────────── S-PERM-USERS-ACCESS-WALL ──────────
   Custom developer-only access wall, rendered inside the normal
   admin shell (sidebar + topbar) for the Users module when the
   current viewer is not super_admin. See app/admin/users/*.php
   gate blocks. */
.access-wall {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 80px 24px;
    max-width: 480px;
    margin: 0 auto;
}
.access-wall-icon {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    background: var(--bg-surface-2, #1e293b);
    border: 1px solid var(--border-color);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 24px;
    color: var(--text-muted);
}
.access-wall-title {
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--text-primary);
    margin: 0 0 12px;
}
.access-wall-message {
    font-size: 0.9375rem;
    color: var(--text-muted);
    line-height: 1.75;
    margin: 0 0 28px;
}
/* ────────── S-PERM-USERS-ACCESS-WALL END ────────── */

/* ════════════════════════════════════════════════════════════════════
   S-DASHBOARD-MOBILE-LAYOUT
   1. KPI tiles: 3-up tablet / 2-up mobile (dashboard only — scoped via
      #kpi-grid so other .stat-grid usages keep their auto-fit cadence).
   2. Active Leases card: horizontal scroll + height cap + only first
      4 rows visible on mobile so it doesn't dominate the page.
   ════════════════════════════════════════════════════════════════════ */

/* ── FIX 1: KPI tile grid at tablet (768-1023px) ── */
@media (max-width: 1023px) {
    .stat-grid#kpi-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 10px;
    }
}

/* ── FIX 1: KPI tile grid at mobile (≤767px) — and chrome tweaks
        to fit content cleanly in the 2-up footprint. Class names
        adapted from the spec to match the codebase (.stat-card not
        .kpi-card, .stat-value not .kpi-value, .stat-card__icon not
        .kpi-icon-wrap). ── */
@media (max-width: 767px) {
    .stat-grid#kpi-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 10px;
    }
    #kpi-grid .stat-card {
        /* Tighter than desktop 14/16/14/22; left padding kept ≥16px
           so text doesn't collide with the 4px accent bar. */
        padding: 12px 12px 12px 18px;
    }
    #kpi-grid .stat-value {
        /* Smaller value font so common amounts like $1,234,567.89
           don't trigger text-overflow:ellipsis in the narrow tile.
           Spec asked 1.5rem but that's larger than the desktop 1.375rem
           and would clip on iPhone SE (320px); 1.125rem keeps every
           realistic KPI value on one line. */
        font-size: 1.125rem;
    }
    #kpi-grid .stat-label {
        font-size: 0.625rem;       /* 10px — was 11px */
        padding-right: 32px;       /* room for the icon at right */
        margin-bottom: 4px;
    }
    #kpi-grid .stat-card__icon {
        width: 28px;
        height: 28px;
    }
    #kpi-grid .stat-card__icon svg {
        width: 14px;
        height: 14px;
    }
    #kpi-grid .stat-delta {
        font-size: 0.6875rem;
    }
}

/* FIX 2 (mobile table scroll for .dashboard-leases-card) removed —
   S-DASHBOARD-MOBILE-CAROUSEL replaced the Active Leases table with a
   carousel, so the .dashboard-leases-card class is no longer present
   in the dashboard markup and these rules had no targets. */
/* ════════════════════════════════════════════════════════════════════
   S-DASHBOARD-MOBILE-LAYOUT END (KPI grid responsive rules above
   remain in force; only the leases-table-scroll block was dropped.)
   ════════════════════════════════════════════════════════════════════ */

/* ════════════════════════════════════════════════════════════════════
   S-DASHBOARD-MOBILE-CAROUSEL
   Horizontal scroll carousel for Active Leases + Pending Activations.
   Each lease/contract becomes one .carousel-card with labelled rows.
   ════════════════════════════════════════════════════════════════════ */

/* ── Dashboard section header (lighter than .card.card-header) ── */
.dashboard-section {
    margin-bottom: 44px;
    /* WHY min-width:0: Pending Activations lives inside the
       .dashboard-grid--widgets 2-column grid on desktop. Without this,
       the carousel's wide flex children would push the grid cell wider
       than its 1fr allowance, defeating overflow-x:auto. */
    min-width: 0;
}
/* Section header: 2px left accent matches the card's 2px top accent —
   same visual language, horizontal on card / vertical on heading. */
.dashboard-section-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: 18px;
    padding: 0 0 14px 14px;
    gap: 16px;
    border-left: 2px solid var(--color-primary);
    border-bottom: 1px solid var(--border-color);
}
/* Title: uppercase, readable size, secondary color */
.dashboard-section-title {
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-secondary);
    margin: 0;
    flex: 1;
}
.dashboard-section-viewall {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
    text-decoration: none;
    white-space: nowrap;
    transition: color 150ms ease;
}
.dashboard-section-viewall:hover {
    color: var(--color-primary);
    text-decoration: none;
}

/* ── Carousel container ───────────────────────────────────────── */
.dashboard-carousel {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    /* WHY overflow-y:visible not hidden: the micro-tilt perspective transform
       on hover can push card edges fractionally outside the container bounds;
       visible lets them breathe without clipping. */
    overflow-y: visible;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;      /* Firefox */
    padding-bottom: 8px;
    padding-top: 6px;           /* breathing room above first card */
}
.dashboard-carousel::-webkit-scrollbar {
    display: none;              /* Chrome / Safari */
}

/* ══ CAROUSEL CARDS — Maison-level redesign ══════════════════════════
   Zero shadows. Zero sheens. Zero glows. Typography and white-space
   carry all the weight — Apple / Louis Vuitton / Chanel restraint.
   The only ornament: a 2px brand-color top border, like a silk ribbon.
   ═══════════════════════════════════════════════════════════════════ */
.carousel-card {
    flex: 0 0 300px;
    scroll-snap-align: start;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 14px;
    padding: 28px 28px 24px;
    display: flex;
    flex-direction: column;
    gap: 0;
    min-height: 290px;
    position: relative;
    transition:
        transform    200ms cubic-bezier(0.23, 1, 0.32, 1),
        border-color 200ms ease;
}
/* No ::before, no ::after — not a single pixel of shadow or glow */
.carousel-card--link {
    text-decoration: none;
    color: inherit;
    cursor: pointer;
}
/* Hover: border highlights in theme color. JS micro-tilt (rotateX/rotateY
   ±5°) provides physical depth. No translateY, no scale, no movement. */
.carousel-card--link:hover {
    border-color: var(--color-primary);
    text-decoration: none;
}
.carousel-card--link:active {
    opacity: 0.85;
    transition-duration: 60ms;
}

/* ── Top row: ref code + status indicator ────────────────────── */
.cc-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 22px;
    gap: 10px;
}
/* Monospace ref — catalog / serial-number aesthetic */
.cc-id {
    font-family: 'DM Mono', monospace;
    font-size: 0.625rem;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex: 1;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
/* Status indicator: dot + uppercase label — no pill background.
   A 5px color dot is enough; a filled badge is visual noise. */
.cc-pill {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 0.5625rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    white-space: nowrap;
}
.cc-pill::before {
    content: '';
    display: block;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
}
.cc-pill--active  { color: #4ade80; }
.cc-pill--danger  { color: #f87171; }
.cc-pill--warning { color: #fbbf24; }
.cc-pill--info    { color: #7dd3fc; }

/* ── Customer — dominant editorial text ──────────────────────── */
.cc-customer {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--text-primary);
    line-height: 1.3;
    margin-bottom: 4px;
    /* Allow up to 2 lines, then ellipsis */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    /* Remove white-space:nowrap — let it wrap */
    word-break: break-word;
}

/* ── Equipment — catalog reference line ──────────────────────── */
.cc-equipment {
    font-size: 0.625rem;
    color: var(--text-muted);
    margin-bottom: 24px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.cc-dot { margin: 0 6px; opacity: 0.3; }

/* ── Divider — hairline rule ─────────────────────────────────── */
.cc-divider { height: 1px; background: var(--border-color); margin-bottom: 22px; }

/* ── Rate — the price-tag moment ─────────────────────────────── */
.cc-rate {
    flex: 1;
    display: flex;
    align-items: baseline;
    margin-bottom: 22px;
}
/* Light weight at large size = Louis Vuitton price-tag aesthetics */
.cc-rate-amount {
    font-size: 2.625rem;
    font-weight: 300;
    color: var(--text-primary);
    letter-spacing: -0.04em;
    line-height: 1;
}
/* Period unit: all-caps label like a spec sheet */
.cc-rate-period {
    font-size: 0.5625rem;
    color: var(--text-muted);
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    margin-left: 7px;
    align-self: flex-end;
    margin-bottom: 5px;
}

/* ── Footer ──────────────────────────────────────────────────── */
.cc-footer {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: 12px;
    margin-top: auto;
    padding-top: 18px;
    border-top: 1px solid var(--border-color);
}
.cc-footer-item { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cc-footer-item--right { text-align: right; align-items: flex-end; }
.cc-footer-label {
    font-size: 0.5rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--text-muted);
}
.cc-footer-value {
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    letter-spacing: -0.01em;
}

/* ── Empty / loading / error state ────────────────────────────── */
.carousel-empty {
    font-size: 0.875rem;
    color: var(--text-muted);
    padding: 24px 4px;
}

/* ── Responsive card widths ──────────────────────────────────── */
@media (max-width: 767px) {
    .dashboard-carousel {
        /* Right padding creates space so last card doesn't
           bleed to edge, revealing next card peek */
        padding-right: 20px;
        /* Scroll padding aligns cards to left edge */
        scroll-padding-left: 16px;
    }
    .carousel-card {
        /* 78vw = card takes 78% of screen width,
           leaving ~22% visible for gap + next card peek.
           Guaranteed regardless of screen size. */
        flex: 0 0 78vw;
        max-width: 320px; /* cap on larger phones/tablets */
        min-width: 220px; /* floor on very small screens */
    }
}
@media (min-width: 768px) {
    .carousel-card {
        flex: 0 0 340px;
    }
}
@media (min-width: 1280px) {
    .carousel-card {
        flex: 0 0 380px;
    }
}
/* ════════════════════════════════════════════════════════════════════
   S-DASHBOARD-MOBILE-CAROUSEL END
   ════════════════════════════════════════════════════════════════════ */
