/* ============================================
   THEME VARIABLES
   Default / [data-theme="dark"] = dark red theme
   [data-theme="light"]          = white red theme
   ============================================ */

:root,
:root[data-theme="dark"] {
    /* Brand — Apple system red */
    --red:           #ff453a;
    --bright-red:    #ff6961;
    --red-glow:      rgba(255, 69, 58, 0.22);
    --red-glow-lg:   rgba(255, 69, 58, 0.12);

    /* Backgrounds — Apple dark system grays */
    --bg-body:       #000000;
    --bg-sidebar:    rgba(22, 22, 24, 0.72);
    --bg-header:     rgba(22, 22, 24, 0.72);
    --bg-footer:     #1c1c1e;
    --bg-card:       #1c1c1e;
    --bg-input:      #2c2c2e;
    --bg-btn:        #2c2c2e;
    --bg-hover:      rgba(255, 255, 255, 0.06);
    --bg-active:     rgba(255, 69, 58, 0.16);
    --bg-overlay:    rgba(0, 0, 0, 0.55);

    /* Borders — hairline */
    --border:        rgba(255, 255, 255, 0.10);
    --border-input:  rgba(255, 255, 255, 0.14);

    /* Text — Apple label hierarchy.
       Alpha values are chosen so each token clears WCAG AA (4.5:1) against the
       *darkest* surface it can land on, which is the #000 body, not the #1c1c1e
       card. Measured, not eyeballed — see the ratios in each comment. */
    --text-primary:  #f5f5f7;                      /* 12.80 on #2c2c2e … 19.29 on #000 */
    --text-secondary:rgba(235, 235, 245, 0.62);    /* 5.49 worst */
    --text-muted:    rgba(235, 235, 245, 0.58);    /* 5.04 worst (was 0.34 → 2.61, illegible) */
    --text-heading:  #ffffff;                      /* 21.00 on #000 */
    --text-nav:      rgba(235, 235, 245, 0.66);    /* 6.04 worst */
    --text-nav-cat:  rgba(235, 235, 245, 0.58);    /* 5.04 worst (was 0.50 → 4.17 on inputs) */

    /* ── Section accents ──────────────────────────────────────────
       Same token names as the light theme so section rules can be written
       once. Here the tints are near-black surfaces rather than pale washes,
       and the accents are brightened to stay legible on them. */
    --accent-ink:        #f5f5f7;
    --accent-amber:      #ffb761;
    --accent-amber-deep: #ffa23d;
    --accent-amber-tint: #1e1a14;
    --accent-amber-tint2:#241e16;
    --accent-amber-glow: rgba(255, 183, 97, 0.14);
    --accent-blue:       #7e9bec;
    --accent-blue-text:  #93aef5;
    --accent-blue-tint:  #14181f;
    --accent-blue-tint2: #171c26;
    --accent-blue-glow:  rgba(126, 155, 236, 0.14);
    --preorder-ink:      #ffb761;   /* 7.82 on its own tint */
    --install-ink:       #7cbcff;

    /* ── Status inks ──────────────────────────────────────────────
       Four semantic colours for "good / caution / informational / service".
       Admin pages kept reaching for #2ecc71, #f39c12, #3498db and #9b59b6 as
       text on a tint of themselves; those are chosen for a dark UI and score
       1.87-2.70 in the light theme, so each page was quietly unreadable there.
       Declared once here, per theme, and measured at the 12%, 15% and 20%
       tint strengths those pages actually use. Worst case shown. */
    --ok-ink:    #2ecc71;   /* 5.50 */
    --warn-ink:  #ffb761;   /* 6.26 */
    --info-ink:  #93aef5;   /* 5.25 */
    --svc-ink:   #d0a8f0;   /* 5.62 */
    /* The fifth of the set. --red (#ff453a) is a fill, not an ink: as text on
       a 14% tint of itself it measures 4.28 here, under the 4.5 floor. This is
       the same hue lifted until it clears. */
    --danger-ink: #ff6961;  /* 5.17 on a 14% --red tint */

    /* Misc */
    --avatar-bg:     #3a3a3c;
    --shadow:        0 1px 2px rgba(0, 0, 0, 0.40), 0 10px 34px rgba(0, 0, 0, 0.55);
    --sidebar-logo-bg: #000000;
    --skeleton-base:  rgba(255, 255, 255, 0.05);
    --skeleton-shine: rgba(255, 255, 255, 0.09);

    /* ── Rounded showcase ──────────────────────────────────────────
       The "floating card" language used by the landing sections: inset
       from the viewport edge, generously rounded, lifted with a soft
       shadow. Defined globally so every page (home, about, …) draws on
       one set of numbers rather than each re-inventing them. */
    --showcase-radius: clamp(14px, 2vw, 28px);
    --showcase-gutter: clamp(10px, 1.6vw, 22px);
    --showcase-shadow: 0 12px 38px rgba(0, 0, 0, 0.55);   /* light overrides below */
    /* Banner shape, measured off the supplied reference artwork (~2.91:1 and
       3.00:1). Change this one value to reshape the banner. */
    --showcase-ratio:  3 / 1;
    /* Solid fill for full-colour brand blocks (quote card, testimonial band,
       about hero/CTA). A fixed hex rather than var(--red) on purpose: --red is
       #ff453a in dark mode and white on that measures 3.41:1, under AA.
       #a10010 holds white at 8.32:1 and the amber eyebrow at 4.59:1, in both
       themes. */
    --brand-block:     #a10010;

    /* ── Shared design tokens (theme-independent) ── */
    --radius-sm:   8px;
    --radius:      12px;
    --radius-lg:   18px;
    --radius-pill: 980px;
    --blur:        saturate(180%) blur(20px);
    --ease:        cubic-bezier(0.4, 0, 0.2, 1);
    --font-sans:   -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
                   "Inter", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

:root[data-theme="light"] {
    /* Brand — Apple system red, darker "accessible" variant.
       #ff3b30 scored 3.26:1 as link text on white and 3.55:1 under white button
       labels; both failed AA. Darkening fixes both at once, because --red is used
       303× as a foreground colour and 98× as a fill. */
    --red:           #d70015;                      /* text 4.94, white-on-fill 5.38 */
    --bright-red:    #e0352b;
    --red-glow:      rgba(255, 59, 48, 0.14);
    --red-glow-lg:   rgba(255, 59, 48, 0.07);

    /* Backgrounds — warm neutral base.
       #f5f2f2 instead of Apple's cool #f5f5f7: the page reads as warm paper
       rather than grey, which is what stops the light theme looking washed out
       once the amber/blue section tints sit on top of it. */
    --bg-body:       #f5f2f2;
    --bg-sidebar:    rgba(255, 255, 255, 0.72);
    --bg-header:     rgba(255, 255, 255, 0.72);
    --bg-footer:     #ffffff;
    --bg-card:       #ffffff;
    --bg-input:      #f5f5f7;
    --bg-btn:        #f0f0f2;
    --bg-hover:      rgba(0, 0, 0, 0.04);
    --bg-active:     rgba(255, 59, 48, 0.10);
    --bg-overlay:    rgba(0, 0, 0, 0.28);

    /* Borders — hairline */
    --border:        rgba(0, 0, 0, 0.08);
    --border-input:  rgba(0, 0, 0, 0.13);

    /* Text — Apple label hierarchy. Each token clears AA against the *lighter*
       surface it can land on (#fff card), not just the #f5f5f7 body. */
    --text-primary:  #2b2a2a;   /* 12.86 on the body … 14.31 on a white card */
    --text-secondary:#55555a;   /* 6.66 worst (across every section tint below) */
    --text-muted:    #67676c;   /* 4.75 worst. Was #6e6e73, which measured 4.66 on
                                   plain white but dropped to 4.28 once the tinted
                                   section backgrounds landed under it — i.e. it
                                   only passed because the page was uniformly grey.
                                   Re-solved against the DEEPEST tint in use. */
    --text-heading:  #2b2a2a;   /* 12.86 */
    --text-nav:      #424245;   /* 9.20 */
    --text-nav-cat:  #67676c;   /* 4.75 worst — same reason as --text-muted */

    /* ── Section accents ──────────────────────────────────────────
       Measured, not eyeballed. The two accents behave very differently:

         --accent-amber (#feb05d) is a FILL ONLY colour. It scores 1.63:1 on the
         body, so it can never carry text or an icon glyph; put --accent-ink on
         top of it instead (7.89:1) and it is safe.

         --accent-blue (#5a7acd) is fine for non-text UI (bars, borders, fills)
         but only 3.70:1 on the body — large text at best. --accent-blue-text is
         the darkened variant for anything actually readable (5.29:1). */
    --accent-ink:        #2b2a2a;
    --accent-amber:      #feb05d;
    --accent-amber-deep: #e8963c;
    --accent-amber-tint: #fef3e6;
    --accent-amber-tint2:#fdeeda;
    --accent-amber-glow: rgba(254, 176, 93, 0.20);
    --accent-blue:       #5a7acd;
    --accent-blue-text:  #4260b4;
    --accent-blue-tint:  #edf1fb;
    --accent-blue-tint2: #e6ecf9;
    --accent-blue-glow:  rgba(90, 122, 205, 0.16);
    --preorder-ink:      #8a5a12;   /* 5.35 on its own tint */
    --install-ink:       #0a5bb8;

    /* Same four, darkened for a white card. #8a5a12 was the obvious amber but
       measured 4.11 once the tint reached 25%, so it is a shade deeper. */
    --ok-ink:    #166136;   /* 5.46 */
    --warn-ink:  #744b0d;   /* 5.10 */
    --info-ink:  #3a56a8;   /* 5.04 */
    --svc-ink:   #6b3fa0;   /* 5.38 */
    --danger-ink: #a10010;  /* 6.96 on a 14% --red tint; --red itself is 4.50, no margin */

    /* Misc */
    --avatar-bg:     #e8e8ed;
    --shadow:        0 1px 2px rgba(0, 0, 0, 0.04), 0 10px 30px rgba(0, 0, 0, 0.08);
    /* Lighter than the dark-theme default — a 0.55 shadow on a pale ground
       reads as a smudge rather than a lift. */
    --showcase-shadow: 0 10px 34px rgba(0, 0, 0, 0.16);
    --sidebar-logo-bg: #ffffff;
    --skeleton-base:  rgba(0, 0, 0, 0.06);
    --skeleton-shine: rgba(255, 255, 255, 0.6);
}

/* Default state (Light Mode) */
.logo-dark-mode { display: none; }
.logo-light-mode { display: block; }

/* Dark Mode state */
[data-theme="dark"] .logo-dark-mode { display: block; }
[data-theme="dark"] .logo-light-mode { display: none; }

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

/* ============================================
   BODY
   ============================================ */
body {
    font-family: var(--font-sans);
    background: var(--bg-body);
    color: var(--text-primary);
    display: flex;
    align-items: flex-start;
    /* NOTE: no overflow-y here on purpose. `overflow-y: auto` made <body> a
       scroll container, and a scroll container between the viewport and
       .top-header is what stops `position: sticky` working — the header
       scrolled away with the page instead of pinning. The document scrolls on
       <html>, which is what sticky needs to resolve against. */
    letter-spacing: -0.011em;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    transition: background 0.25s ease, color 0.25s ease;
}

/* ============================================
   MODERN POLISH (Apple-style)
   Global refinements layered on top of the tokens.
   ============================================ */
h1, h2, h3, h4, h5 { letter-spacing: -0.022em; }

/* Smooth, consistent interaction on all controls */
button, .btn, a, input, select, textarea, .card, [class*="card"] {
    transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease),
                color 0.2s var(--ease), box-shadow 0.2s var(--ease),
                transform 0.15s var(--ease), opacity 0.2s var(--ease);
}
button:not(:disabled), .btn:not(:disabled) { -webkit-tap-highlight-color: transparent; }
button:not(:disabled):active, .btn:not(:disabled):active { transform: scale(0.97); }

/* Soft focus ring instead of the default outline */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible {
    outline: none;
    box-shadow: 0 0 0 4px var(--red-glow);
    border-radius: var(--radius-sm);
}

::selection { background: var(--red-glow); color: var(--text-heading); }

/* Thin, unobtrusive scrollbars */
* { scrollbar-width: thin; scrollbar-color: var(--border-input) transparent; }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: var(--border-input);
    border-radius: var(--radius-pill);
    border: 3px solid transparent;
    background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); background-clip: content-box; }

/* Inline SVG icons (assets/icons/*.svg via the icon() helper).
   Sized in em so they scale with text; colour inherited via currentColor. */
.ic { width: 1em; height: 1em; display: inline-block; vertical-align: -0.125em; flex-shrink: 0; }
.ic-sm { width: .875em; height: .875em; }
.ic-lg { width: 1.25em; height: 1.25em; }
.ic-xl { width: 1.5em;  height: 1.5em; }
.ic-2x { width: 2em;    height: 2em; }
.ic-3x { width: 3em;    height: 3em; }

/* Sidebar nav icons — fixed, consistent size + centred alignment with the label.
   Add class="nav-ico" to a pasted SVG in a nav link. */
.nav-links a > span:first-child,
.shop-drill-list li a > span:first-child { display: inline-flex; align-items: center; gap: 10px; }
.nav-ico { width: 20px; height: 20px; flex-shrink: 0; }

/* Paste-and-forget: a raw icon SVG dropped inline (no class) auto-sizes to the
   surrounding font. CSS overrides its baked-in width/height="24". Only affects
   icon-grid viewBoxes AND only when the <svg> has no class, so app graphics with
   their own classes are never touched. Add class="ic ic-lg" (etc.) for a custom
   size, or wrap in an element with font-size to scale it. */
svg[viewBox="0 0 24 24"]:not([class]),
svg[viewBox="0 0 20 20"]:not([class]),
svg[viewBox="0 0 16 16"]:not([class]) {
    width: 1em; height: 1em; display: inline-block; vertical-align: -0.125em; flex-shrink: 0;
}

/* ============================================
   SIDEBAR
   ============================================ */
.sidebar {
    width: 260px;
    height: 100vh;
    background-color: var(--bg-sidebar);
    backdrop-filter: var(--blur);
    -webkit-backdrop-filter: var(--blur);
    border-right: 1px solid var(--border);
    position: fixed;
    top: 0;
    left: 0;
    display: flex;
    flex-direction: column;
    z-index: 100;
    overflow: hidden;
    transition: transform 0.32s cubic-bezier(0.4, 0, 0.2, 1),
                background 0.25s ease, border-color 0.25s ease;
}

.sidebar-logo {
    flex: 0 0 90px;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: var(--sidebar-logo-bg);
    border-bottom: 1px solid var(--border);
}
.sidebar-logo img { max-width: 130px; height: auto; }

.nav-links { list-style: none; padding: 10px 0; margin: 0; } /* sizing/scroll handled by #sidebarSlider */
.nav-links li { margin: 2px 0; }

.nav-links a, .collapsible-btn {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 11px 20px;
    color: var(--text-nav);
    text-decoration: none;
    font-size: 14px;
    font-weight: 500;
    border-left: 3px solid transparent;
    transition: all 0.2s ease;
    width: 100%;
    background: none;
    border-top: none;
    border-right: none;
    border-bottom: none;
    cursor: pointer;
}

.nav-links a:hover, .collapsible-btn:hover {
    background: var(--bg-hover);
    color: var(--red);
    border-left-color: var(--red);
}

.nav-links a.active {
    background: var(--bg-active);
    color: var(--red);
    border-left-color: var(--red);
    font-weight: 600;
}

.active-category > .collapsible-btn {
    color: var(--red);
    border-left-color: var(--red);
}

.nav-category {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-nav-cat);
    padding: 16px 20px 6px;
}

.collapsible-content {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.35s ease;
    background: var(--bg-overlay);
}
.collapsible-content.show { max-height: 400px; }
.collapsible-content a {
    padding: 9px 20px 9px 44px;
    font-size: 13px;
}

.arrow { font-size: 10px; transition: transform 0.3s; color: var(--text-muted); }
.rotate { transform: rotate(180deg); }

/* ============================================
   MAIN WRAPPER
   ============================================ */
.main-wrapper {
    margin-left: 260px;
    width: calc(100% - 260px);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    transition: margin-left 0.32s cubic-bezier(0.4, 0, 0.2, 1),
                width 0.32s cubic-bezier(0.4, 0, 0.2, 1);
}

/* ── Collapsed sidebar (desktop) ─────────────────────────────
   Toggled via the header icon; state persisted in localStorage. */
@media (min-width: 769px) {
    .sidebar-collapsed .sidebar {
        transform: translateX(-100%);
    }
    .sidebar-collapsed .main-wrapper {
        margin-left: 0;
        width: 100%;
    }
    /* Nudge the toggle icon to hint at its active (re-open) state */
    .sidebar-collapsed .menu-toggle { color: var(--red); }
}

/* ============================================
   TOP HEADER
   ============================================ */
.top-header {
    height: 64px;
    background-color: var(--bg-header);
    backdrop-filter: var(--blur);
    -webkit-backdrop-filter: var(--blur);
    border-bottom: 1px solid var(--border);
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 24px;
    position: sticky;
    top: 0;
    z-index: 98;
    transition: background 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;
}

/* Once the page has scrolled the header is floating over content rather than
   sitting above it, so it needs to separate itself: a real shadow and a less
   transparent ground. Toggled by the scroll listener in header.php.
   Falls back gracefully — without JS the header is still sticky, just flat. */
.top-header.is-stuck {
    box-shadow: 0 1px 0 var(--border), 0 6px 20px rgba(0, 0, 0, 0.10);
}
:root[data-theme="dark"] .top-header.is-stuck {
    box-shadow: 0 1px 0 var(--border), 0 8px 26px rgba(0, 0, 0, 0.55);
}
/* backdrop-filter is doing the heavy lifting where it is supported; where it
   is not, this keeps the bar opaque enough to read text through. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .top-header { background-color: var(--bg-card); }
}

.header-title { display: flex; align-items: center; gap: 12px; }
.header-title h2 { font-size: 16px; font-weight: 600; color: var(--text-heading); }

.menu-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    color: var(--text-heading);
    cursor: pointer;
    padding: 6px;
    border-radius: 8px;
    transition: background 0.2s ease, color 0.2s ease;
}
.menu-toggle:hover { background: var(--bg-hover); color: var(--red); }
.menu-toggle svg { width: 22px; height: 22px; display: block; }

.account-menu { display: flex; align-items: center; gap: 12px; }

.account-info {
    display: flex;
    flex-direction: column;
    text-align: right;
}
.account-name { font-size: 13px; font-weight: 600; color: var(--text-heading); }
.account-role { font-size: 11px; color: var(--text-muted); }

.avatar-link { text-decoration: none; }
.avatar-container {
    width: 36px; height: 36px;
    border-radius: 50%;
    border: 2px solid var(--red);
    background: var(--avatar-bg);
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
}
.avatar-img { width: 100%; height: 100%; object-fit: cover; }
.avatar-text { color: var(--text-heading); font-weight: 700; font-size: 15px; }

.logout-btn-header {
    padding: 7px 14px;
    border-radius: 8px;
    background: var(--bg-btn);
    color: var(--text-primary);
    text-decoration: none;
    font-size: 13px;
    font-weight: 500;
    border: 1px solid var(--border);
    transition: 0.2s;
}
.logout-btn-header:hover { border-color: var(--red); color: var(--red); }

.header-cart-link {
    display: flex; align-items: center; gap: 6px;
    background: var(--bg-btn);
    color: var(--text-primary);
    text-decoration: none;
    padding: 7px 14px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 600;
    border: 1px solid var(--border);
    transition: 0.2s;
}
.header-cart-link:hover { border-color: var(--red); color: var(--red); }

.cart-count-pill {
    background: var(--red); color: #fff;
    font-size: 10px; padding: 2px 6px;
    border-radius: 10px; font-weight: 800;
}

.header-credit-pill {
    background: var(--red-glow);
    border: 1px solid var(--red);
    color: var(--red);
    padding: 4px 10px;
    border-radius: 20px;
    font-size: 13px;
    font-weight: 700;
}

/* ============================================
   THEME TOGGLE BUTTON
   ============================================ */
.theme-toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 13px;
    border-radius: 20px;
    background: var(--bg-btn);
    border: 1px solid var(--border);
    color: var(--text-primary);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s ease;
    white-space: nowrap;
}
.theme-toggle:hover {
    border-color: var(--red);
    color: var(--red);
}
.theme-label { font-size: 12px; }

/* ============================================
   SIDEBAR OVERLAY (mobile)
   ============================================ */
.sidebar-overlay {
    display: none;
    position: fixed;
    top: 0; left: 0;
    width: 100%; height: 100vh;
    background: rgba(0,0,0,0.7);
    z-index: 99;
}

/* ============================================
   CONTENT + FOOTER
   ============================================ */
/* min-width:0 is load-bearing. body is `display:flex` (above), so .content-area
   is a flex item and without this it keeps the flex default of min-width:auto —
   its content-based minimum. Any table with a min-width wider than the screen
   then pushes the whole column out: measured on the workshop inventory page at
   a 390px viewport, .content-area became 914px, the PAGE scrolled sideways, and
   the .table-scroll wrapper that is supposed to do the scrolling never did.
   Letting the item shrink puts the overflow back inside the wrapper where it
   belongs. Harmless on pages with nothing wide in them. */
.content-area { flex: 1; min-width: 0; }

/* ============================================
   NOTIFICATION BELL (header)
   Lives here rather than in header.php's <style>, because that block only
   renders for the guest/customer top-nav — the bell is for every signed-in
   role, workshop and battery portals included.
   ============================================ */
.notif-wrap { position: relative; flex-shrink: 0; }
.notif-btn {
    display: flex; align-items: center; justify-content: center;
    width: 36px; height: 36px; border-radius: 999px;
    background: var(--bg-hover); border: 1px solid var(--border);
    color: var(--text-nav, var(--text-primary));
    cursor: pointer; position: relative;
    transition: color .2s, border-color .2s;
}
.notif-btn:hover { color: var(--red); border-color: var(--red); }
.notif-bubble {
    position: absolute; top: -4px; right: -4px;
    min-width: 17px; height: 17px; padding: 0 4px;
    border-radius: 999px; background: var(--red); color: #fff;
    font-size: 10px; font-weight: 800; line-height: 17px; text-align: center;
    border: 2px solid var(--bg-header, var(--bg-card));
    box-sizing: content-box;
}
/* Same animated-visibility pattern as the nav dropdowns: display can't be
   transitioned, and visibility:hidden keeps the panel out of the tab order. */
.notif-panel {
    position: absolute; top: calc(100% + 8px); right: 0;
    width: min(360px, calc(100vw - 32px)); z-index: 300;
    background: var(--bg-card); border: 1px solid var(--border);
    border-radius: 14px; box-shadow: var(--showcase-shadow);
    overflow: hidden;
    opacity: 0; visibility: hidden; pointer-events: none;
    transform: translateY(-6px);
    transition: opacity .18s var(--ease, ease), transform .18s var(--ease, ease), visibility .18s;
}
.notif-wrap.open .notif-panel { opacity: 1; visibility: visible; pointer-events: auto; transform: translateY(0); }
.notif-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 13px 15px; border-bottom: 1px solid var(--border);
    font-size: 13px; font-weight: 800; color: var(--text-heading);
}
.notif-readall {
    background: none; border: none; cursor: pointer; font-family: inherit;
    font-size: 11.5px; font-weight: 700; color: var(--red);
}
.notif-readall:hover { text-decoration: underline; }
.notif-list { max-height: 340px; overflow-y: auto; }
.notif-loading, .notif-none { padding: 26px 16px; text-align: center; font-size: 13px; color: var(--text-muted); }
.notif-row {
    display: flex; gap: 11px; align-items: flex-start;
    padding: 12px 15px; border-bottom: 1px solid var(--border);
    text-decoration: none; color: inherit; transition: background .16s;
}
.notif-row:last-child { border-bottom: none; }
.notif-row:hover { background: var(--bg-hover); }
.notif-row.unread { background: var(--red-glow); }
.notif-row.unread:hover { background: var(--bg-hover); }
.notif-row-ico {
    width: 30px; height: 30px; border-radius: 9px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center; font-size: 12px;
}

/* ── Notification tones ──────────────────────────────────────────────────
   NotificationService::meta() returns a tone name, not a hex. Both render
   sites — the bell dropdown and the notifications list page — used to build
   an 8-digit colour by concatenating the hex with "1f", which pinned the
   palette to four fixed values that each failed WCAG AA in one theme:
   #e8963c 2.37 light, #1e9e5a 3.45 light, #c0392b 3.13 dark, #4260b4 2.89
   dark. Driving them from the theme inks instead measures 5.17–7.30 across
   both themes, and one definition now serves both surfaces. */
.nt-tone-ok     { background: rgba(46,204,113,.14);  color: var(--ok-ink); }    /* 6.27 / 6.73 */
.nt-tone-warn   { background: rgba(255,183,97,.14);  color: var(--warn-ink); }  /* 7.30 / 7.07 */
.nt-tone-info   { background: rgba(126,155,236,.14); color: var(--info-ink); }  /* 6.21 / 6.04 */
.nt-tone-danger { background: rgba(255,69,58,.14);   color: var(--danger-ink); } /* 5.17 / 6.96 */
.nt-tone-neutral{ background: var(--bg-hover);       color: var(--text-secondary); } /* 5.30 / 6.79 */
.notif-row-t { font-size: 12.5px; font-weight: 800; color: var(--text-heading); line-height: 1.35; }
.notif-row-b { font-size: 12px; color: var(--text-secondary); line-height: 1.5; margin-top: 2px;
               display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.notif-row-a { font-size: 11px; color: var(--text-muted); margin-top: 4px; font-weight: 600; }
.notif-foot {
    display: block; padding: 12px; text-align: center; text-decoration: none;
    font-size: 12.5px; font-weight: 800; color: var(--red);
    border-top: 1px solid var(--border);
}
.notif-foot:hover { background: var(--bg-hover); }

/* ── Narrow screens ────────────────────────────────────────────────
   `right: 0` anchors the panel to the bell, and on a phone the bell sits
   mid-header with the cart and avatar to its right, so a 360px panel hung
   90-112px off the left edge. Here it anchors to the viewport instead:
   inset from both sides, so it fits at any width.

   --notif-top is written by the header script from the button's own
   position when the panel opens, so this works under the site header and
   the portal headers alike without hardcoding a header height. */
@media (max-width: 600px) {
    .notif-panel {
        position: fixed;
        top: var(--notif-top, 64px);
        left: 10px; right: 10px;
        width: auto;
        /* The list scrolls inside whatever height is left below the header. */
        max-height: calc(100vh - var(--notif-top, 64px) - 14px);
        max-height: calc(100dvh - var(--notif-top, 64px) - 14px);
        display: flex; flex-direction: column;
    }
    .notif-head, .notif-foot { flex-shrink: 0; }
    .notif-list { max-height: none; flex: 1 1 auto; min-height: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .notif-panel { transition: none !important; transform: none !important; }
}

.dashboard-footer {
    padding: 16px 24px;
    font-size: 12px;
    color: var(--text-muted);
    border-top: 1px solid var(--border);
    background: var(--bg-footer);
    text-align: center;
    transition: background 0.25s ease, border-color 0.25s ease;
}

/* ============================================
   FILTER PANEL
   ============================================ */
.filter-panel-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: pointer;
    user-select: none;
}

.filter-toggle-btn {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 12px;
    color: var(--text-muted);
    padding: 4px;
    transition: transform 0.3s;
}

/* ============================================
   MOBILE
   ============================================ */
@media (max-width: 768px) {
    .sidebar {
        transform: translateX(-100%);
        transition: transform 0.3s ease, background 0.25s ease;
    }
    .sidebar.active { transform: translateX(0); }
    .sidebar-overlay.active { display: block; }
    .main-wrapper { margin-left: 0; width: 100%; }
    .top-header { padding: 0 16px; }
    .account-info { display: none; }
    .theme-label { display: none; }

    .filter-panel-body {
        display: none;
        margin-top: 14px;
    }
    .filter-panel-body.open { display: block; }
    .filter-toggle-btn.open { transform: rotate(180deg); }
}

@media (min-width: 769px) {
    .filter-panel-body { display: block !important; }
    .filter-toggle-btn { display: none; }
    .filter-panel-header { cursor: default; }
}

/* ProductsStyle */
.products-layout {
        display: flex;
        gap: 24px;
        padding: 24px;
        align-items: flex-start;
    }

    /* Filter sidebar */
    .filter-panel {
        flex: 0 0 240px;
        background: var(--bg-sidebar);
        border-radius: 12px;
        border: 1px solid var(--border);
        padding: 20px;
        position: sticky;
        top: 84px;
    }

    .filter-panel h3 {
        font-size: 13px;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 1px;
        color: var(--text-primary);
        margin-bottom: 16px;
        padding-bottom: 10px;
        border-bottom: 1px solid #f0f0f0;
    }

    .filter-section {
        margin-bottom: 20px;
    }

    .filter-label {
        font-size: 12px;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.8px;
        color: #999;
        display: block;
        margin-bottom: 10px;
    }

    .filter-search {
        width: 100%;
        padding: 10px 12px;
        border: 1px solid #e0e0e0;
        border-radius: 8px;
        font-size: 14px;
        outline: none;
        transition: border-color 0.2s;
    }

    .filter-search:focus {
        border-color: var(--red, #e74c3c);
    }

    .checkbox-list {
        max-height: 180px;
        overflow-y: auto;
        display: flex;
        flex-direction: column;
        gap: 6px;
        scrollbar-width: thin;
    }

    .checkbox-item {
        display: flex;
        align-items: center;
        gap: 8px;
        font-size: 13px;
        color: #555;
        cursor: pointer;
        padding: 3px 0;
    }

    .checkbox-item input {
        accent-color: var(--red, #e74c3c);
        width: 15px;
        height: 15px;
    }

    .checkbox-item:hover {
        color: var(--text-muted);
    }

    .price-inputs {
        display: flex;
        gap: 8px;
    }

    .price-inputs input {
        width: 100%;
        padding: 8px 10px;
        border: 1px solid #e0e0e0;
        border-radius: 8px;
        font-size: 13px;
        outline: none;
    }

    .price-inputs input:focus {
        border-color: var(--red, #e74c3c);
    }

    .btn-clear {
        width: 100%;
        padding: 10px;
        background: var(--red);
        color: var(--text-primary);
        border: 1px solid var(--border);
        border-radius: 8px;
        font-size: 13px;
        font-weight: 600;
        cursor: pointer;
        transition: 0.2s;
        margin-top: 4px;
    }

    .btn-clear:hover {
        background: #eee;
        color: #333;
    }

    /* Main content */
    .products-main {
        flex: 1;
        min-width: 0;
    }

    .action-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 20px;
    }

    .action-header h3 {
        font-size: 18px;
        font-weight: 600;
    }

    .item-count {
        font-size: 13px;
        color: var(--text-muted);
        margin-top: 2px;
    }

    .header-actions {
        display: flex;
        gap: 10px;
        align-items: center;
    }

    /* --red is #ff453a in dark and holds white at 3.41:1. */
    .add-btn {
        background: var(--brand-block);
        color: #fff;
        padding: 9px 18px;
        border-radius: 8px;
        text-decoration: none;
        font-size: 13px;
        font-weight: 600;
        transition: 0.2s;
        white-space: nowrap;
    }

    .add-btn:hover {
        background: #7d000c;
    }

    .toggle-deleted-btn {
        padding: 9px 16px;
        border-radius: 8px;
        font-size: 13px;
        font-weight: 600;
        cursor: pointer;
        border: 1px solid var(--border-input);
        background: var(--bg-card);
        color: var(--text-secondary);
        transition: 0.2s;
        white-space: nowrap;
    }

    .toggle-deleted-btn.active {
        background: rgba(255, 69, 58, 0.10);
        color: var(--red);
        border-color: var(--red);
    }

    /* Product grid */
    .products-grid {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
        gap: 20px;
        position: relative;
        min-height: 300px;
    }

    .product-card {
        background: var(--bg-card);
        border-radius: 12px;
        overflow: hidden;
        border: 1px solid var(--border);
        cursor: pointer;
        transition: transform 0.2s, box-shadow 0.2s;
        display: flex;
        flex-direction: column;
        position: relative;
    }

    .product-card:hover {
        transform: translateY(-4px);
        box-shadow: var(--showcase-shadow);
        border-color: var(--brand-block);
    }

    .deleted-badge {
        position: absolute;
        top: 10px;
        right: 10px;
        /* white on #ff4d4d measured 3.27:1 */
        background: var(--brand-block);
        color: #fff;
        font-size: 10px;
        font-weight: 700;
        padding: 3px 8px;
        border-radius: 4px;
        z-index: 2;
        text-transform: uppercase;
    }

    .preorder-badge {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        /* #f59e0b on its own tint is 1.95:1 in light mode. */
        background: rgba(245, 158, 11, 0.13);
        color: var(--preorder-ink, #ffb761);
        border: 1px solid rgba(245, 158, 11, 0.35);
        font-size: 11px;
        font-weight: 600;
        padding: 3px 10px;
        border-radius: 20px;
        margin: 4px 0 6px;
        letter-spacing: 0.3px;
        width: fit-content;
    }
    /* Installation only: blue, so it doesn't read as a pre-order wait. */
    .preorder-badge.install-only {
        background: rgba(10, 132, 255, 0.12);
        color: var(--install-ink, #4da3ff);
        border-color: rgba(10, 132, 255, 0.35);
    }

    .card-image-wrapper {
        height: 200px;
        background: var(--bg-input);
        overflow: hidden;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .card-image-wrapper img {
        width: 100%;
        height: 100%;
        object-fit: cover;
        transition: transform 0.3s;
    }

    .product-card:hover .card-image-wrapper img {
        transform: scale(1.04);
    }

    /* Themed stand-in for a product with no photo. Replaces assets/img/
       no-image.png, a 1080x1080 black square that rendered as a solid black
       slab on the light theme. Shared by the products grid and the homepage's
       Best Sellers, which use the same card. */
    .card-image-wrapper.is-empty {
        background: var(--bg-input);
        border-bottom: 1px solid var(--border);
        color: var(--text-muted);
        flex-direction: column;
        gap: 8px;
    }
    .card-image-wrapper.is-empty::before {
        content: '\f03e';                  /* fa-image */
        font-family: 'Font Awesome 6 Free';
        font-weight: 900;
        font-size: 26px;
        opacity: .5;
    }
    .card-image-wrapper.is-empty::after {
        content: 'No image';
        font-size: 11px;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 1px;
        opacity: .75;
    }

    .card-info {
        padding: 16px;
        flex: 1;
        display: flex;
        flex-direction: column;
    }

    .product-category {
        font-size: 10px;
        text-transform: uppercase;
        letter-spacing: 1px;
        color: var(--pg-ink, var(--red));
        font-weight: 700;
        margin-bottom: 6px;
    }

    .product-title {
        font-size: 14px;
        font-weight: 600;
        color: var(--text-primary);
        margin-bottom: 10px;
        line-height: 1.4;
        min-height: 40px;
    }

    .product-meta {
        display: flex;
        justify-content: space-between;
        font-size: 11px;
        color: var(--text-muted);
        margin-bottom: 12px;
        padding-bottom: 12px;
        border-bottom: 1px solid var(--border);
    }

    .product-meta code {
        font-size: 10px;
        background: var(--bg-hover, #222);
        border-radius: 4px;
        padding: 1px 5px;
        color: var(--text-secondary, #aaa);
        font-family: monospace;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        max-width: 130px;
        display: inline-block;
        vertical-align: middle;
    }

    .sku-ref {
        display: inline-block;
        font-size: 9px;
        font-weight: 700;
        background: var(--bg-hover, #222);
        color: var(--text-muted, #666);
        border-radius: 4px;
        padding: 1px 5px;
        margin-left: 3px;
        vertical-align: middle;
        white-space: nowrap;
    }

    .price-section {
        margin-top: auto;
    }

    .price-label {
        font-size: 11px;
        color: #666;
        display: block;
        margin-bottom: 2px;
    }

    .main-price {
        font-size: 20px;
        font-weight: 800;
        color: var(--red);
    }

    .admin-prices {
        background: rgba(255, 255, 255, 0.05);
        border-radius: 8px;
        padding: 8px 10px;
        margin-top: 8px;
    }

    .admin-price-row {
        display: flex;
        justify-content: space-between;
        font-size: 11px;
        color: #888;
        margin-bottom: 4px;
    }

    .admin-price-row:last-child {
        margin-bottom: 0;
    }

    .admin-price-row .val {
        color: #ccc;
        font-weight: 600;
    }

    /* Loading spinner */
    .loading-state {
        grid-column: 1/-1;
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 80px 0;
    }

    .spinner {
        width: 36px;
        height: 36px;
        border: 3px solid rgba(231, 76, 60, 0.2);
        border-top-color: var(--red, #e74c3c);
        border-radius: 50%;
        animation: spin 0.8s linear infinite;
    }

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

    /* Skeleton loading cards — mirror the product-card shape so the grid
       keeps its layout (no flash/jump) while data loads. */
    .skeleton-card {
        background: var(--bg-card);
        border-radius: 12px;
        overflow: hidden;
        border: 1px solid var(--border);
        display: flex;
        flex-direction: column;
    }
    .skeleton-card .sk-img { height: 200px; }
    .skeleton-card .sk-body {
        padding: 16px;
        display: flex;
        flex-direction: column;
        gap: 11px;
    }
    .sk-line { height: 12px; border-radius: 6px; }
    .sk-line.sk-cat    { width: 35%; height: 9px; }
    .sk-line.sk-title  { width: 90%; height: 14px; }
    .sk-line.sk-title2 { width: 62%; height: 14px; }
    .sk-line.sk-price  { width: 45%; height: 20px; margin-top: 10px; }

    .sk-img, .sk-line {
        position: relative;
        overflow: hidden;
        background: var(--skeleton-base);
    }
    .sk-img::after, .sk-line::after {
        content: '';
        position: absolute;
        inset: 0;
        transform: translateX(-100%);
        background: linear-gradient(90deg, transparent,
                    var(--skeleton-shine) 50%, transparent);
        animation: sk-shimmer 1.25s ease-in-out infinite;
    }
    @keyframes sk-shimmer { 100% { transform: translateX(100%); } }

    /* Real cards fade in once loaded (skipped on silent resize refetches) */
    @keyframes cardFadeIn {
        from { opacity: 0; transform: translateY(6px); }
        to   { opacity: 1; transform: translateY(0); }
    }
    .products-grid.is-loaded .product-card {
        animation: cardFadeIn 0.28s var(--ease, ease) both;
    }
    @media (prefers-reduced-motion: reduce) {
        .sk-img::after, .sk-line::after { animation: none; }
        .products-grid.is-loaded .product-card { animation: none; }
    }

    /* Empty state */
    /* Shared by 18 pages. The background and border were hardcoded light
       values, so every empty state painted a white block on the dark theme —
       see the Dispatch queue. Tokens instead; the design is unchanged in the
       light theme, where --bg-card is #fff and --border is a hairline. */
    .empty-state {
        grid-column: 1/-1;
        text-align: center;
        padding: 60px 20px;
        background: var(--bg-card);
        border-radius: 12px;
        border: 2px dashed var(--border);
    }

    .empty-state h3 {
        font-size: 18px;
        color: #333;
        margin-bottom: 8px;
    }

    .empty-state p {
        color: #999;
        font-size: 14px;
        margin-bottom: 20px;
    }

    .wa-btn {
        display: inline-flex;
        align-items: center;
        gap: 8px;
        background: #25D366;
        color: #fff;
        padding: 10px 22px;
        border-radius: 8px;
        text-decoration: none;
        font-weight: 700;
        font-size: 14px;
    }

    /* Pagination */
    .pagination-container {
        display: flex;
        justify-content: center;
        margin-top: 24px;
        padding-bottom: 20px;
    }

    .pagination {
        display: flex;
        gap: 6px;
    }

    .page-btn {
        min-width: 38px;
        height: 38px;
        padding: 0 12px;
        background: #252525;
        color: #aaa;
        border: 1px solid #3d3d3d;
        border-radius: 6px;
        cursor: pointer;
        font-size: 13px;
        font-weight: 600;
        transition: 0.2s;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .page-btn:hover:not(:disabled):not(.active) {
        background: #333;
        color: #fff;
    }

    .page-btn.active {
        background: var(--red, #e74c3c);
        border-color: var(--red, #e74c3c);
        color: #fff;
        cursor: default;
    }

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

    /* ============================================
   AVATAR DROPDOWN (mobile profile menu)
   ============================================ */
.avatar-dropdown-wrap {
    position: relative;
}
 
.avatar-dropdown {
    display: none;
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    min-width: 200px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.3);
    z-index: 999;
    overflow: hidden;
    animation: dropdownFade 0.15s ease;
}
 
.avatar-dropdown.open {
    display: block;
}
 
@keyframes dropdownFade {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}
 
.avatar-dropdown-user {
    padding: 12px 16px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
 
.avatar-dropdown-name {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-heading);
}
 
.avatar-dropdown-role {
    font-size: 11px;
    color: var(--text-muted);
}
 
.avatar-dropdown-divider {
    height: 1px;
    background: var(--border);
    margin: 0;
}
 
.avatar-dropdown-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 11px 16px;
    font-size: 13px;
    font-weight: 500;
    color: var(--text-primary);
    background: none;
    border: none;
    cursor: pointer;
    text-decoration: none;
    transition: background 0.15s;
    text-align: left;
}
 
.avatar-dropdown-item:hover {
    background: var(--bg-hover);
    color: var(--red);
}
 
.avatar-dropdown-logout {
    color: var(--red);
    font-weight: 600;
}
 
/* ============================================
   MOBILE HEADER — hide desktop-only items
   ============================================ */

    /* Mobile */
    @media (max-width: 768px) {
        .desktop-only {
        display: none !important;
    }

    .cart-label {
        display: none;
    }

        .products-layout {
            flex-direction: column;
            padding: 16px;
            gap: 16px;
        }

        .filter-panel {
            flex: none;
            width: 100%;
            position: static;
        }

        .products-grid {
            grid-template-columns: repeat(2, 1fr);
            gap: 12px;
        }

        .card-image-wrapper,
        .skeleton-card .sk-img {
            height: 150px;
        }

        .product-title {
            font-size: 13px;
            min-height: 36px;
        }

        .main-price {
            font-size: 16px;
        }

        .action-header {
            flex-direction: column;
            align-items: flex-start;
            gap: 10px;
        }

        .header-actions {
            width: 100%;
            display: grid;
            grid-template-columns: 1fr 1fr;
        }

        .add-btn,
        .toggle-deleted-btn {
            text-align: center;
        }

        .top-header {
        padding: 8px 12px;
        flex-wrap: nowrap;
        overflow: visible;
    }

    /* Hide text label on theme toggle */
    .theme-label {
        display: none;
    }

    /* Hide username/role text */
    .account-info {
        display: none;
    }

    /* Hide logout text, show icon only */
    .logout-btn-header {
        font-size: 0;
        padding: 6px 8px;
    }
    .logout-btn-header::before {
        font-size: 14px;
        content: '↩';
    }

    /* Shrink cart label */
    .header-cart-link span:first-of-type + span {
        display: none;
    }

    /* Shrink credit pill */
    .header-credit-pill {
        font-size: 11px;
        padding: 4px 8px;
    }

    /* Shrink avatar */
    .avatar-container {
        width: 32px;
        height: 32px;
        font-size: 13px;
    }
    }
/* EndProductsStyle */
@media (min-width: 769px) {
    /* On mobile, use position:fixed so dropdown escapes overflow:hidden parent */
    .avatar-dropdown {
        position: fixed;
        top: 60px;
        right: 12px;
        left: auto;
        min-width: 220px;
        z-index: 9999;
    }
    .avatar-dropdown.open {
        display: block;
    }
}

/* ── Inventory tabs — mobile fix ───────────────── */
@media (max-width: 768px) {
    .tab-nav {
        overflow-x: auto;
        flex-wrap: nowrap;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        padding: 5px;
    }

    .tab-nav::-webkit-scrollbar {
        display: none;
    }

    .tab-btn {
        flex: none;
        white-space: nowrap;
        padding: 8px 12px;
        font-size: 12px;
    }

    .tab-badge {
        font-size: 10px;
        padding: 1px 5px;
    }
}