/* =============================================
   AutoParts — Main CSS
   Flat, light-first design system (calibrated against trodo.com).
   See the THEME TOKENS block below before changing any colour.
   ============================================= */

/* ---- Google Font ---- */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap');

/* =============================================
   THEME TOKENS

   Calibrated against trodo.com, the reference the client picked: a flat,
   light-first parts catalogue. The rules that keep it looking serious:

     * NO gradients anywhere. Every fill is one solid colour.
     * NO glows, and shadows only where something genuinely floats
       (dropdowns, modals). Cards are separated by a 1px border instead.
     * Small radii (4px surfaces / 6px controls), not pill-shaped.
     * One accent (blue) for actions and links. Amber is reserved for
       warnings — it is NOT the price colour; prices are plain dark ink,
       which is what makes a catalogue read as a catalogue.
     * Restrained weights: 600 for headings, never 800/900.

   Light is the DEFAULT theme (`:root`); dark is the opt-in variant. Every
   variable is defined in both and keeps its ROLE, not its lightness, so the
   ~700 var() call sites need no per-theme handling:

     --bg-primary    page background
     --bg-secondary  recessed fill: inputs, hovers, table stripes
     --bg-card       card / panel surface
     --bg-card-hover card surface, hovered
     --bg-nav        sticky bars (navbar, admin topbar)

   The active theme is written to `data-theme` on <html> by the inline script
   in includes/theme_boot.php (see it for why that must run before paint).
   ============================================= */
:root {
    color-scheme: light;

    /* Surfaces */
    --bg-primary:    #FBFBFC;
    --bg-secondary:  #F4F6F8;
    --bg-card:       #FFFFFF;
    --bg-card-hover: #F9FAFB;
    --bg-nav:        #FFFFFF;
    --bg-overlay:    rgba(33, 43, 54, 0.45);
    --bg-row-alt:    #FAFBFC;
    --bg-img-placeholder: #F4F6F8;

    /* The dark band behind the hero. A flat slate, not a gradient. */
    --bg-hero:       #212B36;
    --text-on-hero:  #FFFFFF;
    --text-on-hero-muted: #B6BEC7;

    /* Accent — one blue, used for actions and links only. */
    --blue-400: #0077C7;
    --blue-500: #0077C7;
    --blue-600: #0069B0;
    --blue-700: #005991;

    /* Warnings / attention. Never used for prices. */
    --amber-400: #B45309;
    --amber-500: #C2680C;
    --amber-600: #92400E;
    --on-amber:  #FFFFFF;

    --green-500: #067A54;
    --green-text:#067A54;
    --red-500:   #D42C2C;
    --red-400:   #D42C2C;

    /* Ink */
    --text-primary:   #212B36;
    --text-secondary: #4A5765;
    --text-muted:     #637381;

    /* Price gets its own token so it is never confused with an accent. */
    --price-color: #212B36;

    /* Hairlines. A card is a white box with a 1px border and nothing else. */
    --border:      #E6E9EC;
    --border-blue: #B7D8EE;
    --border-card: #E6E9EC;

    /* Badges over product photography stay dark-on-light-text in BOTH themes:
       they sit on arbitrary images, not on the page surface. */
    --bg-img-badge:  rgba(255, 255, 255, 0.94);
    --on-img-badge:  #212B36;
    --bg-img-scrim:  none;

    /* Kept as variables because ~30 call sites reference them, but every one
       is now a SOLID colour. Do not reintroduce linear-gradient() here. */
    --gradient-blue:  #0077C7;
    --gradient-amber: #B45309;
    --gradient-hero:  #212B36;
    --gradient-card:  none;

    /* Glow is off. The names survive so the ~5 call sites keep resolving —
       as a transparent zero-shadow, because a literal `none` inside a
       comma-separated box-shadow list is invalid and voids the declaration. */
    --glow-blue:  0 0 0 rgba(0,0,0,0);
    --glow-amber: 0 0 0 rgba(0,0,0,0);

    /* Shadows: only for things that genuinely overlay the page. */
    --shadow-sm:   0 1px 2px rgba(33, 43, 54, 0.06);
    --shadow-md:   0 2px 8px rgba(33, 43, 54, 0.10);
    --shadow-lg:   0 8px 24px rgba(33, 43, 54, 0.14);
    --shadow-card: none;

    /* Radius */
    --radius-xs: 3px;
    --radius-sm: 4px;
    --radius-md: 6px;
    --radius-lg: 6px;
    --radius-xl: 8px;

    /* Transitions — short and unshowy. */
    --transition:      all 0.15s ease;
    --transition-fast: all 0.12s ease;
    --transition-slow: all 0.2s ease;
}

:root[data-theme="dark"] {
    color-scheme: dark;

    --bg-primary:    #12161C;
    --bg-secondary:  #1A1F27;
    --bg-card:       #171C23;
    --bg-card-hover: #1E242D;
    --bg-nav:        #171C23;
    --bg-overlay:    rgba(0, 0, 0, 0.6);
    --bg-row-alt:    #1A1F27;
    --bg-img-placeholder: #1A1F27;

    --bg-hero:       #0E1218;
    --text-on-hero:  #F2F4F6;
    --text-on-hero-muted: #99A4B0;

    /* Lifted so it clears contrast on a dark surface; still one accent. */
    --blue-400: #4DA8E8;
    --blue-500: #3E9BDD;
    --blue-600: #58B4EF;
    --blue-700: #7BC5F4;

    --amber-400: #D99A3C;
    --amber-500: #C9862A;
    --amber-600: #B0731F;
    --on-amber:  #12160F;

    --green-500: #35B37E;
    --green-text:#35B37E;
    --red-500:   #E5646A;
    --red-400:   #E5646A;

    --text-primary:   #E4E8ED;
    --text-secondary: #A8B2BD;
    --text-muted:     #7A8592;

    --price-color: #E4E8ED;

    --border:      #262D37;
    --border-blue: #2C4A63;
    --border-card: #262D37;

    --bg-img-badge:  rgba(10, 13, 18, 0.82);
    --on-img-badge:  #FFFFFF;
    --bg-img-scrim:  none;

    --gradient-blue:  #2C7FBE;
    --gradient-amber: #C9862A;
    --gradient-hero:  #0E1218;
    --gradient-card:  none;

    --glow-blue:  0 0 0 rgba(0,0,0,0);
    --glow-amber: 0 0 0 rgba(0,0,0,0);

    --shadow-sm:   0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-md:   0 2px 8px rgba(0, 0, 0, 0.45);
    --shadow-lg:   0 8px 24px rgba(0, 0, 0, 0.55);
    --shadow-card: none;
}

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

html {
    /* 15px base (trodo runs 14px). Every rem below scales with this, so
       this one line is what tightens the whole page density. */
    font-size: 15px;
    scroll-behavior: smooth;
    -webkit-text-size-adjust: 100%;
}

body {
    font-family: 'Inter', system-ui, -apple-system, sans-serif;
    background-color: var(--bg-primary);
    color: var(--text-primary);
    line-height: 1.6;
    min-height: 100vh;
    overflow-x: hidden;
    -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }
button, input, select, textarea { font-family: inherit; outline: none; }
ul, ol { list-style: none; }

/* The browser's own `[hidden] { display: none }` sits in the UA stylesheet, so
   ANY author rule that sets a display beats it — and almost every list item in
   this project is `display: flex`. Every JS-driven show/hide here toggles the
   `hidden` property (the vehicle-picker cards, the Brend list narrowing, the
   Marka/Model/Nəsil tag picker), and without this they set the attribute while
   the element stays perfectly visible. `!important` is the point: this has to
   outrank the component's own display, whatever it is. */
[hidden] { display: none !important; }

/* ---- Scrollbar ---- */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: var(--bg-secondary); }
::-webkit-scrollbar-thumb { background: var(--blue-700); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--blue-600); }

/* ---- Selection ---- */
::selection { background: rgba(59,130,246,0.3); color: var(--text-primary); }

/* =============================================
   LAYOUT
   ============================================= */
.container {
    width: 100%;
    max-width: 1400px;
    margin: 0 auto;
    padding: 0 24px;
}

.page-wrapper { min-height: 100vh; display: flex; flex-direction: column; }
.main-content { flex: 1; }

/* Grid */
.grid-products {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 24px;
}

/* =============================================
   NAVBAR
   ============================================= */
.navbar {
    position: sticky;
    top: 0;
    z-index: 100;
    background: var(--bg-nav);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border-bottom: 1px solid var(--border);
    padding: 0;
}

.navbar-inner {
    display: flex;
    align-items: center;
    gap: 24px;
    height: 70px;
}

.navbar-logo {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 1.35rem;
    font-weight: 600;
    letter-spacing: -0.2px;
    flex-shrink: 0;
}

.navbar-logo .logo-icon {
    width: 36px;
    height: 36px;
    background: var(--gradient-blue);
    border-radius: var(--radius-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.1rem;
    box-shadow: var(--glow-blue);
}

.logo-text-auto { color: var(--text-primary); }
.logo-text-parts { color: var(--blue-400); }

/* Uploaded logo. Height-capped and width-free so a wide wordmark and a square
   badge both sit on the same navbar line without either being distorted —
   `contain` never crops, and the shop's own artwork is the one image on the
   page we must not second-guess. */
.logo-img {
    height: 38px;
    width: auto;
    max-width: 200px;
    object-fit: contain;
    display: block;
}

.navbar-search {
    flex: 1;
    max-width: 560px;
    position: relative;
}

.navbar-search input {
    width: 100%;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 11px 48px 11px 18px;
    color: var(--text-primary);
    font-size: 0.9rem;
    transition: var(--transition);
}

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

.navbar-search input:focus {
    border-color: var(--blue-500);
    background: var(--bg-card);
    box-shadow: 0 0 0 3px rgba(59,130,246,0.12);
}

.navbar-search-icon {
    position: absolute;
    right: 14px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-muted);
    pointer-events: none;
    display: flex;
}

.navbar-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
}

.nav-icon-btn {
    width: 42px;
    height: 42px;
    border-radius: var(--radius-sm);
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: var(--transition);
    color: var(--text-secondary);
    position: relative;
}

.nav-icon-btn:hover {
    background: var(--bg-card-hover);
    border-color: var(--border-blue);
    color: var(--text-primary);
}

.cart-badge {
    position: absolute;
    top: -5px;
    right: -5px;
    background: var(--gradient-amber);
    color: var(--on-amber);
    font-size: 0.65rem;
    font-weight: 700;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid var(--bg-primary);
    line-height: 1;
}

/* =============================================
   HERO SECTION
   ============================================= */
.hero {
    background: var(--gradient-hero);
    padding: 80px 0 60px;
    position: relative;
    overflow: hidden;
}

/* Uploaded banner photo. The scrim is not decoration: the hero copy is light,
   the admin can upload any photograph, and a bright sky behind white text is
   unreadable. A fixed dark overlay is the only thing that makes an ARBITRARY
   image safe here — sampling the image to pick a text colour is not something
   a PHP page can do, and asking the admin to "upload something dark" is a rule
   nobody remembers. `background-image` is set inline by index.php. */
.hero.has-bg {
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

.hero.has-bg::before {
    content: '';
    position: absolute;
    inset: 0;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(15, 23, 42, 0.72);
    pointer-events: none;
}

/* The hero's own copy is light by design, but on a light-theme page without a
   photo it sits on the themed hero background. With a photo it always sits on
   the dark scrim, so the text is pinned light there regardless of theme. */
.hero.has-bg .hero-title,
.hero.has-bg .hero-title .gradient-text { color: #FFFFFF; }
.hero.has-bg .hero-subtitle,
.hero.has-bg .hero-stat-label { color: rgba(255, 255, 255, 0.82); }
.hero.has-bg .hero-stat-value { color: #FFFFFF; }

.hero::before {
    content: '';
    position: absolute;
    top: -50%;
    left: -10%;
    width: 60%;
    height: 200%;
    background: none;
    pointer-events: none;
}

.hero::after {
    content: '';
    position: absolute;
    bottom: -30%;
    right: -5%;
    width: 50%;
    height: 150%;
    background: none;
    pointer-events: none;
}

.hero-grid-bg {
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(rgba(255,255,255,0.045) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255,255,255,0.045) 1px, transparent 1px);
    background-size: 50px 50px;
    pointer-events: none;
}

.hero-content {
    position: relative;
    z-index: 1;
    max-width: 700px;
}

.hero-badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: rgba(59,130,246,0.1);
    border: 1px solid rgba(59,130,246,0.25);
    border-radius: 100px;
    padding: 6px 16px;
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--blue-400);
    margin-bottom: 24px;
}

.hero-title {
    font-size: clamp(1.75rem, 4vw, 2.4rem);
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: -0.2px;
    margin-bottom: 16px;
    color: var(--text-on-hero);
}

/* Was a blue->amber gradient fill. Solid now; the emphasis comes from
   weight and colour, not from a rainbow. */
.hero-title .gradient-text { color: var(--text-on-hero); }

.hero-subtitle {
    font-size: 1.05rem;
    color: var(--text-secondary);
    margin-bottom: 36px;
    max-width: 550px;
    line-height: 1.7;
}

.hero-search {
    display: flex;
    gap: 12px;
    max-width: 600px;
}

.hero-search input {
    flex: 1;
    background: rgba(13, 21, 38, 0.8);
    border: 1px solid var(--border-blue);
    border-radius: var(--radius-md);
    padding: 16px 22px;
    color: var(--text-primary);
    font-size: 0.95rem;
    backdrop-filter: blur(10px);
    transition: var(--transition);
}

.hero-search input:focus {
    border-color: var(--blue-500);
    box-shadow: 0 0 0 3px rgba(59,130,246,0.15);
}

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

.hero-stats {
    display: flex;
    gap: 40px;
    margin-top: 48px;
}

.hero-stat { }
.hero-stat-value {
    font-size: 1.8rem;
    font-weight: 600;
    color: var(--text-primary);
    letter-spacing: -0.2px;
}
.hero-stat-label { font-size: 0.8rem; color: var(--text-muted); margin-top: 2px; }

/* =============================================
   CATEGORY BAR
   ============================================= */
/* =============================================
   VEHICLE PICKER — Marka → Model → Nəsil, as cards
   One step is on screen at a time (see renderVehiclePicker()); every card is a
   real <a>, so all of this is link styling, not widget styling.
   ============================================= */
.vehicle-picker {
    background: var(--bg-card);
    border-bottom: 1px solid var(--border);
    padding: 22px 0 24px;
}

.vp-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}

.vp-title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--text-primary);
}

.vp-title svg { color: var(--blue-400); flex-shrink: 0; }

.vp-hint {
    margin-top: 3px;
    font-size: 0.82rem;
    color: var(--text-muted);
}

/* Three static labels, lit up to the current step. Deliberately not links —
   the breadcrumb below is the thing you navigate with; this only says where
   you are, so two controls never compete for the same job. */
.vp-progress { display: flex; align-items: center; gap: 6px; }

.vp-progress-step {
    padding: 4px 10px;
    border-radius: 999px;
    border: 1px solid var(--border);
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text-muted);
    white-space: nowrap;
}

.vp-progress-step.is-on {
    border-color: rgba(59, 130, 246, 0.35);
    background: rgba(59, 130, 246, 0.10);
    color: var(--blue-400);
}

.vp-crumbs {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 14px;
    font-size: 0.83rem;
}

.vp-crumb { color: var(--blue-400); font-weight: 500; }
.vp-crumb:hover { text-decoration: underline; }
.vp-crumb.is-current { color: var(--text-primary); font-weight: 700; }
.vp-crumb-sep { color: var(--text-muted); }

.vp-crumb-reset {
    margin-left: auto;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--text-muted);
}
.vp-crumb-reset:hover { color: var(--red-400); }

.vp-search {
    position: relative;
    display: flex;
    align-items: center;
    gap: 8px;
    max-width: 300px;
    margin-bottom: 12px;
    padding: 7px 12px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}

.vp-search svg { color: var(--text-muted); flex-shrink: 0; }

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

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

.vp-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 12px;
}

/* Collapsed list: the overflow cards are RENDERED but not displayed, so the
   type-to-narrow box can still find them (it drops .is-collapsed the moment you
   type) and a no-JS visitor gets the whole list via the <noscript> override.
   Three classes beat the single-class `.vehicle-card { display: flex }`, so no
   !important is needed — and the search's own `hidden` still wins over both. */
.vp-grid.is-collapsed .vehicle-card.is-overflow { display: none; }

.vp-more {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    margin-top: 12px;
    padding: 11px 16px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-card);
    border-radius: 6px;
    color: var(--text-secondary);
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.vp-more:hover {
    background: var(--bg-card-hover);
    border-color: var(--blue-400);
    color: var(--text-primary);
}

.vp-more-count {
    padding: 2px 7px;
    border-radius: 3px;
    background: var(--bg-card);
    border: 1px solid var(--border-card);
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--text-muted);
}

.vehicle-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 9px;
    padding: 15px 10px 13px;
    background: var(--bg-card);
    border: 1px solid var(--border-card);
    border-radius: var(--radius-md);
    text-align: center;
    transition: var(--transition-fast);
}

/* Hairline + fill only — no lift, no shadow, no glow (see the token block). */
.vehicle-card:hover {
    background: var(--bg-card-hover);
    border-color: var(--blue-400);
}

.vehicle-card.is-selected {
    border-color: var(--blue-400);
    background: rgba(59, 130, 246, 0.08);
}

/* A car the shop has no parts for yet. It is still a real link — clicking it
   gives an honest empty grid rather than a card that mysteriously does nothing
   — it just must not compete for attention with the cars we do stock. Greyscale
   on top of the opacity because a colour logo at 45% still pulls the eye harder
   than a black-and-white one. Rendered only when VEHICLE_PICKER_DIM_EMPTY is on
   (config.php); with it off the class is never emitted and these rules are dead.
   Hover lifts it most of the way back so the card does not feel disabled. */
.vehicle-card.is-empty {
    opacity: 0.45;
}

.vehicle-card.is-empty .vehicle-card-img img {
    filter: grayscale(1);
}

.vehicle-card.is-empty:hover,
.vehicle-card.is-empty:focus-visible {
    opacity: 0.85;
}

.vehicle-card.is-empty:hover .vehicle-card-img img,
.vehicle-card.is-empty:focus-visible .vehicle-card-img img {
    filter: grayscale(0.25);
}

.vehicle-card-img {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 76px;
}

/* Model and nəsil tiles carry a PHOTO rather than a logo, so they get the room
   a car in three-quarter view actually needs — a wide shot squeezed into a
   logo-sized box is unrecognisable, which defeats the whole point of picking
   your car by sight. */
.vc-model .vehicle-card-img,
.vc-generation .vehicle-card-img { height: 112px; }

.vehicle-card-img img {
    max-width: 100%;
    max-height: 100%;
    /* contain, never cover: these come from wildly different sources and
       cropping a logo to fill a box mangles it. */
    object-fit: contain;
    width: auto;
    height: auto;
}

.vehicle-card-letter {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: var(--bg-secondary);
    color: var(--text-muted);
    font-size: 1.35rem;
    font-weight: 700;
}

.vehicle-card-name {
    font-size: 0.86rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--text-primary);
    /* Two lines max: a long model name must not make its card taller than the
       others in the same grid row. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.vehicle-card-sub {
    font-size: 0.74rem;
    color: var(--text-muted);
    white-space: nowrap;
}

.vp-empty {
    padding: 18px 0;
    font-size: 0.85rem;
    color: var(--text-muted);
}

@media (max-width: 640px) {
    .vehicle-picker { padding: 16px 0 18px; }
    /* Two columns on a phone rather than three: a 92px tile made the car in it
       too small to tell an E46 from an E90, which is the one thing this step
       exists to let you do. */
    .vp-grid { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; }
    .vp-progress { display: none; }
    .vehicle-card { padding: 12px 8px 11px; }
    .vehicle-card-img { height: 60px; }
    .vc-model .vehicle-card-img,
    .vc-generation .vehicle-card-img { height: 88px; }
    .vehicle-card-letter { width: 46px; height: 46px; font-size: 1.15rem; }
    .vehicle-card-name { font-size: 0.79rem; }
}

.category-bar {
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border);
    padding: 0;
}

.category-bar-inner {
    display: flex;
    gap: 4px;
    padding: 12px 0;
    overflow-x: auto;
    scrollbar-width: none;
}

.category-bar-inner::-webkit-scrollbar { display: none; }

.cat-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 8px 16px;
    border-radius: var(--radius-sm);
    background: transparent;
    border: 1px solid transparent;
    color: var(--text-secondary);
    font-size: 0.85rem;
    font-weight: 500;
    cursor: pointer;
    transition: var(--transition-fast);
    white-space: nowrap;
}

.cat-btn:hover {
    background: var(--bg-card);
    color: var(--text-primary);
    border-color: var(--border);
}

.cat-btn.active {
    background: rgba(59,130,246,0.12);
    border-color: rgba(59,130,246,0.3);
    color: var(--blue-400);
}

/* ---- Subcategory strip (second level, inside .category-bar) ----
   Visually subordinate to .cat-btn on purpose: smaller, pill-shaped and
   separated by a hairline, so the two rows read as parent and child rather
   than as two competing sets of filters. */
.subcategory-bar-inner {
    display: flex;
    gap: 4px;
    padding: 0 0 12px;
    margin-top: -4px;
    overflow-x: auto;
    scrollbar-width: none;
    border-top: 1px solid var(--border);
    padding-top: 10px;
}

.subcategory-bar-inner::-webkit-scrollbar { display: none; }

.subcat-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    border-radius: 999px;
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-secondary);
    font-size: 0.79rem;
    font-weight: 500;
    cursor: pointer;
    transition: var(--transition-fast);
    white-space: nowrap;
}

.subcat-btn:hover {
    background: var(--bg-card);
    color: var(--text-primary);
}

.subcat-btn.active {
    background: rgba(59,130,246,0.12);
    border-color: rgba(59,130,246,0.3);
    color: var(--blue-400);
}

.subcat-count {
    font-size: 0.7rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.subcat-btn.active .subcat-count { color: var(--blue-400); }

/* =============================================
   PRODUCTS SECTION
   ============================================= */
.products-section { padding: 40px 0 60px; }

.section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 28px;
    gap: 16px;
    flex-wrap: wrap;
}

.section-title {
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--text-primary);
}

.section-count {
    font-size: 0.85rem;
    color: var(--text-muted);
    margin-top: 2px;
}

.sort-select {
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 9px 14px;
    color: var(--text-secondary);
    font-size: 0.85rem;
    cursor: pointer;
    transition: var(--transition);
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2364748B' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    padding-right: 30px;
}

.sort-select:focus { border-color: var(--blue-500); color: var(--text-primary); }

/* =============================================
   PRODUCT CARD
   ============================================= */
.product-card {
    background: var(--bg-card);
    border: 1px solid var(--border-card);
    border-radius: var(--radius-lg);
    overflow: hidden;
    transition: var(--transition);
    cursor: pointer;
    display: flex;
    flex-direction: column;
    position: relative;
    box-shadow: var(--shadow-card);
}

.product-card:hover {
    transform: translateY(-4px);
    border-color: var(--border-blue);
    box-shadow: var(--shadow-md), var(--glow-blue);
    background: var(--bg-card-hover);
}

.product-card-image {
    position: relative;
    aspect-ratio: 4/3;
    background: var(--bg-img-placeholder);
    overflow: hidden;
    flex-shrink: 0;
}

.product-card-image img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    padding: 20px;
    transition: var(--transition-slow);
}

.product-card:hover .product-card-image img {
    transform: none;
}

.product-card-image-overlay {
    position: absolute;
    inset: 0;
    background: var(--bg-img-scrim);
}

.product-brand-badge {
    position: absolute;
    top: 12px;
    left: 12px;
    background: var(--bg-img-badge);
    backdrop-filter: blur(10px);
    border: 1px solid var(--border);
    border-radius: var(--radius-xs);
    padding: 4px 10px;
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--on-img-badge);
    letter-spacing: 0.5px;
    text-transform: uppercase;
}

.product-stock-badge {
    position: absolute;
    top: 12px;
    right: 12px;
    border-radius: var(--radius-xs);
    padding: 4px 8px;
    font-size: 0.7rem;
    font-weight: 600;
}

.stock-in  { background: rgba(16,185,129,0.15); color: var(--green-500); border: 1px solid rgba(16,185,129,0.25); }
.stock-out { background: rgba(239, 68, 68,0.15); color: var(--red-400);  border: 1px solid rgba(239,68,68,0.25); }

/* Make/Model tag chip — product.php's structured "Marka / Model" row */
.model-tag {
    display: inline-block;
    background: rgba(59,130,246,0.12);
    color: var(--blue-400);
    border: 1px solid rgba(59,130,246,0.2);
    border-radius: var(--radius-xs);
    padding: 4px 10px;
    font-size: 0.78rem;
    font-weight: 600;
    margin: 0 6px 6px 0;
}

.product-card-body {
    padding: 18px 18px 14px;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.product-category {
    font-size: 0.72rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    font-weight: 500;
}

.product-name {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--text-primary);
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.product-code-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: rgba(59,130,246,0.15);
    border: 1px solid rgba(59,130,246,0.3);
    border-radius: var(--radius-xs);
    padding: 4px 10px;
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--blue-400);
    width: fit-content;
    font-family: 'Courier New', monospace;
}

.product-card-footer {
    padding: 0 18px 18px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: auto;
}

.product-price {
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--price-color);
    letter-spacing: -0.2px;
}

/* ---- Discounted prices (renderPrice() in functions.php) ----
   The struck-through number is the STANDARD price; the plain one is what the
   customer actually pays. Muted and smaller so the pair reads as one price with
   a history rather than two numbers competing for attention.

   Deliberately no coloured fills or "SALE!" ribbons on the grid — the card has
   to keep reading as a catalogue row (see the palette note at the top of this
   file, and note that amber is reserved for warnings and is never a price).
   Only the product page spells the percentage out. */
.price-old {
    color: var(--text-muted);
    font-weight: 500;
    text-decoration: line-through;
    /* em, not rem: the same markup is dropped into the card, the detail page,
       the buy bar, the cart row and the suggest dropdown, each at its own size. */
    font-size: 0.82em;
    margin-right: 6px;
}

.price-new { color: var(--price-color); }

.product-price.has-discount,
.product-detail-price.has-discount,
.buy-bar-price.has-discount {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
}

.price-off {
    margin-left: 10px;
    padding: 2px 7px;
    border: 1px solid var(--red-500);
    border-radius: var(--radius-sm);
    color: var(--red-500);
    font-size: 0.5em;
    font-weight: 700;
    letter-spacing: 0;
    white-space: nowrap;
}

.sg-price.has-discount { display: inline-flex; align-items: baseline; }

.btn-add-cart {
    display: flex;
    align-items: center;
    gap: 6px;
    background: var(--gradient-blue);
    border: none;
    border-radius: var(--radius-sm);
    padding: 9px 16px;
    color: #fff;
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
    transition: var(--transition);
    white-space: nowrap;
}

.btn-add-cart:hover {
    transform: scale(1.04);
    box-shadow: var(--glow-blue);
}

.btn-add-cart:active { transform: scale(0.97); }

.btn-add-cart.added {
    background: var(--green-500);
}

/* =============================================
   BUTTONS
   ============================================= */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 11px 22px;
    border-radius: var(--radius-sm);
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
    transition: var(--transition);
    border: none;
    line-height: 1;
}

.btn-primary {
    background: var(--gradient-blue);
    color: #fff;
}
.btn-primary:hover { opacity: 0.9; transform: translateY(-1px); box-shadow: var(--glow-blue); }

.btn-amber {
    background: var(--gradient-amber);
    color: var(--on-amber);
}
.btn-amber:hover { opacity: 0.9; transform: translateY(-1px); box-shadow: var(--glow-amber); }

.btn-whatsapp {
    background: #25D366;
    color: #fff;
    padding: 14px 28px;
    font-size: 1rem;
    border-radius: var(--radius-md);
}
.btn-whatsapp:hover { opacity: 0.95; transform: translateY(-2px); box-shadow: 0 0 25px rgba(37,211,102,0.3); }

.btn-outline {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-secondary);
}
.btn-outline:hover { border-color: var(--border-blue); color: var(--text-primary); background: var(--bg-card); }

.btn-danger {
    background: rgba(239,68,68,0.15);
    border: 1px solid rgba(239,68,68,0.25);
    color: var(--red-400);
}
.btn-danger:hover { background: rgba(239,68,68,0.25); }

.btn-sm { padding: 7px 14px; font-size: 0.8rem; }
.btn-lg { padding: 16px 32px; font-size: 1rem; }
.btn-full { width: 100%; }

/* =============================================
   MINI CART SIDEBAR
   ============================================= */
.cart-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.6);
    backdrop-filter: blur(4px);
    z-index: 200;
    opacity: 0;
    visibility: hidden;
    transition: var(--transition);
}

.cart-overlay.open { opacity: 1; visibility: visible; }

.cart-sidebar {
    position: fixed;
    top: 0;
    right: 0;
    width: 420px;
    max-width: 100vw;
    height: 100vh;
    background: var(--bg-secondary);
    border-left: 1px solid var(--border);
    z-index: 201;
    display: flex;
    flex-direction: column;
    transform: translateX(100%);
    transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.cart-sidebar.open { transform: translateX(0); }

.cart-sidebar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 22px 24px;
    border-bottom: 1px solid var(--border);
}

.cart-sidebar-title {
    font-size: 1.1rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    gap: 10px;
}

.cart-close-btn {
    width: 36px;
    height: 36px;
    border-radius: var(--radius-xs);
    background: var(--bg-card);
    border: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: var(--text-secondary);
    transition: var(--transition-fast);
}
.cart-close-btn:hover { color: var(--text-primary); border-color: var(--border-blue); }

.cart-sidebar-items {
    flex: 1;
    overflow-y: auto;
    padding: 16px 24px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.cart-item {
    display: flex;
    gap: 14px;
    background: var(--bg-card);
    border: 1px solid var(--border-card);
    border-radius: var(--radius-md);
    padding: 14px;
    transition: var(--transition-fast);
}

.cart-item:hover { border-color: var(--border); }

.cart-item-img {
    width: 70px;
    height: 70px;
    border-radius: var(--radius-xs);
    background: var(--bg-primary);
    overflow: hidden;
    flex-shrink: 0;
}

.cart-item-img img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    padding: 6px;
}

.cart-item-info { flex: 1; min-width: 0; }

.cart-item-name {
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-bottom: 3px;
}

.cart-item-brand {
    font-size: 0.75rem;
    color: var(--blue-400);
    margin-bottom: 8px;
}

.cart-item-controls {
    display: flex;
    align-items: center;
    gap: 10px;
}

.qty-btn {
    width: 26px;
    height: 26px;
    border-radius: var(--radius-xs);
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8rem;
    font-weight: 700;
    transition: var(--transition-fast);
}
.qty-btn:hover { border-color: var(--border-blue); color: var(--text-primary); }

.qty-value {
    font-size: 0.9rem;
    font-weight: 700;
    min-width: 20px;
    text-align: center;
}

.cart-item-price {
    font-size: 1rem;
    font-weight: 700;
    color: var(--price-color);
    white-space: nowrap;
    align-self: center;
}

.cart-item-remove {
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    padding: 2px;
    display: flex;
    align-items: center;
    transition: var(--transition-fast);
    align-self: flex-start;
}
.cart-item-remove:hover { color: var(--red-400); }

.cart-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 16px;
    flex: 1;
    color: var(--text-muted);
    text-align: center;
    padding: 40px;
}

.cart-empty-icon {
    font-size: 3.5rem;
    opacity: 0.4;
}

.cart-sidebar-footer {
    padding: 20px 24px;
    border-top: 1px solid var(--border);
}

.cart-total-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16px;
}

.cart-total-label { color: var(--text-secondary); font-size: 0.9rem; }
.cart-total-amount {
    font-size: 1.3rem;
    font-weight: 600;
    color: var(--price-color);
}

/* =============================================
   FILTER SIDEBAR (Desktop)
   ============================================= */
.shop-layout {
    display: grid;
    grid-template-columns: 260px 1fr;
    gap: 28px;
    align-items: start;
}

/* AJAX filtering (ShopFilter in main.js) swaps this region's contents in
   place. While the request is in flight the layout dims and stops taking
   clicks, so a second filter can't be queued against results that are about
   to be replaced. Deliberately no spinner and no height change — the grid
   must not shift under the pointer. */
.shop-layout.is-loading {
    opacity: .45;
    pointer-events: none;
    transition: opacity .18s ease;
}

.shop-layout.is-loading .filter-sidebar {
    /* The sidebar is what the user is actually interacting with — keep it
       legible so the control they just changed stays readable. */
    opacity: .85;
}

.filter-sidebar {
    position: sticky;
    top: 90px;
    background: var(--bg-card);
    border: 1px solid var(--border-card);
    border-radius: var(--radius-lg);
    padding: 24px;
}

.filter-title {
    font-size: 0.9rem;
    font-weight: 700;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.8px;
    margin-bottom: 16px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--border);
}

.filter-group { margin-bottom: 24px; }

.filter-group-label {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 10px;
}

.filter-check-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-height: 200px;
    overflow-y: auto;
}

.filter-check-item {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 7px 10px;
    border-radius: var(--radius-xs);
    cursor: pointer;
    transition: var(--transition-fast);
    font-size: 0.85rem;
}

.filter-check-item:hover { background: var(--bg-secondary); }

.filter-check-item input[type="checkbox"] {
    width: 16px;
    height: 16px;
    accent-color: var(--blue-500);
    cursor: pointer;
}

/* ---- Filter list search (Brend) ---- */
.filter-search {
    position: relative;
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 0 10px;
    margin-bottom: 8px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-xs);
    color: var(--text-muted);
    transition: var(--transition-fast);
}

.filter-search:focus-within {
    border-color: var(--border-blue);
    color: var(--blue-400);
}

.filter-search input {
    flex: 1;
    min-width: 0;
    background: none;
    border: 0;
    outline: none;
    padding: 8px 0;
    font-family: inherit;
    font-size: 0.82rem;
    color: var(--text-primary);
}

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

.filter-search-empty {
    padding: 8px 10px;
    font-size: 0.78rem;
    color: var(--text-muted);
}

.filter-clear {
    display: block;
    margin-top: 8px;
    font-size: 0.75rem;
    color: var(--text-muted);
    transition: var(--transition-fast);
}

.filter-clear:hover { color: var(--red-400); }

/* =============================================
   SEARCHABLE SELECT (assets/js/searchable-select.js)
   The real <select> stays in the form but is taken out of the visual flow;
   .ss-trigger + .ss-panel are what the user actually interacts with.
   ============================================= */
.ss { position: relative; }

/* While open the whole wrapper is lifted, so the panel clears any *later*
   sibling card that would otherwise paint over it. */
.ss.is-open { z-index: 70; }

/* Set by searchable-select.js on clipping ancestors for as long as the panel is
   open — see the unclip() comment there. !important because the rules it defeats
   (.table-card and friends) are plain class selectors it must outrank whatever
   the ancestor turns out to be. */
.ss-unclip { overflow: visible !important; }

/* Not display:none — the select must keep participating in the form, and
   some browsers skip validation/serialization on fully hidden controls. */
.ss-native {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
    clip: rect(0 0 0 0);
}

.ss-trigger {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 10px 13px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-family: inherit;
    font-size: 0.86rem;
    text-align: left;
    cursor: pointer;
    transition: var(--transition-fast);
}

.ss-trigger:hover { border-color: var(--border-blue); }

.ss-trigger:focus-visible,
.ss.is-open .ss-trigger {
    outline: none;
    border-color: var(--blue-500);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}

.ss.is-empty .ss-value { color: var(--text-muted); }

.ss-value {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ss-caret {
    flex-shrink: 0;
    font-size: 0.7rem;
    color: var(--text-muted);
    transition: var(--transition-fast);
}

.ss.is-open .ss-caret { transform: rotate(180deg); }

.ss-panel {
    position: absolute;
    top: calc(100% + 5px);
    left: 0;
    right: 0;
    z-index: 60;
    background: var(--bg-card);
    border: 1px solid var(--border-blue);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}

.ss-search {
    width: 100%;
    padding: 10px 13px;
    background: var(--bg-secondary);
    border: 0;
    border-bottom: 1px solid var(--border);
    outline: none;
    font-family: inherit;
    font-size: 0.84rem;
    color: var(--text-primary);
}

.ss-search::placeholder { color: var(--text-muted); }

.ss-list {
    list-style: none;
    margin: 0;
    padding: 4px;
    max-height: 220px;
    overflow-y: auto;
}

.ss-option {
    padding: 8px 11px;
    border-radius: var(--radius-xs);
    font-size: 0.85rem;
    color: var(--text-secondary);
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Keyboard-active and pointer-hover deliberately share one look — there is
   only ever one "next Enter target". */
.ss-option.is-active,
.ss-option:hover {
    background: var(--bg-card-hover);
    color: var(--text-primary);
}

.ss-option.is-selected {
    color: var(--blue-400);
    font-weight: 600;
}

.ss-empty {
    padding: 12px 13px;
    font-size: 0.8rem;
    color: var(--text-muted);
    text-align: center;
}

.price-inputs {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}

.price-input {
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-xs);
    padding: 8px 12px;
    color: var(--text-primary);
    font-size: 0.85rem;
    width: 100%;
    transition: var(--transition);
}

.price-input:focus {
    border-color: var(--blue-500);
    box-shadow: 0 0 0 2px rgba(59,130,246,0.1);
}

/* =============================================
   PRODUCT DETAIL
   ============================================= */
.product-detail { padding: 40px 0 60px; }

.breadcrumb {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 32px;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.breadcrumb a { color: var(--text-muted); transition: var(--transition-fast); }
.breadcrumb a:hover { color: var(--blue-400); }
.breadcrumb-sep { color: var(--border); }

.product-detail-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 48px;
    align-items: start;
}

.product-detail-image {
    background: var(--bg-card);
    border: 1px solid var(--border-card);
    border-radius: var(--radius-xl);
    aspect-ratio: 1;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px;
}

.product-detail-image img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.product-detail-info {}

.product-detail-category {
    font-size: 0.8rem;
    color: var(--blue-400);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    margin-bottom: 10px;
}

.product-detail-name {
    font-size: 1.8rem;
    font-weight: 600;
    line-height: 1.3;
    letter-spacing: -0.2px;
    margin-bottom: 20px;
}

.product-detail-meta {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 20px;
    background: var(--bg-card);
    border: 1px solid var(--border-card);
    border-radius: var(--radius-md);
    margin-bottom: 24px;
}

.meta-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 0.9rem;
}

.meta-label { color: var(--text-muted); }
.meta-value { font-weight: 600; color: var(--text-primary); font-family: monospace; }

/* The other meta values are one short line; fitment is free text up to 500
   chars, so this row has to top-align and let the value wrap instead of
   squeezing the label. */
.meta-row-block { align-items: flex-start; gap: 16px; }
.meta-row-block .meta-label { flex: 0 0 auto; }
.meta-fitment {
    text-align: right;
    line-height: 1.5;
    overflow-wrap: anywhere;
    word-break: break-word;
    min-width: 0;
}

.product-detail-price {
    font-size: 1.75rem;
    font-weight: 600;
    color: var(--price-color);
    letter-spacing: -0.3px;
    margin-bottom: 24px;
}

.product-detail-actions {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.qty-control {
    display: flex;
    align-items: center;
    gap: 12px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 4px;
    width: fit-content;
}

.qty-control-btn {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-xs);
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    font-size: 1.1rem;
    font-weight: 700;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: var(--transition-fast);
}
.qty-control-btn:hover { color: var(--text-primary); border-color: var(--blue-500); }

.qty-control-value {
    font-size: 1rem;
    font-weight: 700;
    min-width: 32px;
    text-align: center;
}

.product-detail-desc {
    margin-top: 32px;
    padding-top: 28px;
    border-top: 1px solid var(--border);
}

.product-detail-desc h3 {
    font-size: 1rem;
    font-weight: 700;
    margin-bottom: 12px;
}

.product-detail-desc p {
    font-size: 0.9rem;
    color: var(--text-secondary);
    line-height: 1.75;
}

/* Related Products */
.related-section { padding: 40px 0; border-top: 1px solid var(--border); }
.related-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 20px;
}

/* =============================================
   CART PAGE
   ============================================= */
.cart-page { padding: 40px 0 60px; }
.cart-page-title {
    font-size: 1.8rem;
    font-weight: 600;
    margin-bottom: 32px;
    letter-spacing: -0.2px;
}

.cart-page-layout {
    display: grid;
    grid-template-columns: 1fr 340px;
    gap: 28px;
    align-items: start;
}

.cart-page-items {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.cart-page-item {
    display: flex;
    gap: 18px;
    background: var(--bg-card);
    border: 1px solid var(--border-card);
    border-radius: var(--radius-md);
    padding: 18px;
    align-items: center;
    transition: var(--transition-fast);
}

.cart-page-item:hover { border-color: var(--border); }

.cart-page-item-img {
    width: 90px;
    height: 90px;
    background: var(--bg-secondary);
    border-radius: var(--radius-sm);
    overflow: hidden;
    flex-shrink: 0;
}

.cart-page-item-img img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    padding: 8px;
}

.cart-page-item-info { flex: 1; }

.cart-page-item-name {
    font-size: 1rem;
    font-weight: 600;
    margin-bottom: 4px;
}

.cart-page-item-meta {
    display: flex;
    gap: 12px;
    font-size: 0.8rem;
    color: var(--text-muted);
    margin-bottom: 12px;
}

.cart-page-item-meta span { color: var(--blue-400); font-weight: 500; }

.cart-summary-card {
    background: var(--bg-card);
    border: 1px solid var(--border-card);
    border-radius: var(--radius-lg);
    padding: 24px;
    position: sticky;
    top: 90px;
}

.cart-summary-title {
    font-size: 1.05rem;
    font-weight: 700;
    margin-bottom: 20px;
    padding-bottom: 16px;
    border-bottom: 1px solid var(--border);
}

.cart-summary-row {
    display: flex;
    justify-content: space-between;
    font-size: 0.9rem;
    margin-bottom: 10px;
    color: var(--text-secondary);
}

.cart-summary-total {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-top: 16px;
    margin-top: 8px;
    border-top: 1px solid var(--border);
}

.cart-summary-total-label { font-weight: 600; font-size: 1rem; }
.cart-summary-total-amount {
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--price-color);
    letter-spacing: -0.2px;
}

.whatsapp-note {
    background: rgba(37,211,102,0.06);
    border: 1px solid rgba(37,211,102,0.15);
    border-radius: var(--radius-sm);
    padding: 12px;
    font-size: 0.8rem;
    color: var(--green-text);
    margin: 16px 0;
    line-height: 1.6;
}

/* =============================================
   FORMS
   ============================================= */
.form-group { margin-bottom: 18px; }

.form-label {
    display: block;
    font-size: 0.83rem;
    font-weight: 600;
    color: var(--text-secondary);
    margin-bottom: 7px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
}

.form-control {
    width: 100%;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 11px 14px;
    color: var(--text-primary);
    font-size: 0.9rem;
    transition: var(--transition);
}

.form-control:focus {
    outline: none;
    border-color: var(--blue-500);
    box-shadow: 0 0 0 3px rgba(59,130,246,0.12);
    background: var(--bg-card);
}

.form-control::placeholder { color: var(--text-muted); }

textarea.form-control {
    resize: vertical;
    min-height: 100px;
}

select.form-control {
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2394A3B8' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    padding-right: 36px;
}

/* =============================================
   ALERTS
   ============================================= */
.alert {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 13px 16px;
    border-radius: var(--radius-sm);
    font-size: 0.88rem;
    font-weight: 500;
    margin-bottom: 16px;
}

.alert-success { background: rgba(16,185,129,0.1); border: 1px solid rgba(16,185,129,0.2); color: var(--green-text); }
.alert-error   { background: rgba(239,68,68,0.1);  border: 1px solid rgba(239,68,68,0.2);  color: var(--red-400); }
.alert-warning { background: rgba(245,158,11,0.1); border: 1px solid rgba(245,158,11,0.2); color: var(--amber-400); }
.alert-info    { background: rgba(59,130,246,0.1); border: 1px solid rgba(59,130,246,0.2); color: var(--blue-400); }
/* .alert is display:flex for the icon+one-line-of-text case. A text-heavy
   alert — several sentences, a <strong> or two, a follow-up line — turns every
   text run into its own flex item and gets laid out in columns. This is the
   opt-out for those. */
.alert-block   { display: block; }

/* =============================================
   PAGINATION
   ============================================= */
.pagination {
    display: flex;
    gap: 6px;
    justify-content: center;
    margin-top: 40px;
    flex-wrap: wrap;
}

.page-btn {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-xs);
    background: var(--bg-card);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    font-size: 0.85rem;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: var(--transition-fast);
    text-decoration: none;
}

.page-btn:hover { border-color: var(--border-blue); color: var(--text-primary); }
.page-btn.active { background: var(--gradient-blue); border-color: var(--blue-500); color: #fff; }
.page-ellipsis { background: none; border-color: transparent; cursor: default; pointer-events: none; }

/* =============================================
   EMPTY STATE
   ============================================= */
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 80px 24px;
    text-align: center;
    gap: 16px;
}

.empty-state-icon {
    font-size: 4rem;
    opacity: 0.25;
    margin-bottom: 8px;
}

.empty-state h3 { font-size: 1.2rem; font-weight: 700; }
.empty-state p  { color: var(--text-muted); font-size: 0.9rem; }

/* =============================================
   TOAST NOTIFICATIONS
   ============================================= */
.toast-container {
    position: fixed;
    bottom: 24px;
    right: 24px;
    z-index: 9999;
    display: flex;
    flex-direction: column;
    gap: 10px;
    pointer-events: none;
}

.toast {
    display: flex;
    align-items: center;
    gap: 12px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 14px 18px;
    font-size: 0.88rem;
    font-weight: 500;
    box-shadow: var(--shadow-lg);
    pointer-events: auto;
    animation: toastIn 0.4s cubic-bezier(0.4, 0, 0.2, 1);
    min-width: 280px;
    max-width: 380px;
}

.toast.toast-success { border-left: 3px solid var(--green-500); }
.toast.toast-error   { border-left: 3px solid var(--red-500); }
.toast.toast-info    { border-left: 3px solid var(--blue-500); }

@keyframes toastIn {
    from { transform: translateX(20px); opacity: 0; }
    to   { transform: translateX(0);    opacity: 1; }
}

@keyframes toastOut {
    from { transform: translateX(0);   opacity: 1; }
    to   { transform: translateX(20px); opacity: 0; }
}

/* =============================================
   FOOTER
   ============================================= */
.site-footer {
    background: var(--bg-secondary);
    border-top: 1px solid var(--border);
    padding: 48px 0 24px;
    margin-top: auto;
}

.footer-grid {
    display: grid;
    grid-template-columns: 1.5fr 1fr 1fr;
    gap: 40px;
    margin-bottom: 36px;
}

.footer-brand {}
.footer-brand-name {
    font-size: 1.25rem;
    font-weight: 600;
    margin-bottom: 10px;
}
.footer-brand-desc { font-size: 0.85rem; color: var(--text-muted); line-height: 1.7; }

.footer-col-title {
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.7px;
    margin-bottom: 14px;
}

.footer-links {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.footer-links a {
    font-size: 0.85rem;
    color: var(--text-muted);
    transition: var(--transition-fast);
}
.footer-links a:hover { color: var(--blue-400); }

.footer-bottom {
    border-top: 1px solid var(--border);
    padding-top: 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 0.8rem;
    color: var(--text-muted);
}

/* =============================================
   LOADING SKELETON
   ============================================= */
/* A flat fill that pulses, rather than the usual sweeping shimmer — the
   shimmer is a gradient, and there are no gradients in this design. */
.skeleton {
    background: var(--bg-secondary);
    animation: skeleton-pulse 1.4s ease-in-out infinite;
    border-radius: var(--radius-xs);
}

@keyframes skeleton-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.55; }
}

/* =============================================
   RESPONSIVE
   ============================================= */
@media (max-width: 1100px) {
    .shop-layout { grid-template-columns: 1fr; }
    .filter-sidebar { position: static; }
    .related-grid { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 900px) {
    .product-detail-grid { grid-template-columns: 1fr; }
    .cart-page-layout { grid-template-columns: 1fr; }
    .cart-summary-card { position: static; }
    .footer-grid { grid-template-columns: 1fr 1fr; }
    .related-grid { grid-template-columns: repeat(2, 1fr); }
    .hero-stats { gap: 24px; }
}

@media (max-width: 640px) {
    .container { padding: 0 16px; }
    .navbar-search { display: none; }
    .hero { padding: 48px 0 36px; }
    .hero-search { flex-direction: column; }
    .footer-grid { grid-template-columns: 1fr; }
    .grid-products { grid-template-columns: repeat(2, 1fr); gap: 14px; }
    .cart-sidebar { width: 100%; }
    .related-grid { grid-template-columns: repeat(2, 1fr); }
    .hero-stats { flex-wrap: wrap; gap: 20px; }
}

@media (max-width: 400px) {
    .grid-products { grid-template-columns: 1fr; }
}

/* =============================================
   THEME TOGGLE
   Both icons are in the DOM; CSS picks which one shows. This avoids having
   to re-run lucide.createIcons() (which rebuilds the <svg>) on every click.
   The icon shown is the theme you will switch TO, so light (the default)
   shows the moon.
   ============================================= */
.theme-toggle .theme-icon-sun { display: none; }
:root[data-theme="dark"] .theme-toggle .theme-icon-sun  { display: block; }
:root[data-theme="dark"] .theme-toggle .theme-icon-moon { display: none; }

.theme-toggle:hover { color: var(--blue-500); }

/* Cross-fade on theme change instead of hard-cutting. Colour properties only:
   animating `all` here would also animate every transform/layout change that
   happens to coincide with the switch. */
@media (prefers-reduced-motion: no-preference) {
    body,
    .navbar,
    .product-card,
    .filter-sidebar,
    .table-card,
    .admin-sidebar,
    .admin-topbar {
        transition: background-color .15s ease, border-color .15s ease, color .15s ease;
    }
}

/* =============================================
   FLAT-DESIGN OVERRIDES

   These undo decorative treatments baked into rules further up the file.
   They live at the end so the originals stay readable as-is rather than
   being surgically rewritten in a dozen places.
   ============================================= */

/* The sheen overlay that used to sit on cards was a gradient. */
.product-card,
.filter-sidebar,
.stat-card { background-image: none; }

/* Cards separate by border alone — no drop shadow, no hover lift. A grid
   of parts should sit still while you scan it. */
.product-card {
    box-shadow: none;
    border: 1px solid var(--border-card);
}

.product-card:hover {
    box-shadow: none;
    transform: none;
    border-color: var(--border-blue);
}

/* Buttons: no glow, no lift. */
.btn-primary:hover,
.btn-amber:hover,
.btn-whatsapp:hover {
    box-shadow: none;
    transform: none;
    filter: brightness(0.94);
}

/* Scrollbar: neutral, not a blue accent stripe. */
::-webkit-scrollbar-thumb { background: #C6CDD5; border-radius: 2px; }
::-webkit-scrollbar-thumb:hover { background: #AEB7C2; }
:root[data-theme="dark"] ::-webkit-scrollbar-thumb { background: #333B47; }
:root[data-theme="dark"] ::-webkit-scrollbar-thumb:hover { background: #414B59; }

::selection { background: rgba(0, 119, 199, 0.16); color: var(--text-primary); }

/* The hero is a flat slate band in both themes; its text does not follow
   --text-primary because the band does not follow --bg-primary. */
.hero { background: var(--bg-hero); }
.hero-subtitle { color: var(--text-on-hero-muted); }
.hero-stat-value { color: var(--text-on-hero); }
.hero-stat-label { color: var(--text-on-hero-muted); }

.hero-badge {
    background: rgba(255, 255, 255, 0.10);
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: var(--radius-sm);
    color: var(--text-on-hero);
}

/* Uppercase micro-labels (category, filter group headings) carry the
   "spec sheet" tone that makes a parts catalogue feel authoritative. */
.filter-group-label,
.product-category {
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--text-muted);
}

/* The part number is the thing professionals actually search by, so it gets
   a monospace treatment rather than being styled like a decorative chip. */
.product-code-chip {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.72rem;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    border-radius: var(--radius-xs);
}

/* Brand chip on the card image. A dark pill read as a "sticker" over our
   light placeholders; a white chip with a hairline matches how trodo shows
   the manufacturer and stays legible over real photography too. */
.product-brand-badge {
    background: var(--bg-img-badge);
    color: var(--on-img-badge);
    border: 1px solid var(--border);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.04em;
}

.product-stock-badge {
    font-size: 0.66rem;
    font-weight: 600;
    border-radius: var(--radius-xs);
}

/* Denser grid: a parts catalogue is a scanning surface, not a lookbook. */
.grid-products {
    grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
    gap: 16px;
}

.related-grid { gap: 16px; }

/* The hero was 80/60px of padding around poster-sized type. Trimmed to a
   compact band so the catalogue starts above the fold. */
.hero { padding: 48px 0 44px; }
.hero-stats { gap: 32px; }
.hero-stat-value { font-size: 1.5rem; font-weight: 600; }

/* Category + part-number row on a product card. Was inline flex-wrap:wrap,
   which let a long code ("13.0470-7217.2") drop onto its own line and push
   the title down — cards in the same row then ended up different heights.
   Now the code never wraps and the category truncates instead, because the
   part number is the field customers actually match on. */
.product-meta-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    min-width: 0;
}

.product-meta-row .product-category {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.product-meta-row .product-code-chip { flex-shrink: 0; }

/* Two-line clamp so price/button rows line up across a grid row regardless
   of how long the product name is. */
.product-name {
    margin-top: 6px;
    font-size: 0.9rem;
    font-weight: 500;
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: 2.52em;
}

/* Footer pinned to the bottom of the card so prices align row to row. */
.product-card-body { flex: 1; }

/* =============================================
   INSTANT SEARCH PANEL (SearchSuggest — assets/js/main.js)

   Lives on <body> with position:fixed rather than inside .navbar-search: the
   navbar is a flex row that clips, and an absolutely positioned child there
   gets cut off the same way admin's .table-card amputated the searchable
   select. JS keeps left/top/width pinned to the input.
   ============================================= */
.sg-panel {
    position: fixed;
    z-index: 300;
    max-height: min(70vh, 520px);
    overflow-y: auto;
    background: var(--bg-card);
    border: 1px solid var(--border-blue);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    padding: 4px;
}

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

.sg-group-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 7px 11px 5px;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--text-muted);
}

.sg-clear {
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--blue-500);
    cursor: pointer;
}

.sg-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 11px;
    border-radius: var(--radius-xs);
    font-size: 0.85rem;
    color: var(--text-secondary);
    cursor: pointer;
}

/* Keyboard-active and pointer-hover share one look — there is only ever one
   "next Enter target", the same rule the searchable select follows. */
.sg-item.is-active { background: var(--bg-secondary); color: var(--text-primary); }

.sg-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The matched run. A tinted chip rather than a colour change: on a part number
   the eye needs to find the position, not read a different colour. */
.sg-panel mark {
    background: rgba(0, 119, 199, 0.16);
    color: inherit;
    border-radius: 2px;
    padding: 0 1px;
}

.sg-code {
    flex-shrink: 0;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.73rem;
    color: var(--text-muted);
}

.sg-price {
    flex-shrink: 0;
    font-weight: 700;
    font-size: 0.82rem;
    color: var(--price-color);
}

.sg-meta { flex-shrink: 0; font-size: 0.75rem; color: var(--text-muted); }

.sg-ico { flex-shrink: 0; color: var(--text-muted); }

.sg-item-all {
    justify-content: center;
    margin-top: 2px;
    border-top: 1px solid var(--border);
    border-radius: 0 0 var(--radius-xs) var(--radius-xs);
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--blue-500);
}

.sg-note {
    padding: 9px 11px;
    font-size: 0.78rem;
    color: var(--text-muted);
    background: var(--bg-secondary);
    border-radius: var(--radius-xs);
    margin-bottom: 4px;
}

/* =============================================
   ACTIVE FILTER CHIPS (renderFilterChips — includes/functions.php)
   ============================================= */
.filter-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 7px;
    margin-bottom: 14px;
}

.filter-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    max-width: 100%;
    padding: 5px 9px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-size: 0.78rem;
    color: var(--text-secondary);
    text-decoration: none;
    transition: var(--transition-fast);
}

.filter-chip:hover {
    border-color: var(--red-400);
    color: var(--text-primary);
}

.filter-chip-label { color: var(--text-muted); flex-shrink: 0; }

.filter-chip-value {
    font-weight: 600;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.filter-chip-x {
    flex-shrink: 0;
    font-size: 0.95rem;
    line-height: 1;
    color: var(--text-muted);
}

.filter-chip:hover .filter-chip-x { color: var(--red-400); }

.filter-chip-clear {
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--blue-500);
    text-decoration: none;
}

.filter-chip-clear:hover { text-decoration: underline; }

/* =============================================
   LOAD MORE (renderLoadMore — includes/functions.php)
   ============================================= */
.load-more-wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    padding: 28px 0 8px;
}

.load-more-status { font-size: 0.8rem; color: var(--text-muted); }

.load-more-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-width: 200px;
    justify-content: center;
    padding: 11px 22px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    font-family: inherit;
    font-size: 0.86rem;
    font-weight: 600;
    color: var(--text-primary);
    cursor: pointer;
    transition: var(--transition-fast);
}

.load-more-btn:hover:not(:disabled) { border-color: var(--blue-500); color: var(--blue-500); }
.load-more-btn:disabled { opacity: 0.7; cursor: default; }

.load-more-spinner { display: none; }

.load-more-btn.is-loading .load-more-label::after { content: '…'; }

.load-more-btn.is-loading .load-more-spinner {
    display: block;
    width: 13px;
    height: 13px;
    border: 2px solid var(--border);
    border-top-color: var(--blue-500);
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
}

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

.load-more-end { font-size: 0.8rem; color: var(--text-muted); }

/* =============================================
   LAZY IMAGES (LazyImages — assets/js/main.js)

   The skeleton lives on the WRAPPER, not the <img>, so it is covered as the
   image fades in rather than disappearing a frame early. width/height on every
   product <img> reserves the box, which is what stops the grid from jumping
   as images arrive.
   ============================================= */
.product-card-image,
.cart-page-item-img,
.product-detail-image {
    position: relative;
    background: var(--bg-img-placeholder);
}

.product-card-image::after,
.cart-page-item-img::after {
    content: '';
    position: absolute;
    inset: 0;
    /* A pulsing SOLID tint, not a sweeping gradient: the no-gradient rule in
       the token block applies to loading states too, and a flat pulse reads as
       "loading" just as well without the promo-page shimmer. */
    background: var(--bg-img-placeholder);
    animation: skeletonPulse 1.4s ease-in-out infinite;
    opacity: 1;
    transition: opacity 0.25s ease;
    pointer-events: none;
}

/* :has() so the skeleton retires when THIS card's image lands, without a
   per-card class. Browsers without :has() simply keep a static placeholder
   tint behind an already-opaque image — invisible either way. */
.product-card-image:has(img.is-loaded)::after,
.cart-page-item-img:has(img.is-loaded)::after { opacity: 0; }

@keyframes skeletonPulse {
    0%, 100% { background-color: var(--bg-img-placeholder); }
    50%      { background-color: var(--bg-card-hover); }
}

img.lazy-img {
    opacity: 0;
    transition: opacity 0.3s ease;
}

img.lazy-img.is-loaded { opacity: 1; }

/* The one exception to the fade: reduced-motion users get the image outright. */
@media (prefers-reduced-motion: reduce) {
    img.lazy-img { opacity: 1; transition: none; }
    .product-card-image::after,
    .cart-page-item-img::after { animation: none; }
}

/* =============================================
   PRODUCT IMAGE ZOOM + LIGHTBOX (ProductDetail — assets/js/main.js)
   ============================================= */
.product-detail-image {
    overflow: hidden;
    cursor: zoom-in;
}

.product-detail-image img {
    transition: transform 0.18s ease;
    will-change: transform;
}

/* No transition while tracking the cursor — easing a transform that updates on
   every mousemove makes the magnifier lag behind the pointer. */
.product-detail-image.is-zooming img { transition: none; }

.zoom-hint {
    position: absolute;
    right: 10px;
    bottom: 10px;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 9px;
    background: var(--bg-img-badge);
    color: var(--on-img-badge);
    border-radius: var(--radius-sm);
    font-size: 0.72rem;
    font-weight: 600;
    pointer-events: none;
    opacity: 0;
    transition: var(--transition-fast);
}

.product-detail-image:hover .zoom-hint { opacity: 1; }
.product-detail-image.is-zooming .zoom-hint { opacity: 0; }

/* =============================================
   PRODUCT GALLERY (product.php — ProductDetail in assets/js/main.js)

   The main frame keeps every rule it had as a single image; this only adds the
   controls layered over it and the thumbnail strip underneath. Arrows are
   visible at rest rather than on hover: on a phone there is no hover, and the
   swipe gesture alone leaves no sign that more pictures exist.
   ============================================= */
.product-gallery {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.gallery-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 50%;
    color: var(--text-primary);
    box-shadow: var(--shadow-md);
    cursor: pointer;
    opacity: 0.9;
    transition: var(--transition-fast);
}

.gallery-nav:hover { opacity: 1; border-color: var(--blue-400); color: var(--blue-400); }
.gallery-nav-prev { left: 10px; }
.gallery-nav-next { right: 10px; }

/* While the hover magnifier is tracking the cursor the arrows are both in the
   way and unclickable-feeling, since the image under them is moving. */
.product-detail-image.is-zooming .gallery-nav,
.product-detail-image.is-zooming .gallery-counter { opacity: 0; pointer-events: none; }

.gallery-counter {
    position: absolute;
    left: 10px;
    bottom: 10px;
    padding: 4px 8px;
    /* Over arbitrary product photography, not over the page surface — same
       reason --bg-img-badge does not flip with the theme. */
    background: var(--bg-img-badge);
    color: var(--on-img-badge);
    border-radius: var(--radius-sm);
    font-size: 0.72rem;
    font-weight: 600;
    pointer-events: none;
    transition: var(--transition-fast);
}

.gallery-thumbs {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding-bottom: 4px;
    scrollbar-width: thin;
}

.gallery-thumb {
    flex: 0 0 auto;
    display: block;
    width: 68px;
    height: 68px;
    padding: 5px;
    background: var(--bg-card);
    border: 1px solid var(--border-card);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: var(--transition-fast);
}

.gallery-thumb img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

.gallery-thumb:hover { border-color: var(--blue-400); }
.gallery-thumb.is-active { border-color: var(--blue-500); }

/* Lightbox navigation — only rendered when the gallery has more than one
   picture, so these never appear on a single-image product. */
.lightbox-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 50%;
    font-size: 1.5rem;
    line-height: 1;
    color: var(--text-primary);
    cursor: pointer;
}

.lightbox-prev { left: 16px; }
.lightbox-next { right: 16px; }

.lightbox-counter {
    position: absolute;
    bottom: 18px;
    left: 50%;
    transform: translateX(-50%);
    padding: 5px 12px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    font-size: 0.8rem;
    color: var(--text-secondary);
}

@media (max-width: 480px) {
    .gallery-nav { width: 32px; height: 32px; }
    .lightbox-nav { width: 38px; height: 38px; left: 8px; }
    .lightbox-next { left: auto; right: 8px; }
}

.lightbox {
    position: fixed;
    inset: 0;
    z-index: 500;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 32px;
    background: var(--bg-overlay);
    backdrop-filter: blur(2px);
    cursor: zoom-out;
}

.lightbox img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    background: var(--bg-card);
    border-radius: var(--radius-md);
    cursor: default;
}

.lightbox-close {
    position: absolute;
    top: 16px;
    right: 20px;
    width: 38px;
    height: 38px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    font-size: 1.4rem;
    line-height: 1;
    color: var(--text-primary);
    cursor: pointer;
}

/* =============================================
   STICKY BUY BAR (product.php)
   ============================================= */
.buy-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 250;
    background: var(--bg-nav);
    border-top: 1px solid var(--border);
    box-shadow: 0 -2px 12px rgba(33, 43, 54, 0.08);
    padding: 10px 0;
    animation: buyBarIn 0.2s ease;
}

.buy-bar[hidden] { display: none; }

@keyframes buyBarIn { from { transform: translateY(100%); } to { transform: none; } }

.buy-bar-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}

.buy-bar-info { display: flex; align-items: center; gap: 10px; min-width: 0; }

.buy-bar-info img {
    width: 40px;
    height: 40px;
    object-fit: cover;
    border-radius: var(--radius-sm);
    background: var(--bg-img-placeholder);
    flex-shrink: 0;
}

.buy-bar-text { min-width: 0; }

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

.buy-bar-code { font-size: 0.74rem; color: var(--text-muted); }

.buy-bar-actions { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }

.buy-bar-price {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--price-color);
    white-space: nowrap;
}

/* On a phone the bar is the primary control, so the product identity gives up
   its space to the price and the button. */
@media (max-width: 700px) {
    .buy-bar-info { display: none; }
    .buy-bar-inner { justify-content: space-between; }
    .buy-bar-actions { flex: 1; justify-content: space-between; gap: 8px; }
    .buy-bar-add span { display: none; }
}

/* =============================================
   TOAST ACTION (undo)
   ============================================= */
.toast-action {
    margin-left: 4px;
    padding: 3px 9px;
    background: none;
    border: 1px solid currentColor;
    border-radius: var(--radius-xs);
    font: inherit;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--blue-500);
    cursor: pointer;
    flex-shrink: 0;
}

.toast-action:hover { background: var(--bg-secondary); }

/* =============================================
   SHARED CART BANNER + CART PAGE TOOLBAR (cart.php)
   ============================================= */
.cart-page-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}

.cart-page-tools { display: flex; gap: 8px; flex-wrap: wrap; }

.share-banner {
    border: 1px solid var(--border-blue);
    border-radius: var(--radius-md);
    background: var(--bg-card);
    padding: 16px 18px;
}

.share-banner-head {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.9rem;
    color: var(--text-primary);
    margin-bottom: 10px;
}

.share-banner-head span { color: var(--text-muted); font-size: 0.8rem; }

.share-banner-list { list-style: none; margin: 0 0 14px; padding: 0; }

.share-banner-list li {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 0;
    border-bottom: 1px solid var(--border);
    font-size: 0.84rem;
    color: var(--text-secondary);
}

.share-banner-list li > span:first-child {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.share-banner-code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.74rem;
    color: var(--text-muted);
}

.share-banner-qty { font-weight: 700; color: var(--text-primary); }

/* =============================================
   PRINT — the cart as a handed-over quote

   Everything interactive disappears; what is left is the item list, the
   totals and a letterhead saying who produced it.
   ============================================= */
.print-head { display: none; }

@media print {
    .navbar,
    .footer,
    .cart-sidebar,
    .cart-overlay,
    .toast-container,
    .buy-bar,
    .filter-sidebar,
    .load-more-wrap,
    .breadcrumb,
    .share-banner,
    .no-print,
    .qty-control,
    .whatsapp-note,
    .btn,
    .form-group,
    .empty-state,
    [data-remove-cart] {
        display: none !important;
    }

    /* Force the light palette regardless of the visitor's theme: a dark page
       prints as a solid black rectangle and empties the toner tray. */
    :root,
    :root[data-theme="dark"] {
        --bg-primary: #FFFFFF;
        --bg-secondary: #FFFFFF;
        --bg-card: #FFFFFF;
        --bg-card-hover: #FFFFFF;
        --text-primary: #000000;
        --text-secondary: #222222;
        --text-muted: #555555;
        --price-color: #000000;
        --border: #BBBBBB;
        --border-card: #BBBBBB;
    }

    body { background: #FFFFFF; }

    .print-head {
        display: flex;
        align-items: flex-start;
        justify-content: space-between;
        gap: 24px;
        padding-bottom: 12px;
        margin-bottom: 20px;
        border-bottom: 2px solid #000;
    }

    .print-head-brand { font-size: 1.3rem; font-weight: 700; }
    .print-head-meta  { font-size: 0.8rem; text-align: right; line-height: 1.5; }

    /* Side-by-side columns waste a printed page — stack them. */
    .cart-page-layout { display: block !important; }
    .cart-summary-card { border: 0 !important; padding: 0 !important; margin-top: 16px; }

    .cart-page-item {
        break-inside: avoid;
        border-bottom: 1px solid #BBB !important;
    }

    .cart-page-item-img { display: none !important; }

    a[href]::after { content: ''; }  /* no URL footnotes after every link */
}
