/* ===================================================
   LawnBeast V2 — Shared Base Styles
   Extracted from css/reports/dashboard.css
   Used by all V2 pages (reports, customer list, etc.)
   =================================================== */

/* ===== VARIABLES ===== */
:root {
    --bg: #f4f6f4;
    --surface: #ffffff;
    --surface-hover: #fafbfa;
    --surface-alt: #f0f2f5;
    --border: #dce0db;
    --border-light: #e9ece8;
    --text: #1a1f1c;
    --text-secondary: #4a5248;
    --text-muted: #6b7a6d;
    --accent: #4e964f;
    --accent-dark: #3d7a3e;
    --accent-bg: #e8f5e9;
    --accent-subtle: #f5faf5;
    --positive: #2e7d32;
    --positive-bg: #c8e6c9;
    --negative: #c62828;
    --negative-bg: #ffcdd2;
    --warning: #ef6c00;
    --warning-bg: #ffe0b2;
    --sidebar-bg: #4e964f;
    --sidebar-text: #ffffff;
    --sidebar-text-muted: rgba(255,255,255,0.6);
    --sidebar-hover: #3d7a3e;
    --sidebar-active: #2d5a2e;
    --chart-primary: #4e964f;
    --chart-secondary: #81c784;
    --chart-tertiary: #c8e6c9;
    --sidebar-width: 200px;
    --sidebar-collapsed: 48px;

    --blue: #5b8def;
    --blue-light: #8fb4f8;
    --teal: #2bb5a0;
    --cta-coral: #f0653f;
    --cta-coral-dark: #d84f2b;
    --cta-violet: #7c5cff;
    --cta-violet-dark: #6544e0;
    --tooltip-bg: #1e2620;

    --shadow-xs: 0 1px 2px rgba(30, 38, 32, 0.04);
    --shadow-sm: 0 1px 3px rgba(30, 38, 32, 0.06), 0 1px 2px rgba(30, 38, 32, 0.04);
    --shadow-md: 0 4px 6px rgba(30, 38, 32, 0.05), 0 2px 4px rgba(30, 38, 32, 0.03);
    --shadow-lg: 0 10px 15px rgba(30, 38, 32, 0.06), 0 4px 6px rgba(30, 38, 32, 0.04);

    --transition-fast: 120ms ease;
    --transition-normal: 200ms ease;
}

/* ===== RESET ===== */
* { margin: 0; padding: 0; box-sizing: border-box; }

body {
    font-family: 'IBM Plex Sans', -apple-system, sans-serif;
    background: var(--bg);
    color: var(--text);
    font-size: 13px;
    line-height: 1.4;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

html { scroll-behavior: smooth; }
.layout { display: flex; min-height: 100vh; }

/* ===== SIDEBAR ===== */
.sidebar {
    width: var(--sidebar-width);
    background: var(--sidebar-bg);
    display: flex;
    flex-direction: column;
    position: fixed;
    top: 0;
    left: 0;
    height: 100vh;
    height: 100dvh;
    z-index: 100;
    transition: width var(--transition-normal), transform var(--transition-normal);
    -webkit-overflow-scrolling: touch;
}

/* --- Collapsed state --- */
.sidebar.collapsed { width: var(--sidebar-collapsed); overflow: visible; cursor: pointer; }
.sidebar.collapsed .nav-text,
.sidebar.collapsed .nav-section-title,
.sidebar.collapsed .sidebar-brand-text,
.sidebar.collapsed .sidebar-footer-text,
.sidebar.collapsed .nav-badge { display: none; }
.sidebar.collapsed .nav-item { justify-content: center; padding: 0.5rem; }
.sidebar.collapsed .nav-item i { margin: 0; font-size: 1.1rem; }
.sidebar.collapsed .sidebar-header { justify-content: center; padding: 0.5rem 0.25rem; }
.sidebar.collapsed .sidebar-brand img { width: 32px; }
.sidebar.collapsed .collapse-btn { margin: 0; display: none; }
.sidebar.collapsed:hover .sidebar-brand { display: none; }
.sidebar.collapsed:hover .collapse-btn { display: flex; margin: 0; }
.sidebar.collapsed .sidebar-footer .nav-item { gap: 0; }
.sidebar.collapsed .sidebar-footer { padding: 0.375rem 0.25rem; }
.sidebar.collapsed .sidebar-nav { overflow: visible; }

/* --- Sidebar header --- */
.sidebar-header {
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid rgba(255,255,255,0.2);
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 52px;
    flex-shrink: 0;
    cursor: pointer;
}

.sidebar-brand {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: 700;
    font-size: 1rem;
    color: #fff;
    text-decoration: none;
    transition: opacity var(--transition-fast);
    cursor: pointer;
}

.sidebar-brand:hover { opacity: 0.9; }
.sidebar-brand img {
    width: 48px;
    height: auto;
    object-fit: contain;
    flex-shrink: 0;
}

.collapse-btn {
    background: rgba(255,255,255,0.15);
    border: none;
    color: #fff;
    cursor: pointer;
    padding: 0.25rem;
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all var(--transition-fast);
}

.collapse-btn:hover {
    background: rgba(255,255,255,0.25);
    transform: scale(1.05);
}

/* --- Sidebar nav --- */
.sidebar-nav { flex: 1; overflow-y: auto; padding: 0.5rem 0; min-height: 0; -webkit-overflow-scrolling: touch; }
.nav-section { padding: 0 0.375rem; margin-bottom: 0.125rem; }

.nav-section-title {
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: rgba(255,255,255,0.75);
    padding: 0.625rem 0.5rem 0.375rem;
    font-weight: 700;
}

.nav-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.5rem;
    color: var(--sidebar-text);
    text-decoration: none;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 500;
    transition: all var(--transition-fast);
    cursor: pointer;
    position: relative;
}

.nav-item::before {
    content: '';
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%) scaleY(0);
    width: 4px;
    height: 70%;
    background: #fff;
    border-radius: 0 3px 3px 0;
    transition: transform var(--transition-fast);
}

.nav-item:hover {
    background: var(--sidebar-hover);
    color: #fff;
    padding-left: 0.875rem;
}

.nav-item.active {
    background: var(--sidebar-active);
    color: #fff;
}

.nav-item.active::before { transform: translateY(-50%) scaleY(1); }
.nav-item i { width: 16px; text-align: center; font-size: 0.875rem; opacity: 0.75; transition: opacity var(--transition-fast); }
.nav-item:hover i,
.nav-item.active i { opacity: 1; }

/* --- Nav badges --- */
.nav-badge {
    margin-left: auto;
    align-self: center;
    font-family: 'IBM Plex Mono', monospace;
    font-size: 10px;
    padding: 0.15rem 0.4rem;
    border-radius: 10px;
    background: rgba(255,255,255,0.25);
    color: #fff;
    font-weight: 500;
    transition: all var(--transition-fast);
    line-height: 1.2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.nav-item:hover .nav-badge { background: rgba(255,255,255,0.35); color: #fff; }

.nav-badge.count {
    background: rgba(255,255,255,0.15);
    color: rgba(255,255,255,0.8);
    font-size: 9px;
}

.nav-badge.alert {
    background: #dc3545;
    color: #fff;
    box-shadow: 0 0 0 2px rgba(255,255,255,0.4);
    animation: pulse-badge 2s infinite;
    margin-bottom: 0;
}

@keyframes pulse-badge {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.7; }
}

.nav-item-back { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: #fff; }
.nav-item-back i { opacity: 1; }

/* --- Disabled nav items --- */
.nav-item.disabled {
    opacity: 0.55;
    cursor: default;
    pointer-events: none;
}

.nav-item.disabled:hover {
    background: transparent;
    padding-left: 0.5rem;
}

.nav-badge.coming-soon {
    background: rgba(255,255,255,0.18);
    color: rgba(255,255,255,0.75);
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.03em;
}

/* --- Collapsed tooltips --- */
.sidebar.collapsed .nav-item[data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    left: calc(100% + 8px);
    top: 50%;
    transform: translateY(-50%);
    background: var(--tooltip-bg);
    color: #fff;
    font-size: 12px;
    font-weight: 500;
    font-family: 'IBM Plex Sans', sans-serif;
    padding: 6px 10px;
    border-radius: 6px;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--transition-fast);
    box-shadow: 0 4px 12px rgba(30, 38, 32, 0.3);
    z-index: 300;
}
.sidebar.collapsed .nav-item[data-tooltip]:hover::after {
    opacity: 1;
}

.nav-divider { height: 1px; background: rgba(255,255,255,0.12); margin: 0.125rem 0.5rem; }

/* --- Sidebar footer --- */
.sidebar-footer { padding: 0.5rem; border-top: 1px solid rgba(255,255,255,0.2); flex-shrink: 0; position: relative; }
.sidebar-footer .nav-divider { margin: 0.375rem 0.25rem; }

/* --- Sidebar user --- */
.user-avatar {
    position: relative;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: rgba(255,255,255,0.2);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    font-weight: 700;
    color: #fff;
    flex-shrink: 0;
}

/* Unread-notification indicator — rides on the avatar so it stays visible with
   the user menu closed and with the sidebar collapsed. */
.user-avatar-dot {
    position: absolute;
    top: -1px;
    right: -1px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--negative);
    border: 2px solid var(--sidebar-bg);
    box-sizing: content-box;
    animation: pulse-badge 2s infinite;
}

.sidebar-footer-text { line-height: 1.2; overflow: hidden; }
.user-name { font-size: 12px; font-weight: 600; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; }
.user-email { font-size: 10px; opacity: 0.6; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; }

/* ===== MAIN CONTENT ===== */
.main-wrapper {
    flex: 1;
    margin-left: var(--sidebar-width);
    transition: margin-left var(--transition-normal);
}

.sidebar.collapsed ~ .main-wrapper { margin-left: var(--sidebar-collapsed); }

/* ===== HEADER ===== */
.header {
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    padding: 0.35rem 1rem;
    min-height: 44px;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    position: sticky;
    top: 0;
    z-index: 50;
    box-shadow: var(--shadow-xs);
}

.header-left { display: flex; align-items: center; gap: 1rem; flex: 1 1 auto; min-width: 0; }
.header-end { display: flex; align-items: center; gap: 0.75rem; }
.header-end:empty { display: none; }

.page-title {
    font-size: 1rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.breadcrumb-link {
    color: var(--text-muted);
    text-decoration: none;
    font-weight: 500;
}

.breadcrumb-link:hover {
    color: var(--primary);
}

.breadcrumb-sep {
    color: var(--text-muted);
    margin: 0 0.1rem;
    font-weight: 400;
}

.header-right { display: flex; flex-direction: column; align-items: flex-end; justify-content: center; gap: 0.1rem; }

/* ===== MAIN ===== */
.main {
    padding: 0.75rem 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

/* ===== KPI ROW ===== */
.kpi-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.5rem; }

.kpi {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 0.625rem 0.75rem;
    position: relative;
    overflow: hidden;
    box-shadow: var(--shadow-xs);
    transition: all var(--transition-normal);
}

.kpi:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
    border-color: var(--accent);
    cursor: pointer;
}

.kpi-drill {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    color: var(--text-muted);
    font-size: 0.75rem;
    opacity: 0;
    transition: opacity var(--transition-fast);
}

.kpi:hover .kpi-drill { opacity: 1; }

.kpi::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: var(--border);
    transition: height var(--transition-fast);
}

.kpi:hover::before { height: 5px; }

.kpi.kpi-revenue::before { background: var(--accent); }
.kpi.kpi-money::before { background: var(--teal); }
.kpi.kpi-alert::before { background: var(--warning); }
.kpi.kpi-jobs::before { background: var(--blue); }

.kpi-label {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    margin-bottom: 0.2rem;
    font-weight: 500;
}

.kpi-value {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--text);
    line-height: 1.1;
    letter-spacing: -0.02em;
}

.kpi-meta {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.25rem;
    font-size: 10px;
}

.kpi-change {
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    padding: 0.125rem 0.35rem;
    border-radius: 4px;
}

.kpi-change.up {
    color: var(--positive);
    background: rgba(39, 103, 73, 0.08);
}

.kpi-change.down {
    color: var(--negative);
    background: rgba(197, 48, 48, 0.08);
}

.kpi-prev { color: var(--text-muted); }

/* Info tooltips (Stripe-style) */
.kpi-info {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
    font-size: 11px;
    margin-left: 4px;
    cursor: pointer;
    opacity: 0.45;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    vertical-align: middle;
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.kpi-info:hover {
    opacity: 1;
    color: var(--accent);
    background: var(--accent-bg);
    box-shadow: 0 0 0 3px rgba(78, 150, 79, 0.12);
}

/* ===== CARDS ===== */
.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: var(--shadow-xs);
    transition: box-shadow var(--transition-normal), border-color var(--transition-normal);
}

.card:hover { box-shadow: var(--shadow-sm); }

.card-header {
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--border-light);
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.card-title {
    font-size: 12px;
    font-weight: 600;
    color: var(--text);
    letter-spacing: -0.01em;
}

.card-body { padding: 0.625rem 0.75rem; }
.card-body.compact { padding: 0.375rem 0.75rem; }

/* ===== LIST ROWS ===== */
.list-header {
    display: flex;
    align-items: center;
    padding: 0.5rem 0.5rem;
    background: var(--surface-alt);
    border-bottom: 2px solid var(--border);
    border-radius: 4px 4px 0 0;
}

.list-header .col {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-secondary);
    font-weight: 700;
}

.list-row {
    display: flex;
    align-items: center;
    padding: 0.55rem 0.5rem;
    border-bottom: 1px solid var(--border-light);
    transition: background var(--transition-fast);
    cursor: default;
}

.list-row:hover { background: var(--surface-hover); }
.list-row:last-child { border-bottom: none; }

.list-row .col {
    font-size: 12px;
}

/* ===== LINKS ===== */
.link {
    color: var(--accent);
    font-size: 11px;
    text-decoration: none;
    font-weight: 600;
    transition: all var(--transition-fast);
    padding: 0.2rem 0.4rem;
    margin: -0.2rem -0.4rem;
    border-radius: 3px;
    border: 1px solid transparent;
}

.link:hover {
    background: var(--accent-bg);
    border-color: var(--accent);
    color: var(--accent-dark);
}

/* ===== MOBILE ===== */
.sidebar-overlay {
    display: none;
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(30, 38, 32, 0.4);
    backdrop-filter: blur(2px);
    z-index: 99;
    opacity: 0;
    transition: opacity var(--transition-normal);
}

.sidebar-overlay.active { display: block; opacity: 1; }

.mobile-menu-btn {
    display: none;
    position: relative;         /* anchors .mobile-menu-dot */
    background: none;
    border: none;
    color: var(--text);
    font-size: 1.25rem;
    cursor: pointer;
    padding: 0.25rem;
    border-radius: 4px;
    transition: background var(--transition-fast);
}

.mobile-menu-btn:hover { background: var(--surface-hover); }

/* Unread indicator on the hamburger — the mobile twin of .user-avatar-dot. Only the
   closed drawer hides that one, so this is display: none by default and switched on
   inside the <=1024px block, where the button itself is visible. Ringed in --surface
   (the header's background) rather than --sidebar-bg, which is what the avatar dot
   sits on. */
.mobile-menu-dot {
    display: none;
    position: absolute;
    top: 2px;
    right: 2px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--negative);
    border: 2px solid var(--surface);
    box-sizing: content-box;
    animation: pulse-badge 2s infinite;
}

/* ===== RESPONSIVE ===== */
@media (max-width: 1400px) { .kpi-row { grid-template-columns: repeat(2, 1fr); } }

@media (max-width: 1024px) {
    /* --- Mobile nav: a panel that drops DOWN from under the header --------------
       Previously an off-canvas column that slid in from the left edge. It now
       unrolls beneath the header, matching the public site's menu (see
       `.mobile-menu` in public-base.css): the bar you tapped stays put and lit, so
       the toggle is still there to close it and the page title never disappears.

       The reveal is a max-height clip rather than a translate — the same mechanism
       the public menu uses, for the same reason. A panel sliding in from off-screen
       has to travel across the header to get here, and .sidebar (z-index 100) paints
       over .header (50), so it would wipe over the header instead of growing out
       from under it. Clipping never paints outside the panel's own box, so there is
       no z-index fight to arbitrate.

       The open cap is a length, not `none`, because max-height has no auto value to
       transition to. It runs to the bottom edge of the viewport: a contractor's nav
       is taller than that on a phone and scrolls inside .sidebar-nav, while a
       customer's short nav simply stops early and leaves the overlay tappable. */
    .sidebar,
    .sidebar.collapsed {
        /* Set live by js/v2/base.js — the header is not a fixed height (it grows a
           controls row under 768px, and the dev banner pushes it down), so a
           hardcoded offset would leave the panel either notching the header or
           floating below it. The fallback is the header's own min-height. */
        top: var(--app-header-bottom, 44px);
        left: 0;
        right: 0;
        width: auto;
        height: auto;
        max-height: 0;
        overflow: hidden;
        visibility: hidden;             /* keeps the closed nav out of the tab order */
        box-shadow: var(--shadow-lg);
        transition: max-height var(--transition-normal), visibility var(--transition-normal);
    }
    /* No `.collapsed` twin needed: this is later in source at the same specificity
       as the `.sidebar.collapsed` above, so it already wins for a collapsed panel. */
    .sidebar.mobile-open {
        max-height: calc(100dvh - var(--app-header-bottom, 44px));
        visibility: visible;
    }
    /* Dim only what the panel doesn't cover, and leave the header alone so the
       toggle stays directly tappable rather than closing via the backdrop. */
    .sidebar-overlay { top: var(--app-header-bottom, 44px); }
    .main-wrapper { margin-left: 0; }
    .sidebar.collapsed ~ .main-wrapper { margin-left: 0; }
    .mobile-menu-btn { display: flex; }
    .mobile-menu-dot { display: block; }
    .collapse-btn { display: none; }
    /* Restore collapsed content visibility when mobile-open */
    .sidebar.collapsed.mobile-open .nav-text,
    .sidebar.collapsed.mobile-open .nav-section-title,
    .sidebar.collapsed.mobile-open .sidebar-brand-text,
    .sidebar.collapsed.mobile-open .sidebar-footer-text { display: inline; }
    .sidebar.collapsed.mobile-open .nav-badge { display: inline-flex; }
    .sidebar.collapsed.mobile-open .nav-item { justify-content: flex-start; padding: 0.35rem 0.5rem; }
    .sidebar.collapsed.mobile-open .nav-item i { margin: 0; font-size: 0.875rem; }
    .sidebar.collapsed.mobile-open .sidebar-header { justify-content: space-between; padding: 0.5rem 0.75rem; }
    .sidebar.collapsed.mobile-open .sidebar-brand img { width: 48px; }
    .sidebar.collapsed.mobile-open .sidebar-footer { padding: 0.5rem; }
    .sidebar.collapsed.mobile-open .sidebar-footer .nav-item { gap: 0.5rem; }
    /* Give the nav its scrollbar back. The collapsed rail lets its nav overflow
       visible (`.sidebar.collapsed .sidebar-nav` above) because the icon tooltips
       fly out past its right edge; that rule is (0,2,0) and beats `.sidebar-nav`'s
       own `overflow-y: auto`, so it follows the panel in here — where the drawer
       clips at the viewport bottom and a contractor's nav is taller than that. The
       result is a nav cut off mid-list with no way to reach the rest of it. Reached
       by tapping the sidebar header, which still calls toggleCollapse() at this
       width even though .collapse-btn is hidden. Restated at (0,3,0) rather than
       narrowing the rail's rule, which is correct for the rail. */
    .sidebar.collapsed.mobile-open .sidebar-nav { overflow-y: auto; }
    /* The collapsed sidebar flies its icon tooltips out past its right edge, which
       worked when the rail was 48px of a wide viewport. The drawer is full-width and
       clips, so they would be cut off mid-air — and they are a hover affordance for a
       rail that is showing its labels here anyway. (The account menu flies out the
       same way and has the same problem; it is handled by scoping the pop-out itself
       to desktop widths — see `.sidebar.collapsed .user-menu` below — rather than by
       re-stating the in-panel geometry here, which is just `.user-menu`'s own.) */
    .sidebar.collapsed.mobile-open .nav-item[data-tooltip]::after { display: none; }
}

@media (max-width: 768px) {
    /* --- HEADER: top row is [menu+title], controls wrap below --- */
    .header {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "left"
            "ctrls";
        align-items: center;
        padding: 0.5rem 0.75rem;
        gap: 0.4rem 0.5rem;
    }
    .header-left {
        grid-area: left;
        gap: 0.5rem;
    }
    .header-end {
        grid-area: ctrls;
        justify-self: stretch;
    }
    .header-end:empty {
        display: none;
    }
    .page-title {
        font-size: 0.9rem;
    }
    .header-right {
        align-items: stretch;
    }

    /* --- MAIN CONTENT --- */
    .main { padding: 0.75rem; gap: 0.625rem; }

    /* --- KPI CARDS --- */
    .kpi-row { gap: 0.375rem; }
    .kpi { padding: 0.5rem 0.625rem; }
    .kpi-value { font-size: 1.1rem; }
    .kpi-label { font-size: 9px; }
    .kpi-meta { font-size: 9px; }
    .kpi:hover { transform: none; }

    /* --- CHART CARDS --- */
    .card-header { padding: 0.4rem 0.625rem; }
    .card-body { padding: 0.5rem 0.625rem; }
    .card-body.compact { padding: 0.25rem 0.625rem; }

    /* --- Disable hover effects on touch --- */
    .card:hover { box-shadow: var(--shadow-xs); }
    .nav-item:hover { padding-left: 0.5rem; background: transparent; }
}

@media (max-width: 480px) {
    .main { padding: 0.5rem; gap: 0.5rem; }
    .kpi-row { gap: 0.25rem; }
    .kpi { padding: 0.4rem 0.5rem; }
    .kpi-value { font-size: 1rem; }
    .kpi-change { font-size: 9px; padding: 0.1rem 0.25rem; }
    .kpi-prev { font-size: 9px; }
    .card-title { font-size: 11px; }
}

/* ===== PAGE LOAD ANIMATION ===== */
@keyframes fadeInUp {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: translateY(0); }
}

.kpi { animation: fadeInUp 0.4s ease-out backwards; }
.kpi:nth-child(1) { animation-delay: 0.05s; }
.kpi:nth-child(2) { animation-delay: 0.1s; }
.kpi:nth-child(3) { animation-delay: 0.15s; }
.kpi:nth-child(4) { animation-delay: 0.2s; }

.card { animation: fadeInUp 0.4s ease-out backwards; animation-delay: 0.25s; }

/* ===== USER MENU POPOVER ===== */
.user-menu {
    position: absolute;
    bottom: calc(100% + 6px);
    left: 0.375rem;
    right: 0.375rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: var(--shadow-lg);
    padding: 0.25rem;
    opacity: 0;
    visibility: hidden;
    transform: translateY(4px);
    transition: all var(--transition-normal);
    z-index: 200;
}

.user-menu.open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

/* When sidebar is collapsed, pop user menu out to the right.

   Desktop only. Below 1025px the collapsed sidebar is the full-width mobile drawer,
   which clips its own overflow, so a menu flown out past its right edge would be cut
   off mid-air. Gating the pop-out is what puts the menu back inside the panel — the
   base `.user-menu` geometry above then applies untouched, with nothing to keep in
   step with it. */
@media (min-width: 1025px) {
    .sidebar.collapsed .user-menu {
        left: calc(100% + 8px);
        right: auto;
        bottom: 0;
        width: 160px;
        transform: translateX(-4px);
    }
    .sidebar.collapsed .user-menu.open {
        transform: translateX(0);
    }
}

.user-menu-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.5rem;
    font-size: 12px;
    font-weight: 500;
    color: var(--text);
    text-decoration: none;
    border-radius: 4px;
    transition: background var(--transition-fast);
}

.user-menu-item:hover {
    background: var(--accent-bg);
    color: var(--accent-dark);
}

.user-menu-item i {
    width: 16px;
    text-align: center;
    font-size: 0.8rem;
    opacity: 0.7;
}

.user-menu-item:hover i { opacity: 1; }

/* Unread count on the Notifications menu item */
.user-menu-count {
    margin-left: auto;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 8px;
    background: var(--negative);
    color: #ffffff;
    font-family: 'IBM Plex Mono', monospace;
    font-size: 9px;
    font-weight: 600;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
}

.user-menu-divider {
    height: 1px;
    background: var(--border-light);
    margin: 0.25rem 0.25rem;
}

.user-menu-logout:hover {
    background: var(--negative-bg);
    color: var(--negative);
}

/* ===== REUSABLE SPINNER ===== */
/* Usage: <div class="lb-spinner"></div>
   Sizes: default 28px, .lb-spinner-sm 18px, .lb-spinner-lg 40px
   Inherits current color or use on themed containers */
@keyframes lb-spin { to { transform: rotate(360deg); } }

.lb-spinner {
    width: 28px; height: 28px;
    border: 2.5px solid var(--border);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: lb-spin 0.7s linear infinite;
    flex-shrink: 0;
}
.lb-spinner-sm { width: 18px; height: 18px; border-width: 2px; }
.lb-spinner-lg { width: 40px; height: 40px; border-width: 3px; }

/* Inline button spinner — white-on-transparent, pairs with .cmd-btn.primary/danger/warning.
   Usage: <span class="cmd-btn-spinner"></span> Sending… */
.cmd-btn-spinner {
    display: inline-block;
    width: 14px; height: 14px;
    border: 2px solid rgba(255,255,255,0.4);
    border-top-color: #fff;
    border-radius: 50%;
    animation: lb-spin 0.8s linear infinite;
    vertical-align: -2px;
}

/* ===== PAGE TOAST ===== */
.page-toast {
    position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%) translateY(20px);
    background: var(--text); color: #fff;
    padding: 10px 20px; border-radius: 8px;
    font-size: 13px; font-weight: 600; font-family: inherit;
    display: inline-flex; align-items: center; gap: 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.18);
    opacity: 0; transition: opacity 300ms ease, transform 300ms ease;
    z-index: 2000; white-space: nowrap;
}
.page-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.page-toast i { color: var(--accent); font-size: 15px; }
.page-toast.page-toast-error { background: var(--negative); }
.page-toast.page-toast-error i { color: #fff; }
