@charset "UTF-8";
/* =========================================================================
   DealDraw Design System
   -------------------------------------------------------------------------
   A single source of truth for the platform's visual language.

   Structure
     01. Design tokens          07. Forms
     02. Reset & base           08. Tables (responsive)
     03. Accessibility          09. Cards & surfaces
     04. Typography             10. Feedback (alerts, badges)
     05. Layout primitives      11. Domain components
     06. Buttons                12. Utilities & preferences

   Accessibility contract
     - Every colour pairing used for text meets WCAG 2.1 AA (>= 4.5:1 for
       body copy, >= 3:1 for large text and UI boundaries).
     - Focus is never removed, only restyled, via :focus-visible.
     - Motion respects prefers-reduced-motion.
   ========================================================================= */

/* =========================================================================
   01. DESIGN TOKENS
   ========================================================================= */

:root {
    color-scheme: light;

    /* --- Primary ramp (indigo) -------------------------------------------
       Brand base is --primary-600. Verified against #ffffff:
         600 #4f46e5 -> 6.29:1  (AA body text on white bg, AA white-on-brand)
         700 #4338ca -> 8.03:1
       --------------------------------------------------------------------- */
    --primary-50:  #eef2ff;
    --primary-100: #e0e7ff;
    --primary-200: #c7d2fe;
    --primary-300: #a5b4fc;
    --primary-400: #818cf8;
    --primary-500: #6366f1;
    --primary-600: #4f46e5;
    --primary-700: #4338ca;
    --primary-800: #3730a3;
    --primary-900: #312e81;

    /* --- Neutral ramp (slate) --------------------------------------------
       Text-safe on white: 600 (7.58:1), 700 (10.3:1), 900 (17.85:1).
       400 (#94a3b8) is 2.56:1 and is therefore RESTRICTED to borders,
       dividers and decorative fills. Never use it for text.
       --------------------------------------------------------------------- */
    --neutral-0:   #ffffff;
    --neutral-50:  #f8fafc;
    --neutral-100: #f1f5f9;
    --neutral-200: #e2e8f0;
    --neutral-300: #cbd5e1;
    --neutral-400: #94a3b8;
    --neutral-500: #64748b;
    --neutral-600: #475569;
    --neutral-700: #334155;
    --neutral-800: #1e293b;
    --neutral-900: #0f172a;
    --neutral-950: #020617;

    /* --- Status ramps ----------------------------------------------------
       Each family exposes a -surface (tint), -border, -text (AA on surface
       AND on white) and -solid (AA for white text placed on it).
       --------------------------------------------------------------------- */
    --success-surface: #ecfdf5;
    --success-border:  #6ee7b7;
    --success-text:    #047857; /* 5.48:1 on white */
    --success-solid:   #047857;

    --warning-surface: #fffbeb;
    --warning-border:  #fcd34d;
    --warning-text:    #b45309; /* 5.02:1 on white */
    --warning-solid:   #b45309;

    --danger-surface:  #fef2f2;
    --danger-border:   #fca5a5;
    --danger-text:     #b91c1c; /* 6.47:1 on white */
    --danger-solid:    #b91c1c;

    --info-surface:    #eff6ff;
    --info-border:     #93c5fd;
    --info-text:       #1d4ed8; /* 6.98:1 on white */
    --info-solid:      #1d4ed8;

    /* --- Semantic aliases -------------------------------------------------
       Views and the admin theme picker write to --primary; everything else
       derives from these so a single override re-themes the platform.
       --------------------------------------------------------------------- */
    --primary:      var(--primary-600);
    --primary-dark: var(--primary-700);
    --primary-light:var(--primary-100);
    --secondary:    var(--neutral-500);
    --success:      var(--success-text);
    --danger:       var(--danger-text);
    --warning:      var(--warning-text);
    --info:         var(--info-text);

    --bg:           var(--neutral-50);
    --card-bg:      var(--neutral-0);
    --text:         var(--neutral-900);
    --text-muted:   var(--neutral-500);
    --text-subtle:  var(--neutral-600);
    --border:       var(--neutral-200);
    --border-strong:var(--neutral-300);

    /* --- Spacing scale (4px base) ---------------------------------------- */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.25rem;
    --space-6: 1.5rem;
    --space-8: 2rem;
    --space-10: 2.5rem;
    --space-12: 3rem;
    --space-16: 4rem;

    /* --- Radii ------------------------------------------------------------ */
    --radius-xs: 0.375rem;
    --radius-sm: 0.5rem;
    --radius-md: 0.75rem;
    --radius-lg: 1rem;
    --radius-xl: 1.5rem;
    --radius-pill: 999px;

    /* --- Elevation -------------------------------------------------------- */
    --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06),
                 0 1px 3px rgba(15, 23, 42, 0.05);
    --shadow:    0 4px 6px -2px rgba(15, 23, 42, 0.05),
                 0 10px 20px -6px rgba(15, 23, 42, 0.08);
    --shadow-md: 0 8px 12px -4px rgba(15, 23, 42, 0.06),
                 0 20px 32px -12px rgba(15, 23, 42, 0.12);
    --shadow-lg: 0 12px 20px -8px rgba(15, 23, 42, 0.08),
                 0 28px 48px -16px rgba(15, 23, 42, 0.16);

    /* --- Motion ----------------------------------------------------------- */
    --ease: cubic-bezier(0.4, 0, 0.2, 1);
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --duration-fast: 120ms;
    --duration: 200ms;
    --duration-slow: 320ms;
    --transition: all var(--duration) var(--ease);

    /* --- Focus ring -------------------------------------------------------
       Two-tone: a light halo separates the dark ring from dark backgrounds,
       so one token works on every surface in the app.
       --------------------------------------------------------------------- */
    --focus-ring: 0 0 0 2px var(--neutral-0), 0 0 0 4px var(--primary-600);
    --focus-ring-inverse: 0 0 0 2px var(--neutral-900), 0 0 0 4px var(--primary-300);

    /* --- Layering ---------------------------------------------------------- */
    --z-base: 1;
    --z-sticky: 100;
    --z-header: 200;
    --z-dropdown: 300;
    --z-overlay: 400;
    --z-modal: 500;
    --z-toast: 600;
    --z-skip: 700;

    /* --- Fluid type scale --------------------------------------------------
       clamp(min, preferred, max) keeps headings legible from 320px upward
       without per-breakpoint overrides.
       --------------------------------------------------------------------- */
    --text-xs:   0.75rem;
    --text-sm:   0.875rem;
    --text-base: 1rem;
    --text-lg:   1.125rem;
    --text-xl:   clamp(1.125rem, 1.05rem + 0.35vw, 1.3rem);
    --text-2xl:  clamp(1.35rem, 1.2rem + 0.7vw, 1.6rem);
    --text-3xl:  clamp(1.6rem, 1.35rem + 1.1vw, 2.05rem);
    --text-4xl:  clamp(1.9rem, 1.5rem + 1.8vw, 2.6rem);

    --font-sans: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont,
                 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    --font-display: 'Outfit', var(--font-sans);
    --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

    /* --- Layout ------------------------------------------------------------ */
    --container-max: 1440px;
    --container-pad: clamp(1rem, 0.5rem + 2vw, 2rem);
    --header-height: 4rem;
    --tap-target: 44px; /* WCAG 2.5.5 minimum interactive size */

    /* Touch devices get a larger target than the WCAG floor. 44px is the
       accessibility minimum; 48px is the comfortable size for thumbs and is
       applied under (hover: none) so pointer users keep the tighter scale. */
    --tap-target-touch: 48px;

    /* --- Breakpoint contract -----------------------------------------------
       The storefront is designed against three device bands. These are
       documented here as the single reference because CSS cannot use custom
       properties inside @media queries.

         mobile   360px - 767px    1 column, drawers, sticky action bars
         tablet   768px - 1199px   2-3 columns, sidebar becomes inline
         desktop  1200px +         3-4 columns, persistent sidebar

       360px is the narrowest supported width: below it layouts still reflow
       but are not separately tuned.
       --------------------------------------------------------------------- */
}

/* =========================================================================
   02. RESET & BASE
   ========================================================================= */

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

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    scroll-padding-top: calc(var(--header-height) + var(--space-4));
}

body {
    margin: 0;
    font-family: var(--font-sans);
    font-size: var(--text-base);
    line-height: 1.6;
    color: var(--text);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    min-height: 100vh;
}

img,
picture,
video,
canvas,
svg {
    display: block;
    max-width: 100%;
    height: auto;
}

input,
button,
textarea,
select { font: inherit; color: inherit; }

/* Prevent long words, URLs and reference codes from bursting their column. */
p, h1, h2, h3, h4, h5, h6, li, dd, dt, td, th { overflow-wrap: break-word; }

hr {
    border: 0;
    border-top: 1px solid var(--border);
    margin: var(--space-8) 0;
}

/* =========================================================================
   03. ACCESSIBILITY PRIMITIVES
   ========================================================================= */

/* Screen-reader-only text. Used to give icon-only controls an accessible
   name and to caption data tables without altering the visual design. */
.sr-only {
    position: absolute !important;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Same as .sr-only until focused, then revealed. For skip links. */
.sr-only-focusable:not(:focus):not(:focus-within) {
    position: absolute !important;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* WCAG 2.4.1 Bypass Blocks. First tab stop on every page. */
.skip-link {
    position: absolute;
    top: var(--space-2);
    left: var(--space-2);
    z-index: var(--z-skip);
    padding: var(--space-3) var(--space-5);
    background: var(--primary-700);
    color: var(--neutral-0);
    font-weight: 700;
    text-decoration: none;
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    transform: translateY(-150%);
    transition: transform var(--duration) var(--ease-out);
}
.skip-link:focus {
    transform: translateY(0);
    color: var(--neutral-0);
}

/* --- Global focus policy ------------------------------------------------
   WCAG 2.4.7. `outline: none` is only ever paired with a replacement ring.
   :focus-visible keeps the ring off mouse users but always on for keyboard.
   ------------------------------------------------------------------------ */
:focus-visible {
    outline: 2px solid transparent; /* preserved for Windows High Contrast */
    outline-offset: 2px;
    box-shadow: var(--focus-ring);
    border-radius: var(--radius-xs);
}

/* Browsers without :focus-visible fall back to a visible :focus ring. */
@supports not selector(:focus-visible) {
    :focus {
        outline: 3px solid var(--primary-600);
        outline-offset: 2px;
    }
}

/* Dark surfaces need the inverse halo to stay visible. */
.on-dark :focus-visible,
.navbar-drawer :focus-visible,
.admin-sidebar :focus-visible,
.auth-showcase :focus-visible { box-shadow: var(--focus-ring-inverse); }

/* Anything interactive must meet the 44px minimum target (WCAG 2.5.5). */
.btn,
.btn-icon,
.nav-link,
.pagination li a,
.pagination li span { min-height: var(--tap-target); }

/* =========================================================================
   04. TYPOGRAPHY
   ========================================================================= */

h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-display);
    color: var(--text);
    letter-spacing: -0.02em;
    line-height: 1.2;
    text-wrap: balance;
    margin: 0 0 var(--space-4);
}

h1 { font-size: var(--text-4xl); font-weight: 800; }
h2 { font-size: var(--text-3xl); font-weight: 700; margin-top: var(--space-8); }
h3 { font-size: var(--text-2xl); font-weight: 700; margin-top: var(--space-6); }
h4 { font-size: var(--text-xl); font-weight: 700; }
h5 { font-size: var(--text-lg); font-weight: 700; }
h6 { font-size: var(--text-base); font-weight: 700; }

/* A heading that opens a section should not inherit a stacking top margin. */
h1:first-child, h2:first-child, h3:first-child { margin-top: 0; }

p {
    margin: 0 0 var(--space-4);
    color: var(--text-subtle);
    max-width: 72ch; /* readable measure */
}

small { font-size: var(--text-sm); }

a {
    color: var(--primary-700);
    text-decoration: none;
    font-weight: 500;
    transition: color var(--duration-fast) var(--ease);
}
a:hover { color: var(--primary-800); text-decoration: underline; }

/* Prose links inside body copy stay underlined for WCAG 1.4.1 — colour is
   never the only signal that text is a link. */
.prose a,
p > a:not(.btn):not(.nav-link):not(.footer-link) { text-decoration: underline; }

.eyebrow {
    display: inline-block;
    font-size: var(--text-xs);
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--primary-700);
    margin-bottom: var(--space-2);
}

.lead { font-size: var(--text-lg); color: var(--text-subtle); }

/* =========================================================================
   05. LAYOUT PRIMITIVES
   ========================================================================= */

.container {
    width: 100%;
    max-width: var(--container-max);
    margin-inline: auto;
    padding: var(--space-8) var(--container-pad);
}

/* Auto-responsive grid. `--min` sets the smallest acceptable column width;
   min() stops the track from overflowing narrow viewports, which is the
   failure mode of a bare minmax(320px, 1fr). */
.grid-auto {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(var(--min, 280px), 100%), 1fr));
    gap: var(--gap, var(--space-6));
}

.stack > * + * { margin-top: var(--flow, var(--space-4)); }

.cluster {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gap, var(--space-3));
    align-items: center;
}

.flex {
    display: flex;
    gap: var(--space-4);
    align-items: center;
    flex-wrap: wrap;
}

.flex-between {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-4);
}

/* Page header: title, supporting copy and actions on one consistent row. */
.page-header {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: flex-start;
    gap: var(--space-4);
    margin-bottom: var(--space-8);
    padding-bottom: var(--space-5);
    border-bottom: 1px solid var(--border);
}
.page-header__title { margin: 0; }
.page-header__description {
    margin: var(--space-2) 0 0;
    color: var(--text-muted);
    font-size: var(--text-sm);
}
.page-header__actions {
    display: flex;
    gap: var(--space-3);
    flex-wrap: wrap;
}

/* Breadcrumb trail (WCAG 2.4.8 Location). */
.breadcrumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    list-style: none;
    margin: 0 0 var(--space-4);
    padding: 0;
    font-size: var(--text-sm);
}
.breadcrumb li { display: flex; align-items: center; gap: var(--space-2); }
.breadcrumb li + li::before {
    content: '/';
    color: var(--neutral-400);
    font-weight: 600;
}
.breadcrumb [aria-current='page'] { color: var(--text-muted); font-weight: 600; }

/* =========================================================================
   06. BUTTONS
   ========================================================================= */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-5);
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    background: var(--primary-600);
    color: var(--neutral-0);
    font-family: var(--font-display);
    font-size: var(--text-sm);
    font-weight: 700;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color var(--duration) var(--ease),
                border-color var(--duration) var(--ease),
                box-shadow var(--duration) var(--ease),
                transform var(--duration-fast) var(--ease);
}
.btn:hover {
    background: var(--primary-700);
    color: var(--neutral-0);
    text-decoration: none;
    box-shadow: var(--shadow);
    transform: translateY(-1px);
}
.btn:active { transform: translateY(0); box-shadow: var(--shadow-sm); }

.btn[disabled],
.btn[aria-disabled='true'],
.btn.is-disabled {
    opacity: 0.55;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
    pointer-events: none;
}

.btn-secondary {
    background: var(--neutral-0);
    color: var(--neutral-800);
    border-color: var(--border-strong);
}
.btn-secondary:hover {
    background: var(--neutral-50);
    color: var(--neutral-900);
    border-color: var(--neutral-400);
}

.btn-ghost {
    background: transparent;
    color: var(--primary-700);
    border-color: transparent;
}
.btn-ghost:hover { background: var(--primary-50); color: var(--primary-800); }

.btn-success { background: var(--success-solid); }
.btn-success:hover { background: #036049; }

.btn-danger { background: var(--danger-solid); }
.btn-danger:hover { background: #991b1b; }

.btn-warning { background: var(--warning-solid); }
.btn-warning:hover { background: #92400e; }

.btn-sm {
    padding: var(--space-2) var(--space-4);
    font-size: var(--text-xs);
    min-height: 36px; /* compact controls inside table rows */
}
.btn-lg {
    padding: var(--space-4) var(--space-8);
    font-size: var(--text-base);
    border-radius: var(--radius-lg);
}
.btn-block { width: 100%; }

.btn-link {
    background: none;
    border: none;
    padding: 0;
    min-height: 0;
    color: var(--primary-700);
    font-weight: 700;
    text-decoration: underline;
    box-shadow: none;
}
.btn-link:hover {
    background: none;
    color: var(--primary-800);
    box-shadow: none;
    transform: none;
}

/* Icon-only control. MUST carry aria-label or a nested .sr-only label. */
.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--tap-target);
    height: var(--tap-target);
    flex: 0 0 auto;
    padding: 0;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--neutral-0);
    color: var(--neutral-700);
    cursor: pointer;
    transition: var(--transition);
}
.btn-icon:hover {
    background: var(--primary-50);
    border-color: var(--primary-600);
    color: var(--primary-700);
}
.btn-icon[aria-pressed='true'] {
    background: var(--danger-surface);
    border-color: var(--danger-border);
    color: var(--danger-text);
}

/* Icons scale with their button and never intercept pointer events. */
.icon {
    width: 1.25em;
    height: 1.25em;
    flex: 0 0 auto;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    pointer-events: none;
}
.icon-sm { width: 1em; height: 1em; }
.icon-lg { width: 1.75em; height: 1.75em; }
.icon-xl { width: 2.5em; height: 2.5em; }
.icon-solid { fill: currentColor; stroke: none; }

/* =========================================================================
   07. FORMS
   ========================================================================= */

.form-group { margin-bottom: var(--space-5); }

.form-group label,
.form-label {
    display: block;
    margin-bottom: var(--space-2);
    font-size: var(--text-sm);
    font-weight: 700;
    color: var(--neutral-800);
}

/* Required marker is announced by the input's `required` attribute; the
   asterisk is decorative only. */
.form-label .required { color: var(--danger-text); margin-left: 0.15em; }

.form-group input:not([type='checkbox']):not([type='radio']),
.form-group select,
.form-group textarea,
.form-control {
    display: block;
    width: 100%;
    min-height: var(--tap-target);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--neutral-0);
    color: var(--text);
    font-size: var(--text-base); /* >=16px stops iOS zoom-on-focus */
    font-family: inherit;
    transition: border-color var(--duration) var(--ease),
                box-shadow var(--duration) var(--ease);
}

.form-group input:hover:not(:disabled),
.form-group select:hover:not(:disabled),
.form-group textarea:hover:not(:disabled) { border-color: var(--neutral-400); }

/* Replaces the removed outline — never leaves the field without an indicator. */
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus,
.form-control:focus {
    outline: 2px solid transparent;
    outline-offset: 2px;
    border-color: var(--primary-600);
    box-shadow: 0 0 0 3px var(--primary-100);
}

.form-group input:disabled,
.form-group select:disabled,
.form-group textarea:disabled {
    background: var(--neutral-100);
    color: var(--text-muted);
    cursor: not-allowed;
}

.form-group textarea { min-height: 7rem; resize: vertical; }

.form-group select {
    appearance: none;
    padding-right: var(--space-10);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23475569' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 7.5 10 12.5 15 7.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--space-3) center;
    background-size: 1.15em;
}

/* Invalid state pairs colour with a border weight change and an icon in the
   message, so colour is never the sole indicator (WCAG 1.4.1). */
.form-group input[aria-invalid='true'],
.form-group select[aria-invalid='true'],
.form-group textarea[aria-invalid='true'],
.form-group .is-invalid {
    border-color: var(--danger-text);
    border-width: 2px;
}

.form-error {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin-top: var(--space-2);
    color: var(--danger-text);
    font-size: var(--text-sm);
    font-weight: 600;
}

.form-hint {
    margin-top: var(--space-2);
    color: var(--text-muted);
    font-size: var(--text-sm);
}

/* Native controls inherit the brand colour and a real focus ring. */
input[type='checkbox'],
input[type='radio'] {
    width: 1.15rem;
    height: 1.15rem;
    accent-color: var(--primary-600);
    cursor: pointer;
    flex: 0 0 auto;
}

.form-check {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: var(--tap-target);
    cursor: pointer;
}
.form-check span { font-size: var(--text-sm); color: var(--neutral-700); }

/* Touch-first target sizing ---------------------------------------------
   Everything that can be tapped gets the comfortable 48px size on touch
   devices, where the 44px WCAG floor is only the minimum. (hover: none)
   also catches hybrids with a touchscreen in tablet mode, so the upgrade is
   not gated behind a rigid media query that real devices never hit.
   ------------------------------------------------------------------------ */
@media (hover: none) {
    .btn,
    .btn-icon,
    .btn-lg,
    .btn-sm,
    .nav__link,
    .nav__cta,
    .form-group input:not([type='checkbox']):not([type='radio']),
    .form-group select,
    .form-group textarea,
    .form-control,
    .form-check,
    .visibility-switch,
    .pagination a,
    .pagination button,
    .gallery-thumb,
    .spec-list__row {
        min-height: var(--tap-target-touch);
    }

    .btn-icon {
        width: var(--tap-target-touch);
        height: var(--tap-target-touch);
    }
}

/* Grouped choices. Always wrap radio sets in <fieldset> (WCAG 1.3.1). */
fieldset {
    margin: 0 0 var(--space-5);
    padding: 0;
    border: 0;
}
fieldset legend {
    padding: 0;
    margin-bottom: var(--space-3);
    font-size: var(--text-sm);
    font-weight: 700;
    color: var(--neutral-800);
}

/* Selectable card built on a real radio/checkbox so keyboard and screen
   reader semantics are preserved. */
.choice-card {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-4);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--neutral-0);
    cursor: pointer;
    transition: var(--transition);
}
.choice-card:hover { border-color: var(--primary-400); background: var(--primary-50); }
.choice-card:has(input:checked) {
    border-color: var(--primary-600);
    border-width: 2px;
    background: var(--primary-50);
    padding: calc(var(--space-4) - 1px);
}
.choice-card:has(input:focus-visible) { box-shadow: var(--focus-ring); }
/* Disabled options stay readable — the reason is conveyed by an adjacent
   badge, so the control is dimmed but never illegible. */
.choice-card:has(input:disabled) {
    background: var(--neutral-50);
    border-style: dashed;
    cursor: not-allowed;
}
.choice-card__body {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    flex: 1 1 auto;
    min-width: 0;
}
.choice-card__title {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-weight: 700;
    color: var(--neutral-900);
}
.choice-card__meta { font-size: var(--text-sm); color: var(--text-muted); }

.filter-form {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: flex-end;
    margin-bottom: var(--space-5);
}
.filter-form .form-group { margin-bottom: 0; flex: 1 1 12rem; }

/* =========================================================================
   08. TABLES
   -------------------------------------------------------------------------
   Two responsive strategies:
   a) .table-scroll  — wrapper scrolls horizontally, keyboard focusable and
                       labelled so the scroll region is reachable (WCAG 2.1.1).
   b) .table-stack   — below 768px each row becomes a card, using the
                       data-label attribute on <td> as the row heading.
   ========================================================================= */

.table-scroll {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-radius: var(--radius-md);
}
.table-scroll:focus-visible { box-shadow: var(--focus-ring); }

.table {
    width: 100%;
    border-collapse: collapse;
    margin: var(--space-4) 0;
    font-size: var(--text-sm);
}

.table caption {
    caption-side: top;
    padding-bottom: var(--space-3);
    text-align: left;
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text-muted);
}

.table th,
.table td {
    padding: var(--space-3) var(--space-4);
    text-align: left;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}

.table thead th {
    position: sticky;
    top: 0;
    z-index: var(--z-base);
    background: var(--neutral-50);
    color: var(--neutral-700);
    font-family: var(--font-display);
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    white-space: nowrap;
    border-bottom: 2px solid var(--border-strong);
}

.table tbody tr { transition: background-color var(--duration-fast) var(--ease); }
.table tbody tr:hover { background: var(--neutral-50); }
.table tbody tr:last-child td { border-bottom: 0; }

.table .numeric { text-align: right; font-variant-numeric: tabular-nums; }
.table .actions { white-space: nowrap; text-align: right; }
.table .actions .btn + .btn,
.table .actions form { display: inline-block; margin-left: var(--space-2); }

/* Row-level state. Paired with a text/badge cue in markup, never colour alone. */
tr.unread { background: var(--info-surface); }
tr.unread td { font-weight: 600; }
tr.read td { color: var(--text-muted); }

@media (max-width: 767px) {
    .table-stack thead {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
    }
    .table-stack,
    .table-stack tbody,
    .table-stack tr,
    .table-stack td { display: block; width: 100%; }

    .table-stack tr {
        margin-bottom: var(--space-4);
        border: 1px solid var(--border);
        border-radius: var(--radius-md);
        background: var(--card-bg);
        box-shadow: var(--shadow-sm);
        overflow: hidden;
    }

    .table-stack td {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: var(--space-4);
        padding: var(--space-3) var(--space-4);
        text-align: right;
        border-bottom: 1px solid var(--neutral-100);
    }
    .table-stack td:last-child { border-bottom: 0; }

    /* The column heading, repeated per cell for context. */
    .table-stack td::before {
        content: attr(data-label);
        flex: 0 0 40%;
        text-align: left;
        font-size: var(--text-xs);
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.05em;
        color: var(--text-muted);
    }
    .table-stack td.actions { justify-content: flex-end; }
}

/* =========================================================================
   09. CARDS & SURFACES
   ========================================================================= */

.card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    padding: var(--space-6);
    margin-bottom: var(--space-6);
}

/* Only cards that are themselves links should react to hover. */
.card-interactive { transition: var(--transition); }
.card-interactive:hover {
    box-shadow: var(--shadow-md);
    border-color: var(--primary-300);
    transform: translateY(-2px);
}

.card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-4);
    margin-bottom: var(--space-5);
    padding-bottom: var(--space-4);
    border-bottom: 1px solid var(--border);
}
.card-header h2,
.card-header h3 { margin: 0; }

.card-footer {
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    border-top: 1px solid var(--border);
}

/* Empty state. Every collection view should render one instead of a blank
   region, so users understand nothing is broken. */
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: var(--space-12) var(--space-6);
    background: var(--card-bg);
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius-lg);
}
.empty-state__icon {
    display: grid;
    place-items: center;
    width: 4rem;
    height: 4rem;
    margin-bottom: var(--space-4);
    border-radius: var(--radius-pill);
    background: var(--primary-50);
    color: var(--primary-700);
}
.empty-state__title { margin: 0 0 var(--space-2); font-size: var(--text-xl); }
.empty-state__body {
    margin: 0 0 var(--space-6);
    max-width: 46ch;
    color: var(--text-muted);
}

/* =========================================================================
   10. FEEDBACK
   ========================================================================= */

.alert {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    margin-bottom: var(--space-5);
    border: 1px solid var(--success-border);
    border-left-width: 4px; /* redundant non-colour cue */
    border-radius: var(--radius-md);
    background: var(--success-surface);
    color: var(--success-text);
    font-size: var(--text-sm);
    font-weight: 500;
}
.alert p:last-child,
.alert ul:last-child { margin-bottom: 0; }
.alert ul { padding-left: var(--space-5); margin: 0; }
.alert .icon { margin-top: 0.1em; }

.alert-error,
.alert-danger {
    background: var(--danger-surface);
    color: var(--danger-text);
    border-color: var(--danger-border);
}
.alert-warning {
    background: var(--warning-surface);
    color: var(--warning-text);
    border-color: var(--warning-border);
}
.alert-info {
    background: var(--info-surface);
    color: var(--info-text);
    border-color: var(--info-border);
}

.badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 0.2rem var(--space-3);
    border: 1px solid transparent;
    border-radius: var(--radius-pill);
    background: var(--neutral-100);
    color: var(--neutral-700);
    font-size: var(--text-xs);
    font-weight: 700;
    line-height: 1.5;
    white-space: nowrap;
}
.badge-success { background: var(--success-surface); color: var(--success-text); border-color: var(--success-border); }
.badge-danger  { background: var(--danger-surface);  color: var(--danger-text);  border-color: var(--danger-border); }
.badge-warning { background: var(--warning-surface); color: var(--warning-text); border-color: var(--warning-border); }
.badge-info    { background: var(--info-surface);    color: var(--info-text);    border-color: var(--info-border); }
.badge-secondary { background: var(--neutral-100); color: var(--neutral-700); border-color: var(--border); }
.badge.highlight { background: var(--primary-600); color: var(--neutral-0); border-color: var(--primary-700); }

/* Count indicator on nav icons. */
.badge-count {
    position: absolute;
    top: -0.35rem;
    right: -0.35rem;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 0.3rem;
    display: grid;
    place-items: center;
    border-radius: var(--radius-pill);
    background: var(--danger-solid);
    color: var(--neutral-0);
    font-size: 0.7rem;
    font-weight: 800;
    line-height: 1;
    border: 2px solid var(--neutral-0);
}

/* Status dot + label. The label carries the meaning; the dot reinforces it. */
.status {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-sm);
    font-weight: 600;
}
.status::before {
    content: '';
    width: 0.5rem;
    height: 0.5rem;
    border-radius: var(--radius-pill);
    background: currentColor;
    flex: 0 0 auto;
}
.status-success { color: var(--success-text); }
.status-warning { color: var(--warning-text); }
.status-danger  { color: var(--danger-text); }
.status-muted   { color: var(--text-muted); }

/* Progress bar. role="progressbar" + aria-valuenow belong on the container. */
.progress {
    height: 0.625rem;
    width: 100%;
    margin: var(--space-3) 0;
    border-radius: var(--radius-pill);
    background: var(--neutral-200);
    overflow: hidden;
}
.progress__fill {
    height: 100%;
    border-radius: var(--radius-pill);
    background: var(--primary-600);
    transition: width var(--duration-slow) var(--ease-out);
}
.ticket-progress-container {
    height: 0.625rem;
    width: 100%;
    margin: var(--space-3) 0;
    border-radius: var(--radius-pill);
    background: var(--neutral-200);
    overflow: hidden;
}
.ticket-progress-fill {
    height: 100%;
    border-radius: var(--radius-pill);
    background: var(--primary-600);
    transition: width var(--duration-slow) var(--ease-out);
}

/* =========================================================================
   11. DOMAIN COMPONENTS
   ========================================================================= */

/* --- 11.1 Header & navigation ------------------------------------------- */

.navbar {
    position: sticky;
    top: 0;
    z-index: var(--z-header);
    display: flex;
    align-items: center;
    gap: var(--space-4);
    min-height: var(--header-height);
    padding: var(--space-3) var(--container-pad);
    background: rgba(255, 255, 255, 0.9);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--border);
}
@supports not (backdrop-filter: blur(12px)) {
    .navbar { background: var(--neutral-0); }
}

.navbar-brand {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    flex: 0 0 auto;
    font-family: var(--font-display);
    font-size: var(--text-xl);
    font-weight: 800;
    color: var(--primary-700);
    text-decoration: none;
    white-space: nowrap;
}
.navbar-brand:hover { text-decoration: none; color: var(--primary-800); }
.navbar-brand img { max-height: 2rem; width: auto; }

.navbar-nav {
    display: flex;
    align-items: center;
    gap: var(--space-1);
}
.navbar-nav--primary { flex: 0 1 auto; }
.navbar-nav--utility { flex: 0 0 auto; margin-left: auto; }

.nav-link {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-md);
    color: var(--neutral-700);
    font-size: var(--text-sm);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color var(--duration-fast) var(--ease),
                color var(--duration-fast) var(--ease);
}
.nav-link:hover {
    background: var(--neutral-100);
    color: var(--primary-700);
    text-decoration: none;
}
/* Active state uses weight + underline bar as well as colour. */
.nav-link.active,
.nav-link[aria-current='page'] {
    color: var(--primary-700);
    background: var(--primary-50);
    font-weight: 700;
}
.nav-link.active::after,
.nav-link[aria-current='page']::after {
    content: '';
    position: absolute;
    left: var(--space-3);
    right: var(--space-3);
    bottom: 0.25rem;
    height: 2px;
    border-radius: var(--radius-pill);
    background: var(--primary-600);
}

.header-search {
    display: flex;
    align-items: center;
    flex: 1 1 12rem;
    min-width: 0;
    max-width: 24rem;
    padding-left: var(--space-4);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-pill);
    background: var(--neutral-100);
    transition: border-color var(--duration) var(--ease),
                box-shadow var(--duration) var(--ease),
                background-color var(--duration) var(--ease);
}
.header-search:focus-within {
    background: var(--neutral-0);
    border-color: var(--primary-600);
    box-shadow: 0 0 0 3px var(--primary-100);
}
.header-search input {
    flex: 1 1 auto;
    min-width: 0;
    padding: var(--space-2) 0;
    border: 0;
    background: transparent;
    font-size: var(--text-sm);
}
.header-search input:focus { outline: none; box-shadow: none; }
.header-search button {
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    margin: 0.2rem;
    flex: 0 0 auto;
    border: 0;
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--neutral-600);
    cursor: pointer;
}
.header-search button:hover { background: var(--primary-50); color: var(--primary-700); }

/* Hamburger — hidden on desktop, shown at the nav breakpoint. */
.navbar-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: var(--tap-target);
    height: var(--tap-target);
    margin-left: auto;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--neutral-0);
    color: var(--neutral-800);
    cursor: pointer;
}

/* --- 11.2 Dropdown menu -------------------------------------------------
   Driven by JS toggling [hidden] + aria-expanded, not by :hover, so it is
   operable by keyboard and touch (WCAG 2.1.1).
   ------------------------------------------------------------------------ */

.user-menu-container { position: relative; flex: 0 0 auto; }

.user-menu-trigger {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: var(--tap-target);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-pill);
    background: var(--neutral-0);
    color: var(--neutral-800);
    font-size: var(--text-sm);
    font-weight: 700;
    cursor: pointer;
    transition: var(--transition);
}
.user-menu-trigger:hover { background: var(--primary-50); border-color: var(--primary-400); }
.user-menu-trigger[aria-expanded='true'] {
    background: var(--primary-50);
    border-color: var(--primary-600);
}
.user-menu-trigger__name {
    max-width: 8rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.user-menu-trigger__chevron { transition: transform var(--duration) var(--ease); }
.user-menu-trigger[aria-expanded='true'] .user-menu-trigger__chevron { transform: rotate(180deg); }

.user-dropdown {
    position: absolute;
    right: 0;
    top: calc(100% + var(--space-2));
    z-index: var(--z-dropdown);
    width: min(18rem, calc(100vw - 2rem));
    padding: var(--space-2) 0;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--neutral-0);
    box-shadow: var(--shadow-lg);
}
.user-dropdown[hidden] { display: none; }

.user-dropdown__heading {
    padding: var(--space-2) var(--space-4);
    font-size: var(--text-xs);
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.user-dropdown-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    min-height: 2.75rem;
    padding: var(--space-2) var(--space-4);
    border: 0;
    background: none;
    color: var(--neutral-700);
    font-family: inherit;
    font-size: var(--text-sm);
    font-weight: 600;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}
.user-dropdown-item:hover {
    background: var(--primary-50);
    color: var(--primary-800);
    text-decoration: none;
}
.user-dropdown-item .icon { color: var(--text-muted); }
.user-dropdown-item:hover .icon { color: var(--primary-700); }
.user-dropdown-item__meta { margin-left: auto; }
.user-dropdown-item.text-danger { color: var(--danger-text); }
.user-dropdown-item.text-danger:hover { background: var(--danger-surface); color: var(--danger-text); }
.user-dropdown-item.text-danger .icon { color: var(--danger-text); }

.user-dropdown-divider {
    height: 1px;
    margin: var(--space-2) 0;
    background: var(--border);
}

/* --- 11.3 Mobile navigation drawer -------------------------------------- */

.navbar-drawer { display: none; }

@media (max-width: 991px) {
    .navbar { flex-wrap: wrap; gap: var(--space-3); }
    .navbar-toggle { display: inline-flex; }

    /* Primary links and utility icons collapse into the drawer. */
    .navbar > .navbar-nav--primary { display: none; }

    .header-search {
        order: 3;
        flex-basis: 100%;
        max-width: 100%;
    }

    .navbar-drawer {
        display: block;
        order: 4;
        flex-basis: 100%;
        padding-top: var(--space-3);
        margin-top: var(--space-1);
        border-top: 1px solid var(--border);
    }
    .navbar-drawer[hidden] { display: none; }
    .navbar-drawer .navbar-nav {
        flex-direction: column;
        align-items: stretch;
        gap: var(--space-1);
    }
    .navbar-drawer .nav-link {
        justify-content: flex-start;
        padding: var(--space-3) var(--space-4);
    }
    .navbar-drawer .nav-link.active::after,
    .navbar-drawer .nav-link[aria-current='page']::after { display: none; }
}

@media (min-width: 992px) {
    .navbar-drawer { display: none !important; }
}

/* --- 11.4 Product cards -------------------------------------------------- */

.products-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
    gap: var(--space-6);
    margin: var(--space-8) 0;
}

.product-card {
    position: relative;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    transition: box-shadow var(--duration) var(--ease),
                border-color var(--duration) var(--ease),
                transform var(--duration) var(--ease);
}
.product-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-md);
    border-color: var(--primary-300);
}
/* Keyboard users get the same affordance when focus lands inside the card. */
.product-card:focus-within {
    border-color: var(--primary-600);
    box-shadow: var(--shadow-md);
}

.product-image-container {
    position: relative;
    display: grid;
    place-items: center;
    aspect-ratio: 4 / 3;
    background: var(--neutral-100);
    color: var(--neutral-500);
    border-bottom: 1px solid var(--border);
    overflow: hidden;
}
.product-image-container img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.product-badge-stock {
    position: absolute;
    top: var(--space-3);
    right: var(--space-3);
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 0.25rem var(--space-3);
    border: 1px solid transparent;
    border-radius: var(--radius-pill);
    background: var(--neutral-0);
    font-size: var(--text-xs);
    font-weight: 700;
    box-shadow: var(--shadow-sm);
}

.product-content {
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: var(--space-5);
}

.product-title {
    margin: 0 0 var(--space-2);
    font-size: var(--text-lg);
    font-weight: 700;
    line-height: 1.35;
}
.product-title a { color: var(--text); text-decoration: none; }
.product-title a:hover { color: var(--primary-700); text-decoration: underline; }
/* Stretched link: the whole card is clickable, but only one real link is in
   the tab order — action buttons sit above it via z-index. */
.product-title a::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
}

.product-price {
    margin: 0 0 var(--space-3);
    font-family: var(--font-display);
    font-size: var(--text-xl);
    font-weight: 800;
    color: var(--text);
}
.product-price del {
    margin-left: var(--space-2);
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--text-muted);
}

.product-desc {
    flex-grow: 1;
    margin: 0 0 var(--space-5);
    font-size: var(--text-sm);
    color: var(--text-muted);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.product-actions-toolbar {
    position: relative;
    z-index: 2; /* above the stretched link */
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-top: auto;
    padding-top: var(--space-4);
    border-top: 1px solid var(--border);
}
.product-actions-toolbar > form { display: contents; }
.product-actions-toolbar .btn { flex: 1 1 auto; }

.variation-pill {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: var(--tap-target);
    padding: var(--space-2) var(--space-4);
    margin: 0 var(--space-2) var(--space-2) 0;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-pill);
    background: var(--neutral-0);
    color: var(--neutral-700);
    font-size: var(--text-sm);
    font-weight: 600;
    cursor: pointer;
    transition: var(--transition);
}
.variation-pill:hover { border-color: var(--primary-500); color: var(--primary-700); }
.variation-pill.active,
.variation-pill[aria-pressed='true'] {
    background: var(--primary-600);
    border-color: var(--primary-700);
    color: var(--neutral-0);
    font-weight: 700;
}

/* --- 11.5 Event cards ---------------------------------------------------- */

.event-card {
    position: relative;
    display: flex;
    flex-direction: column;
    margin-bottom: 0;
}

/* Expands a link to cover its nearest positioned ancestor, making a whole
   card clickable while keeping exactly one element in the tab order. Sits
   below z-index 2 so nested controls stay independently clickable. */
.stretched-link::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    border-radius: inherit;
}

/* --- 11.6 Stat cards ----------------------------------------------------- */

.stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
    gap: var(--space-5);
    margin: var(--space-6) 0;
}

.stat-card {
    position: relative;
    padding: var(--space-5);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--card-bg);
    box-shadow: var(--shadow-sm);
    transition: var(--transition);
}
a .stat-card:hover,
.stat-card.card-interactive:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
    border-color: var(--primary-300);
}
.stat-card h3 {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    margin: 0 0 var(--space-3);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.stat-value {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--text-3xl);
    font-weight: 800;
    line-height: 1.1;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}
.stat-card__meta {
    margin: var(--space-2) 0 0;
    font-size: var(--text-sm);
    color: var(--text-muted);
}
.stat-card.highlight {
    background: var(--primary-700);
    border-color: var(--primary-800);
    color: var(--neutral-0);
}
.stat-card.highlight h3 { color: var(--primary-200); }
.stat-card.highlight .stat-value { color: var(--neutral-0); }
.stat-card.highlight .stat-card__meta { color: var(--primary-100); }

/* --- 11.11 Product detail ------------------------------------------------ */

.product-detail {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr));
    gap: var(--space-8);
    align-items: start;
}

.product-gallery__hero {
    position: relative;
    display: grid;
    place-items: center;
    aspect-ratio: 1 / 1;
    max-height: 26rem;
    margin: 0;
    padding: var(--space-4);
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--neutral-0);
    color: var(--neutral-500);
    box-shadow: var(--shadow-sm);
}
.product-gallery__hero img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}
.product-gallery__badge {
    position: absolute;
    top: var(--space-4);
    right: var(--space-4);
}

.product-gallery__thumbs {
    display: flex;
    gap: var(--space-3);
    overflow-x: auto;
    padding-bottom: var(--space-2);
    scrollbar-width: thin;
}

/* Thumbnails are real buttons, so they inherit focus-visible automatically.
   aria-pressed drives the selected ring — no JS style writing required. */
.gallery-thumb {
    display: grid;
    place-items: center;
    width: 4.75rem;
    height: 4.75rem;
    flex: 0 0 auto;
    padding: 0;
    overflow: hidden;
    border: 2px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--neutral-0);
    cursor: pointer;
    transition: border-color var(--duration) var(--ease);
}
.gallery-thumb:hover { border-color: var(--primary-400); }
.gallery-thumb[aria-pressed='true'] { border-color: var(--primary-600); }
.gallery-thumb img { width: 100%; height: 100%; object-fit: cover; }

.product-detail__price {
    margin: 0 0 var(--space-1);
    font-family: var(--font-display);
    font-size: var(--text-4xl);
    font-weight: 800;
    line-height: 1.1;
    color: var(--primary-700);
    font-variant-numeric: tabular-nums;
}

/* Variation pill wrapping a visually hidden radio. :has() styles the label
   from the input's checked state, so selection needs no JavaScript. */
.variation-pill:has(input:checked) {
    background: var(--primary-600);
    border-color: var(--primary-700);
    color: var(--neutral-0);
    font-weight: 700;
}
.variation-pill:has(input:focus-visible) { box-shadow: var(--focus-ring); }

/* Sold-out options stay selectable so their price stays readable, but read as
   unavailable. The label already carries the words "Sold out", so colour is a
   reinforcement here rather than the only signal (WCAG 1.4.1). */
.variation-pill.is-soldout {
    color: var(--text-muted);
    border-style: dashed;
}
.variation-pill.is-soldout:has(input:checked) {
    background: var(--neutral-400);
    border-color: var(--neutral-400);
    border-style: solid;
    color: var(--neutral-0);
}

/* --- 11.12 Page patterns -------------------------------------------------
   Replacements for the recurring inline-styled blocks found across the
   storefront and admin views.
   ------------------------------------------------------------------------ */

/* Hero banner. Gradient is decorative; text sits on a solid dark base so
   contrast never depends on the gradient stop that happens to be behind it. */
.hero {
    position: relative;
    overflow: hidden;
    padding: clamp(2.5rem, 1.5rem + 5vw, 5rem) clamp(1.5rem, 1rem + 3vw, 3.5rem);
    margin-bottom: var(--space-10);
    border-radius: var(--radius-xl);
    background:
        radial-gradient(circle at 85% 15%, rgba(255, 255, 255, 0.16), transparent 55%),
        linear-gradient(135deg, var(--primary-800), var(--primary-900));
    background-color: var(--primary-800);
    color: var(--neutral-0);
}
.hero h1 { color: var(--neutral-0); max-width: 20ch; }
.hero p { color: var(--primary-100); max-width: 56ch; }
.hero .eyebrow { color: var(--primary-200); }
.hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-top: var(--space-6);
}
/* Secondary button on the dark hero needs an inverted treatment. */
.hero .btn-secondary {
    background: rgba(255, 255, 255, 0.12);
    border-color: rgba(255, 255, 255, 0.4);
    color: var(--neutral-0);
}
.hero .btn-secondary:hover {
    background: rgba(255, 255, 255, 0.22);
    border-color: var(--neutral-0);
    color: var(--neutral-0);
}

/* Section heading with a trailing action, used above content groups. */
.section-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin: var(--space-10) 0 var(--space-5);
    padding-bottom: var(--space-3);
    border-bottom: 2px solid var(--border);
}
.section-header:first-child { margin-top: 0; }
.section-header h2,
.section-header h3 { margin: 0; display: flex; align-items: center; gap: var(--space-2); }

/* Horizontal filter/toolbar strip. */
.toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-4);
    margin-bottom: var(--space-6);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--neutral-50);
}
.toolbar__label {
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-right: var(--space-1);
}

/* Chip: a compact filter link. Selected state adds weight and a border so
   it is distinguishable without relying on colour (WCAG 1.4.1). */
.chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 2.25rem;
    padding: var(--space-2) var(--space-4);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-pill);
    background: var(--neutral-0);
    color: var(--neutral-700);
    font-size: var(--text-sm);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    transition: var(--transition);
}
.chip:hover {
    border-color: var(--primary-500);
    background: var(--primary-50);
    color: var(--primary-800);
    text-decoration: none;
}
.chip[aria-current='true'],
.chip.active {
    background: var(--primary-600);
    border-color: var(--primary-700);
    color: var(--neutral-0);
    font-weight: 700;
}
.chip[aria-current='true']:hover,
.chip.active:hover { background: var(--primary-700); color: var(--neutral-0); }

/* Two-column page: content beside a sticky summary rail. Collapses to a
   single column below 900px so neither column is squeezed. */
.layout-with-aside {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(280px, 360px);
    gap: var(--space-8);
    align-items: start;
}
@media (max-width: 900px) {
    .layout-with-aside { grid-template-columns: minmax(0, 1fr); }
    .summary-panel { position: static; }
}

.summary-panel {
    position: sticky;
    top: calc(var(--header-height) + var(--space-4));
    padding: var(--space-6);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--card-bg);
    box-shadow: var(--shadow-sm);
}

/* Key/value rows for totals, order details and receipts. */
.summary-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--space-4);
    padding: var(--space-2) 0;
    font-size: var(--text-sm);
}
.summary-row dt, .summary-row__label { color: var(--text-muted); }
.summary-row dd, .summary-row__value { margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; }
.summary-row--total {
    margin-top: var(--space-3);
    padding-top: var(--space-4);
    border-top: 1px solid var(--border);
    font-size: var(--text-lg);
}
.summary-row--total .summary-row__value,
.summary-row--total dd {
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-weight: 800;
}

/* Description list for record detail pages. <dl> is the correct semantic
   element for key/value data, replacing tables misused for layout. */
.detail-list {
    display: grid;
    grid-template-columns: minmax(8rem, 14rem) minmax(0, 1fr);
    gap: 0;
    margin: 0;
}
.detail-list dt,
.detail-list dd {
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--border);
    margin: 0;
}
.detail-list dt { font-weight: 700; color: var(--neutral-700); background: var(--neutral-50); }
.detail-list dd { font-variant-numeric: tabular-nums; }
@media (max-width: 640px) {
    .detail-list { grid-template-columns: minmax(0, 1fr); }
    .detail-list dt { border-bottom: 0; padding-bottom: var(--space-1); }
}

/* Media object: thumbnail beside its label, used in cart and order rows. */
.media {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-width: 0;
}
.media__figure {
    display: grid;
    place-items: center;
    width: 3.5rem;
    height: 3.5rem;
    flex: 0 0 auto;
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--neutral-100);
    color: var(--neutral-500);
}
.media__figure img { width: 100%; height: 100%; object-fit: cover; }
.media__body { min-width: 0; }
.media__title { font-weight: 700; color: var(--text); }
.media__meta { font-size: var(--text-sm); color: var(--text-muted); }

/* Avatar for user rows in the admin tables. */
.avatar {
    display: grid;
    place-items: center;
    width: 2.5rem;
    height: 2.5rem;
    flex: 0 0 auto;
    border-radius: var(--radius-pill);
    background: var(--primary-100);
    color: var(--primary-800);
    font-family: var(--font-display);
    font-weight: 800;
    text-transform: uppercase;
}
.avatar--admin { background: var(--primary-700); color: var(--neutral-0); }

/* Quantity stepper input inside cart rows. */
.qty-input {
    width: 5rem;
    text-align: center;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* Ticket stub, with the perforated notches drawn via pseudo-elements. */
.ticket-card {
    position: relative;
    padding: var(--space-6);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--card-bg);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}
.ticket-card::before,
.ticket-card::after {
    content: '';
    position: absolute;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: var(--radius-pill);
    background: var(--bg);
    border: 1px solid var(--border);
    top: 50%;
    transform: translateY(-50%);
}
.ticket-card::before { left: -0.85rem; }
.ticket-card::after { right: -0.85rem; }
.ticket-card--winner {
    border-color: var(--success-border);
    border-width: 2px;
    background: var(--success-surface);
}
.ticket-number {
    font-family: var(--font-mono);
    font-size: var(--text-xl);
    font-weight: 700;
    letter-spacing: 0.05em;
}

/* Gateway brand panel used by the mock checkout screens. */
.gateway-brand {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-5);
    margin-bottom: var(--space-6);
    border-radius: var(--radius-lg);
    color: var(--neutral-0);
}
.gateway-brand--jazzcash { background: #8a1538; }  /* white text = 9.7:1 */
.gateway-brand--easypaisa { background: #14532d; } /* white text = 9.4:1 */
.gateway-brand__mark {
    display: grid;
    place-items: center;
    width: 3rem;
    height: 3rem;
    flex: 0 0 auto;
    border-radius: var(--radius-md);
    background: rgba(255, 255, 255, 0.2);
}
.gateway-brand h2 { margin: 0; color: var(--neutral-0); font-size: var(--text-xl); }
.gateway-brand p { margin: 0; color: rgba(255, 255, 255, 0.85); font-size: var(--text-sm); }

/* Narrow single-purpose page (checkout, payment confirmation). */
.narrow-page { max-width: 42rem; margin-inline: auto; }

/* --- 11.12 Pagination ---------------------------------------------------- */

/*
 * Every control in the paginator is sized from the same box so the
 * "Previous" and "Next" buttons are not visually heavier than the page
 * number cells. Three rules do the work:
 *
 *   1. `box-sizing: border-box` so the 1px border does not push the rendered
 *      height past the tap target.
 *   2. An explicit `line-height: 1` so the vertical centre is determined by
 *      padding alone, not the inherited body leading.
 *   3. A shared `min-height: var(--tap-target)` (44px, WCAG 2.5.5) and
 *      `min-width: 2.75rem` so the prev/next buttons are no wider than the
 *      widest digit cell, even with their label.
 *
 * The previous/next links use `display: inline-flex; align-items: center;
 * gap: var(--space-1)` so the icon and the label stay on one baseline.
 */
.pagination {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
    list-style: none;
    padding: 0;
    margin: var(--space-8) 0 0;
    font-variant-numeric: tabular-nums;
}
.pagination > li > a,
.pagination > li > span {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
    min-width: 2.75rem;
    min-height: var(--tap-target);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--neutral-0);
    color: var(--neutral-700);
    font-family: inherit;
    font-size: var(--text-sm);
    font-weight: 600;
    line-height: 1;
    text-decoration: none;
    white-space: nowrap;
    transition: background var(--duration) var(--ease),
                border-color var(--duration) var(--ease),
                color var(--duration) var(--ease);
}
/* Single-page-number cells get the square 44px treatment so the row stays
   aligned even with only a digit in them. */
.pagination > .pagination-link > a,
.pagination > .pagination-current > span,
.pagination > .pagination-ellipsis > span {
    min-width: var(--tap-target);
    padding-inline: var(--space-2);
}

/* Hover/focus keep the button box stable — no translate or scale, just
   colour. The focus ring is its own outline so it never changes layout. */
.pagination > li > a:hover {
    background: var(--primary-50);
    border-color: var(--primary-500);
    color: var(--primary-800);
    text-decoration: none;
}
.pagination > li > a:focus-visible {
    outline: 2px solid var(--primary-600);
    outline-offset: 2px;
}

.pagination > .pagination-current > span {
    background: var(--primary-600);
    border-color: var(--primary-700);
    color: var(--neutral-0);
    cursor: default;
}
.pagination > .pagination-ellipsis > span {
    color: var(--neutral-400);
    background: var(--neutral-0);
    border-color: var(--border);
    cursor: default;
}

/* The Previous and Next cells are disabled (no link) when on the first or
   last page. Visually they look identical to a real button so the row
   never shifts when the user moves between pages. */
.pagination > .pagination-prev--disabled > span,
.pagination > .pagination-next--disabled > span {
    color: var(--neutral-400);
    background: var(--neutral-50);
    cursor: not-allowed;
}

/* Label spacing on prev/next — the icon and text share the same row but
   we add a touch of space between them so the chevron and the word don't
   collide visually. */
.pagination > .pagination-prev > a > .pagination-prev__label,
.pagination > .pagination-prev--disabled > span > .pagination-prev__label {
    margin-left: var(--space-1);
}
.pagination > .pagination-next > a > .pagination-next__label,
.pagination > .pagination-next--disabled > span > .pagination-next__label {
    margin-right: var(--space-1);
}

/* On the tightest viewports the row must wrap, not overflow. */
@media (max-width: 480px) {
    .pagination > li > a,
    .pagination > li > span { padding: var(--space-2); }
    .pagination > .pagination-prev > a > .pagination-prev__label,
    .pagination > .pagination-prev--disabled > span > .pagination-prev__label,
    .pagination > .pagination-next > a > .pagination-next__label,
    .pagination > .pagination-next--disabled > span > .pagination-next__label {
        /* The icon alone is enough at this width; the label repeats the
           icon's meaning for screen readers via aria-label, so dropping
           the visible text keeps every cell square. */
        position: absolute;
        width: 1px; height: 1px; padding: 0; margin: -1px;
        overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
    }
}

/* --- 11.7 Admin workspace ------------------------------------------------ */

.admin-workspace {
    display: grid;
    grid-template-columns: 264px minmax(0, 1fr);
    gap: var(--space-8);
    align-items: start;
}

.admin-sidebar {
    position: sticky;
    top: calc(var(--header-height) + var(--space-4));
    overflow: hidden;
    border: 1px solid var(--neutral-800);
    border-radius: var(--radius-lg);
    background: var(--neutral-900);
    color: var(--neutral-0);
    box-shadow: var(--shadow);
}
.admin-sidebar__header {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-5);
    background: var(--primary-800);
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
.admin-sidebar__title {
    display: block;
    font-family: var(--font-display);
    font-size: var(--text-base);
    font-weight: 800;
    color: var(--neutral-0);
    line-height: 1.2;
}
.admin-sidebar__subtitle {
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--primary-200);
}
.admin-sidebar__nav { display: flex; flex-direction: column; padding: var(--space-2) 0; }
.admin-sidebar__footer {
    padding: var(--space-4) var(--space-5);
    background: var(--neutral-950);
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.admin-nav-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: var(--tap-target);
    padding: var(--space-3) var(--space-5);
    /* #cbd5e1 on #0f172a = 12.1:1 */
    color: var(--neutral-300);
    font-size: var(--text-sm);
    font-weight: 600;
    text-decoration: none;
    border-left: 3px solid transparent;
    transition: background-color var(--duration-fast) var(--ease),
                color var(--duration-fast) var(--ease);
}
.admin-nav-item:hover {
    background: rgba(255, 255, 255, 0.07);
    color: var(--neutral-0);
    text-decoration: none;
}
.admin-nav-item.active,
.admin-nav-item[aria-current='page'] {
    background: var(--primary-700);
    border-left-color: var(--primary-300);
    color: var(--neutral-0);
    font-weight: 700;
}
.admin-nav-item__count {
    margin-left: auto;
    padding: 0.1rem var(--space-2);
    border-radius: var(--radius-pill);
    background: rgba(255, 255, 255, 0.14);
    color: var(--neutral-0);
    font-size: var(--text-xs);
    font-weight: 700;
}
.admin-nav-item.active .admin-nav-item__count { background: rgba(255, 255, 255, 0.25); }

.admin-sidebar__link {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    min-height: var(--tap-target);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-md);
    background: rgba(255, 255, 255, 0.08);
    color: var(--neutral-0);
    font-size: var(--text-sm);
    font-weight: 600;
    text-decoration: none;
}
.admin-sidebar__link:hover { background: rgba(255, 255, 255, 0.16); color: var(--neutral-0); text-decoration: none; }

.admin-sidebar__status {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: var(--space-3);
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--neutral-400);
}

/* Grid children default to min-width:auto, which lets a wide table stretch
   the column and push the sidebar off-screen. min-width:0 confines the
   content so .table-scroll can scroll internally instead. */
.admin-content-area { min-width: 0; }

/* Sidebar becomes a collapsible panel on tablet and below. */
@media (max-width: 991px) {
    .admin-workspace { grid-template-columns: minmax(0, 1fr); gap: var(--space-5); }
    .admin-sidebar { position: static; top: auto; }
    .admin-sidebar__nav { display: none; }
    .admin-sidebar__nav.is-open { display: flex; }
    .admin-sidebar__footer { display: none; }
    .admin-sidebar__nav.is-open ~ .admin-sidebar__footer { display: block; }
    .admin-sidebar__toggle { display: inline-flex !important; }
}

.admin-sidebar__toggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: var(--tap-target);
    height: var(--tap-target);
    margin-left: auto;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: var(--radius-md);
    background: rgba(255, 255, 255, 0.1);
    color: var(--neutral-0);
    cursor: pointer;
}

/* --- 11.8 Authentication ------------------------------------------------- */

.auth-wrapper {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 520px);
    min-height: 100vh;
    background: var(--neutral-900);
}

.auth-showcase {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: var(--space-10);
    padding: clamp(2rem, 1rem + 4vw, 4.5rem);
    background: var(--primary-900);
    color: var(--neutral-0);
    border-right: 1px solid rgba(255, 255, 255, 0.1);
}
.auth-showcase h1 { color: var(--neutral-0); }
/* #cbd5e1 on #312e81 = 8.6:1 */
.auth-showcase p { color: var(--neutral-300); }

.auth-showcase-feature {
    display: flex;
    align-items: flex-start;
    gap: var(--space-4);
    margin-bottom: var(--space-6);
}
.auth-showcase-feature h4 { margin: 0 0 var(--space-1); color: var(--neutral-0); }
.auth-showcase-feature p { margin: 0; font-size: var(--text-sm); }
.auth-showcase-icon {
    display: grid;
    place-items: center;
    width: 2.75rem;
    height: 2.75rem;
    flex: 0 0 auto;
    border-radius: var(--radius-md);
    background: rgba(255, 255, 255, 0.12);
    color: var(--neutral-0);
}

.auth-panel {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: clamp(2rem, 1rem + 4vw, 4rem);
    background: var(--neutral-0);
    overflow-y: auto;
}
.auth-panel__inner { width: 100%; max-width: 26rem; margin-inline: auto; }
.auth-panel-logo {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-8);
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-weight: 800;
    color: var(--primary-700);
    text-decoration: none;
}
.auth-panel h2 { margin: 0 0 var(--space-2); font-size: var(--text-3xl); }
.auth-panel .subtitle { margin: 0 0 var(--space-8); color: var(--text-muted); }

.auth-card {
    width: 100%;
    max-width: 27.5rem;
    padding: var(--space-8);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--neutral-0);
    box-shadow: var(--shadow-md);
}

.auth-actions {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-3);
}
.auth-checkbox {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-sm);
    color: var(--neutral-700);
    cursor: pointer;
}

.auth-divider {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    margin: var(--space-6) 0;
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.auth-divider::before,
.auth-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--border);
}

@media (max-width: 991px) {
    .auth-wrapper { grid-template-columns: minmax(0, 1fr); }
    .auth-showcase { display: none; }
}

/* --- 11.9 Footer --------------------------------------------------------- */

.site-footer {
    margin-top: var(--space-16);
    padding: var(--space-12) var(--container-pad) var(--space-6);
    background: var(--neutral-0);
    border-top: 1px solid var(--border);
}
.site-footer__inner {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
    gap: var(--space-10);
    max-width: var(--container-max);
    margin-inline: auto;
    margin-bottom: var(--space-10);
}
.site-footer__heading {
    margin: 0 0 var(--space-4);
    font-size: var(--text-sm);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text);
}
.site-footer__links {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(140px, 100%), 1fr));
    gap: var(--space-3);
    list-style: none;
    padding: 0;
    margin: 0;
}
.site-footer__bottom {
    max-width: var(--container-max);
    margin-inline: auto;
    padding-top: var(--space-6);
    border-top: 1px solid var(--border);
    text-align: center;
    font-size: var(--text-sm);
    color: var(--text-muted);
}
.footer-link {
    display: inline-block;
    color: var(--text-subtle);
    font-size: var(--text-sm);
    font-weight: 500;
    text-decoration: none;
}
.footer-link:hover { color: var(--primary-700); text-decoration: underline; }

.trust-badges {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-4);
}

/* --- 11.10 Carousel ------------------------------------------------------ */

.carousel-scroll-track {
    display: flex;
    gap: var(--space-5);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    padding-bottom: var(--space-4);
    scrollbar-width: thin;
}
.carousel-scroll-track > * { scroll-snap-align: start; flex: 0 0 clamp(240px, 70vw, 280px); }
.carousel-scroll-track::-webkit-scrollbar { height: 6px; }
.carousel-scroll-track::-webkit-scrollbar-thumb {
    background: var(--border-strong);
    border-radius: var(--radius-pill);
}

/* --- 11.11 Front page: opening slider ------------------------------------
   Built on scroll-snap rather than transforms so touch swiping is native and
   the strip still works with JavaScript disabled. ui.js only layers on the
   buttons, dot state and auto-advance. */

.hero-slider {
    position: relative;
    margin-bottom: var(--space-8);
}
.hero-slider__viewport {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    border-radius: var(--radius-lg);
    /* Scrollbar is hidden because the dots already communicate position. */
    scrollbar-width: none;
}
.hero-slider__viewport::-webkit-scrollbar { display: none; }

.hero-slide {
    position: relative;
    flex: 0 0 100%;
    scroll-snap-align: start;
    min-height: 320px;
    display: flex;
    align-items: flex-end;
    background: var(--primary-900);
    overflow: hidden;
    isolation: isolate;
}
.hero-slide__media {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    z-index: -1;
}
/* Scrim: guarantees text contrast over an unknown photograph. Without it the
   AA ratio depends entirely on whatever image the admin uploaded. */
.hero-slide::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(to top, rgba(2, 6, 23, 0.92) 12%, rgba(2, 6, 23, 0.55) 55%, rgba(2, 6, 23, 0.25) 100%);
    z-index: -1;
}
.hero-slide__body {
    padding: var(--space-6);
    color: #fff;
    max-width: 42rem;
}
.hero-slide__title {
    color: #fff;
    font-size: var(--text-2xl);
    line-height: 1.15;
    margin: 0 0 var(--space-2);
}
.hero-slide__text {
    color: #e2e8f0;
    margin: 0 0 var(--space-3);
}
.hero-slide__price {
    font-size: var(--text-xl);
    font-weight: 700;
    color: #fff;
    margin: 0 0 var(--space-4);
}

.hero-slider__nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    background: rgba(15, 23, 42, 0.72);
    border-color: rgba(255, 255, 255, 0.28);
    color: #fff;
}
.hero-slider__nav:hover { background: rgba(15, 23, 42, 0.9); }
.hero-slider__nav--prev { left: var(--space-3); }
.hero-slider__nav--next { right: var(--space-3); }

.hero-slider__dots {
    display: flex;
    justify-content: center;
    gap: var(--space-2);
    margin-top: var(--space-3);
}
.hero-slider__dot {
    /* Visually a 10px dot, but the hit area is a full tap target. */
    width: var(--tap-target);
    height: var(--space-6);
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    position: relative;
}
.hero-slider__dot::before {
    content: '';
    position: absolute;
    inset: 50% 0 auto;
    transform: translateY(-50%);
    margin: 0 auto;
    width: 10px;
    height: 10px;
    border-radius: var(--radius-pill);
    background: var(--border-strong);
    transition: background var(--transition), width var(--transition);
}
.hero-slider__dot[aria-selected='true']::before {
    background: var(--primary);
    width: 26px;
}

/* --- 11.12 Front page: event promotion banner ---------------------------
   The only dark full-bleed surface on the page. That is what separates it
   from the commerce grid without competing with product imagery. */

.event-banner {
    position: relative;
    border-radius: var(--radius-lg);
    padding: var(--space-6);
    margin-bottom: var(--space-8);
    background:
        radial-gradient(circle at 100% 0%, rgba(79, 70, 229, 0.55), transparent 60%),
        linear-gradient(135deg, #1e1b4b 0%, #0f172a 100%);
    border: 1px solid rgba(255, 255, 255, 0.14);
    overflow: hidden;
}
.event-banner__body { max-width: 46rem; }

.event-banner__kicker {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-3);
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-pill);
    /* Amber on near-black: 10.4:1. Amber on white would have failed AA. */
    background: rgba(251, 191, 36, 0.18);
    color: #fcd34d;
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.event-banner__title {
    color: #fff;
    font-size: var(--text-2xl);
    line-height: 1.2;
    margin: 0 0 var(--space-2);
}
.event-banner__prize {
    color: #e2e8f0;
    font-size: var(--text-lg);
    margin: 0 0 var(--space-5);
}
.event-banner__prize strong { color: #fff; }

.event-steps {
    list-style: none;
    margin: 0 0 var(--space-5);
    padding: 0;
    display: grid;
    gap: var(--space-3);
}
.event-steps li {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    color: #e2e8f0;
    font-weight: 500;
}
.event-steps__num {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: var(--radius-pill);
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
    font-size: var(--text-sm);
    font-weight: 700;
}

.event-banner__progress { margin-bottom: var(--space-5); }
.event-banner .progress { background: rgba(255, 255, 255, 0.16); }
.event-banner__meta {
    margin: var(--space-2) 0 0;
    color: #cbd5e1;
    font-size: var(--text-sm);
}
.event-banner__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
}
/* Inverted secondary: the default grey button disappears on this surface. */
.event-banner .btn-secondary {
    background: rgba(255, 255, 255, 0.12);
    border-color: rgba(255, 255, 255, 0.32);
    color: #fff;
}
.event-banner .btn-secondary:hover { background: rgba(255, 255, 255, 0.2); }

/* --- 11.13 Front page: brand rail & sections ----------------------------- */

.brand-rail {
    display: flex;
    gap: var(--space-3);
    overflow-x: auto;
    padding-bottom: var(--space-3);
    margin-bottom: var(--space-8);
    scroll-snap-type: x proximity;
    scrollbar-width: none;
}
.brand-rail::-webkit-scrollbar { display: none; }

.brand-tile {
    flex: 0 0 auto;
    scroll-snap-align: start;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-1);
    min-width: 6.5rem;
    padding: var(--space-4) var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--card-bg);
    text-decoration: none;
    color: var(--text);
    transition: border-color var(--transition), box-shadow var(--transition), transform var(--transition);
}
.brand-tile:hover {
    border-color: var(--primary);
    box-shadow: var(--shadow-sm);
    transform: translateY(-2px);
}
.brand-tile__icon {
    display: grid;
    place-items: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: var(--radius-pill);
    background: var(--primary-100);
    color: var(--primary-700);
}
.brand-tile__name { font-weight: 600; font-size: var(--text-sm); }
.brand-tile__count { color: var(--text-muted); font-size: var(--text-xs); }

.brand-section { margin-bottom: var(--space-8); }

@media (min-width: 768px) {
    .hero-slide { min-height: 420px; }
    .hero-slide__body { padding: var(--space-8); }
    .hero-slide__title { font-size: var(--text-3xl); }
    .event-banner { padding: var(--space-8); }
    .event-steps {
        grid-template-columns: repeat(3, 1fr);
        align-items: start;
    }
    .event-steps li { align-items: flex-start; }
}

/* --- 11.14 Bottom navigation (phones only) -------------------------------
   One-handed reach: the five primary destinations sit in the bottom third of
   the screen where a thumb rests. Hidden from 641px up, where the top navbar
   is already reachable and two nav bars would compete.
   ------------------------------------------------------------------------- */

.bottom-nav { display: none; }

@media (max-width: 640px) {
    .bottom-nav {
        position: fixed;
        inset: auto 0 0;
        z-index: var(--z-sticky);
        display: grid;
        grid-auto-flow: column;
        grid-auto-columns: 1fr;
        background: var(--card-bg);
        border-top: 1px solid var(--border);
        box-shadow: 0 -2px 12px rgba(15, 23, 42, 0.08);
        /* Clears the iOS home indicator so the row stays tappable. */
        padding-bottom: env(safe-area-inset-bottom, 0px);
    }

    .bottom-nav__item {
        display: grid;
        justify-items: center;
        align-content: center;
        gap: 2px;
        min-height: var(--tap-target);
        padding: var(--space-2) var(--space-1);
        color: var(--text-muted);
        font-size: var(--text-xs);
        font-weight: 600;
        text-decoration: none;
        transition: color var(--duration) var(--ease);
    }
    .bottom-nav__item:hover { color: var(--primary-700); text-decoration: none; }

    /* Active state pairs colour with a top rule, so the current tab is not
       signalled by colour alone (WCAG 1.4.1). */
    .bottom-nav__item[aria-current='page'] {
        color: var(--primary-700);
        box-shadow: inset 0 2px 0 var(--primary-600);
    }

    .bottom-nav__icon-wrap { position: relative; display: inline-grid; }

    .bottom-nav__count {
        position: absolute;
        top: -6px;
        left: 60%;
        min-width: 1.1rem;
        padding: 0 4px;
        border-radius: var(--radius-pill);
        background: var(--danger-solid);
        color: var(--neutral-0);
        font-size: 0.65rem;
        line-height: 1.1rem;
        text-align: center;
        font-variant-numeric: tabular-nums;
    }

    /* Stops the fixed bar covering the end of the page and the footer. */
    body { padding-bottom: calc(4.25rem + env(safe-area-inset-bottom, 0px)); }
}

/* =========================================================================
   11.15 SHOP SIDEBAR + GRID REDESIGN
   Two-column layout on >=992px: a sticky filter column and the results
   grid. Below 992px the sidebar becomes an off-canvas drawer opened by
   the "Filters" button. Every control meets the 44px --tap-target.
   ========================================================================= */

.shop-layout {
    display: grid;
    gap: var(--space-6);
    grid-template-columns: 1fr;
    align-items: start;
}

@media (min-width: 992px) {
    .shop-layout { grid-template-columns: 280px 1fr; gap: var(--space-8); }
}

/* --- Sidebar ---------------------------------------------------------- */
.shop-filters-toggle {
    width: 100%;
    justify-content: center;
    min-height: var(--tap-target);
}
.shop-filters-toggle__count {
    margin-left: var(--space-2);
    min-width: 1.5rem; padding: 0 6px;
    border-radius: var(--radius-pill);
    background: var(--primary-600);
    color: var(--neutral-0);
    font-size: var(--text-xs); font-weight: 700;
    line-height: 1.5rem; text-align: center;
}

.shop-sidebar {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--space-5);
    display: flex; flex-direction: column; gap: var(--space-4);
    /* Mobile default: hidden drawer. JS toggles [data-open="true"]. */
    display: none;
}
.shop-sidebar[data-open="true"] { display: flex; }

@media (min-width: 992px) {
    .shop-sidebar {
        display: flex;
        position: sticky; top: calc(var(--space-4) + 60px);
        max-height: calc(100vh - var(--space-8));
        overflow-y: auto;
        box-shadow: var(--shadow-sm);
    }
    .shop-filters-toggle { display: none; }
}

.shop-sidebar__header {
    display: flex; align-items: center; justify-content: space-between;
    padding-bottom: var(--space-3);
    border-bottom: 1px solid var(--border);
}
.shop-sidebar__title { margin: 0; font-size: var(--text-lg); }
@media (min-width: 992px) { .shop-sidebar__header .btn-icon { display: none; } }

/* --- Filter groups --------------------------------------------------- */
.shop-filter-group {
    border: 0; padding: 0; margin: 0;
    display: flex; flex-direction: column; gap: var(--space-2);
}
.shop-filter-group legend {
    font-size: var(--text-sm); font-weight: 700;
    color: var(--text); margin-bottom: var(--space-1);
    text-transform: uppercase; letter-spacing: 0.04em;
}
.shop-filter-group + .shop-filter-group {
    padding-top: var(--space-4);
    border-top: 1px solid var(--border);
}

.shop-filter-list {
    list-style: none; padding: 0; margin: 0;
    display: flex; flex-direction: column; gap: var(--space-1);
}
.shop-filter-empty { color: var(--text-muted); font-size: var(--text-sm); }

.shop-filter-check {
    display: grid;
    grid-template-columns: 1.1rem 1fr auto;
    gap: var(--space-2);
    align-items: center;
    padding: var(--space-2);
    border-radius: var(--radius);
    cursor: pointer;
    min-height: var(--tap-target);
    transition: background var(--duration) var(--ease);
}
.shop-filter-check:hover { background: var(--surface-2, rgba(0,0,0,0.03)); }
.shop-filter-check input { width: 1.1rem; height: 1.1rem; accent-color: var(--primary-600); }
.shop-filter-check__label { font-size: var(--text-sm); }
.shop-filter-check__count {
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-variant-numeric: tabular-nums;
}
.shop-filter-check--switch {
    grid-template-columns: 2.5rem 1fr;
}
.shop-filter-check--switch input {
    appearance: none;
    width: 2.5rem; height: 1.4rem;
    border-radius: var(--radius-pill);
    background: var(--border-strong);
    position: relative;
    transition: background var(--duration) var(--ease);
}
.shop-filter-check--switch input::after {
    content: '';
    position: absolute; top: 2px; left: 2px;
    width: 1rem; height: 1rem;
    border-radius: 50%;
    background: var(--neutral-0);
    transition: transform var(--duration) var(--ease);
}
.shop-filter-check--switch input:checked { background: var(--primary-600); }
.shop-filter-check--switch input:checked::after { transform: translateX(1.1rem); }
.shop-filter-check--switch input:focus-visible {
    outline: 2px solid var(--primary-600);
    outline-offset: 2px;
}

.visually-hidden-input {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --- Color swatches -------------------------------------------------- */
.shop-filter-list--swatches {
    flex-direction: row; flex-wrap: wrap; gap: var(--space-2);
}
.swatch {
    display: inline-block;
    width: 1.75rem; height: 1.75rem;
    border-radius: 50%;
    border: 2px solid var(--border);
    background: var(--swatch, currentColor);
    cursor: pointer;
    transition: transform var(--duration) var(--ease),
                border-color var(--duration) var(--ease);
    position: relative;
}
.swatch::after {
    content: '';
    position: absolute; inset: -4px;
    border-radius: 50%;
    border: 2px solid transparent;
}
.swatch:hover { transform: scale(1.08); }
.visually-hidden-input:focus-visible + .swatch {
    outline: 2px solid var(--primary-600);
    outline-offset: 2px;
}
.visually-hidden-input:checked + .swatch {
    border-color: var(--primary-600);
}
.visually-hidden-input:checked + .swatch::after {
    border-color: var(--primary-600);
}

/* --- Price slider ---------------------------------------------------- */
.shop-price { display: flex; flex-direction: column; gap: var(--space-3); }
.shop-price__inputs {
    display: grid; grid-template-columns: 1fr auto 1fr; gap: var(--space-2);
    align-items: end;
}
.shop-price__field { display: flex; flex-direction: column; gap: var(--space-1); }
.shop-price__field span {
    font-size: var(--text-xs); color: var(--text-muted); font-weight: 600;
}
.shop-price__field input {
    width: 100%;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    font-size: var(--text-sm);
    min-height: var(--tap-target);
}
.shop-price__field input:focus-visible {
    border-color: var(--primary-600);
    outline: 2px solid var(--primary-600); outline-offset: 2px;
}
.shop-price__sep { color: var(--text-muted); padding-bottom: var(--space-3); }

.shop-price__slider {
    position: relative; height: 28px;
    --pmin: 0; --pmax: 1000;
    --lo: 0%; --hi: 100%;
}
.shop-price__slider::before {
    content: '';
    position: absolute; left: 0; right: 0; top: 50%;
    height: 4px;
    background: var(--border);
    border-radius: var(--radius-pill);
    transform: translateY(-50%);
}
.shop-price__slider::after {
    content: '';
    position: absolute;
    left: var(--lo); right: calc(100% - var(--hi));
    top: 50%;
    height: 4px;
    background: var(--primary-600);
    border-radius: var(--radius-pill);
    transform: translateY(-50%);
}
.shop-price__slider input[type="range"] {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    background: transparent; -webkit-appearance: none; appearance: none;
    margin: 0; padding: 0; pointer-events: none;
}
.shop-price__slider input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 20px; height: 20px;
    border-radius: 50%;
    background: var(--neutral-0);
    border: 2px solid var(--primary-600);
    cursor: grab;
    pointer-events: auto;
    box-shadow: var(--shadow-sm);
}
.shop-price__slider input[type="range"]::-moz-range-thumb {
    width: 20px; height: 20px;
    border-radius: 50%;
    background: var(--neutral-0);
    border: 2px solid var(--primary-600);
    cursor: grab;
    pointer-events: auto;
    box-shadow: var(--shadow-sm);
}
.shop-price__slider input[type="range"]::-webkit-slider-thumb:active { cursor: grabbing; }
.shop-price__slider input[type="range"]:focus-visible::-webkit-slider-thumb {
    outline: 2px solid var(--primary-700); outline-offset: 2px;
}

/* --- Filter actions -------------------------------------------------- */
.shop-filter-actions {
    display: flex; flex-direction: column; gap: var(--space-2);
    padding-top: var(--space-3);
    border-top: 1px solid var(--border);
}

/* --- Results panel --------------------------------------------------- */
.shop-results { display: flex; flex-direction: column; gap: var(--space-5); min-width: 0; }

.shop-results__toolbar {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-4); flex-wrap: wrap;
}
.shop-results__count { margin: 0; color: var(--text-muted); }
.shop-results__count strong { color: var(--text); }
.shop-results__sort {
    display: flex; align-items: center; gap: var(--space-2);
}
.shop-results__sort label { color: var(--text-muted); font-size: var(--text-sm); }
.shop-results__sort select {
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    min-height: var(--tap-target);
    font-size: var(--text-sm);
}

.shop-active {
    display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    background: var(--surface-2, rgba(0,0,0,0.03));
    border-radius: var(--radius);
}
.shop-active__label {
    color: var(--text-muted); font-size: var(--text-sm); font-weight: 600;
}
.shop-active__list {
    list-style: none; padding: 0; margin: 0;
    display: flex; flex-wrap: wrap; gap: var(--space-2);
}
.shop-active__chip {
    display: inline-flex; align-items: center; gap: var(--space-1);
    padding: var(--space-1) var(--space-3);
    background: var(--card-bg);
    border: 1px solid var(--primary-600);
    color: var(--primary-700);
    border-radius: var(--radius-pill);
    font-size: var(--text-sm);
    text-decoration: none;
    min-height: 32px;
    transition: background var(--duration) var(--ease);
}
.shop-active__chip:hover { background: var(--primary-50, rgba(79,70,229,0.08)); }
.shop-active__chip:focus-visible {
    outline: 2px solid var(--primary-600); outline-offset: 2px;
}

/* --- Products grid (shop variant) -----------------------------------
   Explicit column counts per device band rather than auto-fill, because the
   sidebar takes 280px out of the row and auto-fill would otherwise drop to
   two columns at inconsistent widths. Tracks the breakpoint contract in
   section 01: mobile 1, tablet 2, desktop 3, wide 4.
   -------------------------------------------------------------------- */
.products-grid--shop {
    grid-template-columns: 1fr;
    gap: var(--space-5);
}

@media (min-width: 768px) {
    .products-grid--shop { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1200px) {
    .products-grid--shop {
        grid-template-columns: repeat(3, 1fr);
        gap: var(--space-6);
    }
}
@media (min-width: 1440px) {
    .products-grid--shop { grid-template-columns: repeat(4, 1fr); }
}

/* --- Product card enhancements -------------------------------------- */
.product-eyebrow {
    margin: 0 0 var(--space-1) 0;
    font-size: var(--text-xs);
    color: var(--text-muted);
    text-transform: uppercase; letter-spacing: 0.05em;
    font-weight: 600;
}
.product-badge-sale {
    position: absolute; top: var(--space-2); left: var(--space-2);
    padding: 2px 8px;
    background: var(--danger-solid);
    color: var(--neutral-0);
    font-size: var(--text-xs);
    font-weight: 700;
    border-radius: var(--radius);
    z-index: 1;
}
.product-price__effective {
    color: var(--danger-text);
    font-weight: 700;
}
.product-price__was {
    margin-left: var(--space-2);
    color: var(--text-muted);
    text-decoration: line-through;
    font-size: var(--text-sm);
}
.product-rating {
    display: inline-flex; align-items: center; gap: var(--space-2);
    margin-bottom: var(--space-1);
}
.product-rating__stars { color: var(--border-strong); letter-spacing: 1px; }
.product-rating__star.is-filled { color: #f59e0b; }
.product-rating__count { font-size: var(--text-xs); color: var(--text-muted); font-variant-numeric: tabular-nums; }

.product-quickview {
    position: absolute; bottom: var(--space-2); right: var(--space-2);
    display: inline-flex; align-items: center; gap: var(--space-1);
    padding: var(--space-1) var(--space-3);
    background: var(--neutral-0);
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    font-size: var(--text-xs); font-weight: 600;
    color: var(--text);
    opacity: 0;
    transform: translateY(4px);
    transition: opacity var(--duration) var(--ease),
                transform var(--duration) var(--ease);
    min-height: 32px;
    cursor: pointer;
}
.product-card:hover .product-quickview,
.product-card:focus-within .product-quickview,
.product-quickview:focus-visible {
    opacity: 1; transform: translateY(0);
}

/* --- Quick-view dialog ---------------------------------------------- */
.quickview-dialog {
    width: min(560px, 92vw);
    border: 0;
    border-radius: var(--radius-lg);
    padding: 0;
    background: var(--card-bg);
    box-shadow: var(--shadow-lg);
}
.quickview-dialog::backdrop {
    background: rgba(15, 23, 42, 0.55);
    backdrop-filter: blur(2px);
}
.quickview-dialog[open] { animation: quickview-in 200ms var(--ease); }
@keyframes quickview-in {
    from { opacity: 0; transform: translateY(8px) scale(0.98); }
    to   { opacity: 1; transform: none; }
}
.quickview {
    display: flex; flex-direction: column; gap: var(--space-3);
    padding: var(--space-5);
}
.quickview__header {
    display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3);
}
.quickview__title { margin: 0; font-size: var(--text-xl); }
.quickview__body { display: flex; flex-direction: column; gap: var(--space-3); }
.quickview__image {
    width: 100%; aspect-ratio: 16/10;
    background: var(--surface-2, rgba(0,0,0,0.04));
    border-radius: var(--radius);
    display: flex; align-items: center; justify-content: center;
}
.quickview__image img { max-width: 100%; max-height: 100%; object-fit: contain; }
.quickview__price { display: flex; align-items: baseline; gap: var(--space-2); }
.quickview__price-was { color: var(--text-muted); text-decoration: line-through; }
.quickview__actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.quickview__close {
    background: transparent; border: 0; cursor: pointer; padding: var(--space-1);
    color: var(--text-muted);
}

/* --- Drawer backdrop (mobile) --------------------------------------- */
.shop-sidebar[data-open="true"]::before {
    /* Desktop never enters the drawer state, so this only fires on mobile. */
}

/* --- Reduced motion -------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .product-quickview,
    .product-card,
    .shop-active__chip,
    .swatch,
    .shop-filter-check {
        transition: none !important;
    }
    .quickview-dialog[open] { animation: none; }
}

/* --- Print ----------------------------------------------------------- */
@media print {
    .shop-sidebar,
    .shop-filters-toggle,
    .product-quickview,
    .shop-active__chip { display: none !important; }
}

/* =========================================================================
   11.16 ADMIN: FRONTEND CATEGORY VISIBILITY
   =========================================================================
   Styles the admin settings screen that controls which categories reach the
   storefront. The switch is a real <input type="checkbox"> with a painted
   track, so keyboard operation, form submission and the :checked state all
   come from the platform rather than from JavaScript.
   ========================================================================= */

/* --- Summary tiles ---------------------------------------------------- */
.visibility-summary {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: var(--space-3);
    margin-bottom: var(--space-5);
}

.visibility-summary__tile {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-4);
    border: 1px solid var(--border);
    border-left: 4px solid var(--border-strong);
    border-radius: var(--radius-lg);
    background: var(--card-bg);
}

/* Left border, not fill, carries the accent so the value keeps full contrast. */
.visibility-summary__tile--on  { border-left-color: var(--primary-600); }
.visibility-summary__tile--off { border-left-color: var(--warning-border, var(--border-strong)); }

.visibility-summary__value {
    font-size: var(--text-2xl);
    font-weight: 800;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.visibility-summary__label {
    font-size: var(--text-sm);
    color: var(--text-muted);
}

/* --- Search + filter toolbar ------------------------------------------ */
.visibility-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}

.visibility-toolbar__search {
    position: relative;
    flex: 1 1 260px;
    min-width: 0;
}

.visibility-toolbar__search-icon {
    position: absolute;
    top: 50%;
    left: var(--space-3);
    transform: translateY(-50%);
    color: var(--text-muted);
    pointer-events: none;
}

.visibility-toolbar__search input {
    box-sizing: border-box;
    width: 100%;
    min-height: var(--tap-target);
    /* Left padding clears the icon; it is not a magic number. */
    padding: var(--space-2) var(--space-3) var(--space-2) calc(var(--space-3) * 2 + 1rem);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--neutral-0);
    font: inherit;
    font-size: var(--text-sm);
}

.visibility-toolbar__search input:focus-visible {
    outline: 2px solid var(--primary-600);
    outline-offset: 2px;
}

.visibility-toolbar__filter {
    display: inline-flex;
    gap: var(--space-1);
    padding: 3px;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background: var(--neutral-50);
}

.visibility-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: calc(var(--tap-target) - 8px);
    padding: var(--space-2) var(--space-4);
    border-radius: var(--radius-pill);
    color: var(--neutral-700);
    font-size: var(--text-sm);
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    transition: background var(--duration) var(--ease), color var(--duration) var(--ease);
}

.visibility-chip:hover { background: var(--neutral-0); }
.visibility-chip.is-active {
    background: var(--primary-600);
    color: var(--neutral-0);
}

/* The radio is visually hidden, so the focus ring has to be drawn on the
   label instead or keyboard users lose the focus indicator (WCAG 2.4.7). */
.visibility-chip:focus-within {
    outline: 2px solid var(--primary-600);
    outline-offset: 2px;
}

/* --- Card + table ------------------------------------------------------ */
.visibility-card { padding: 0; overflow: hidden; }

.visibility-card__head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-5);
    border-bottom: 1px solid var(--border);
}

.visibility-card__title {
    margin: 0;
    font-size: var(--text-lg);
}

.visibility-card__hint {
    margin: var(--space-1) 0 0;
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.visibility-card__bulk {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.visibility-card__no-match {
    margin: 0;
    padding: var(--space-6) var(--space-5);
    color: var(--text-muted);
    text-align: center;
}

.visibility-table { margin: 0; }
.visibility-table__switch-col { width: 1%; white-space: nowrap; }

.visibility-name {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

/* Indent marks the parent/child relationship visually; the "in <parent>"
   text in the meta line carries the same information for screen readers. */
.visibility-name--child { padding-left: var(--space-5); }

.visibility-name__icon {
    font-size: 1.35rem;
    line-height: 1;
}

.visibility-name__meta {
    display: block;
    margin-top: 2px;
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-weight: 400;
}

/* --- The switch -------------------------------------------------------- */
.visibility-switch {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: var(--tap-target);
    cursor: pointer;
    user-select: none;
}

.visibility-switch input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.visibility-switch__track {
    position: relative;
    flex: none;
    width: 2.75rem;
    height: 1.5rem;
    border-radius: var(--radius-pill);
    background: var(--border-strong);
    transition: background var(--duration) var(--ease);
}

.visibility-switch__track::after {
    content: '';
    position: absolute;
    top: 3px;
    left: 3px;
    width: 1.125rem;
    height: 1.125rem;
    border-radius: 50%;
    background: var(--neutral-0);
    box-shadow: var(--shadow-sm);
    transition: transform var(--duration) var(--ease);
}

.visibility-switch input:checked + .visibility-switch__track { background: var(--primary-600); }
.visibility-switch input:checked + .visibility-switch__track::after { transform: translateX(1.25rem); }

/* Focus ring lives on the track because the input itself is off-screen. */
.visibility-switch input:focus-visible + .visibility-switch__track {
    outline: 2px solid var(--primary-600);
    outline-offset: 2px;
}

.visibility-switch__label {
    min-width: 3.5rem;
    color: var(--text-muted);
    font-size: var(--text-sm);
    font-weight: 600;
}

.visibility-switch input:checked ~ .visibility-switch__label { color: var(--primary-700); }

/* --- Save bar ---------------------------------------------------------- */
.visibility-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    border-top: 1px solid var(--border);
    background: var(--neutral-50);
}

.visibility-actions__status {
    margin: 0;
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.visibility-actions__status[data-dirty="true"] {
    color: var(--primary-700);
    font-weight: 600;
}

.visibility-actions__buttons {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-left: auto;
}

/* --- Narrow viewports --------------------------------------------------- */
@media (max-width: 640px) {
    .visibility-toolbar__filter { width: 100%; justify-content: space-between; }
    .visibility-chip { flex: 1; padding-inline: var(--space-2); }
    .visibility-actions__buttons { width: 100%; }
    .visibility-actions__buttons .btn { flex: 1; justify-content: center; }
}

/* --- User preferences --------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .visibility-switch__track,
    .visibility-switch__track::after,
    .visibility-chip { transition: none; }
}

/* In forced-colours mode the painted track disappears, so give it a border
   that the OS palette will honour. */
@media (forced-colors: active) {
    .visibility-switch__track { border: 1px solid CanvasText; }
    .visibility-switch input:checked + .visibility-switch__track { background: Highlight; }
}

/* =========================================================================
   12. UTILITIES & USER PREFERENCES
   ========================================================================= */

.text-muted   { color: var(--text-muted) !important; }
.text-subtle  { color: var(--text-subtle) !important; }
/* AA-compliant replacements for the former 2.1:1–3.8:1 status colours. */
.text-success { color: var(--success-text) !important; font-weight: 600; }
.text-danger  { color: var(--danger-text) !important;  font-weight: 600; }
.text-warning { color: var(--warning-text) !important; font-weight: 600; }
.text-info    { color: var(--info-text) !important;    font-weight: 600; }

.text-right  { text-align: right; }
.text-center { text-align: center; }
.text-left   { text-align: left; }
.numeric     { font-variant-numeric: tabular-nums; }
.truncate    { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.full-width  { width: 100%; }
.no-wrap     { white-space: nowrap; }

.mb-0 { margin-bottom: 0 !important; }
.mb-1 { margin-bottom: var(--space-2); }
.mb-2 { margin-bottom: var(--space-4); }
.mb-3 { margin-bottom: var(--space-6); }
.mt-0 { margin-top: 0 !important; }
.mt-1 { margin-top: var(--space-2); }
.mt-2 { margin-top: var(--space-4); }
.mt-3 { margin-top: var(--space-6); }
.mt-auto { margin-top: auto; }

/* Visibility helpers. These only ever *hide*; they never set a display value,
   which would clobber the element's own layout mode (flex, grid, ...). */
@media (max-width: 640px) {
    .hide-sm { display: none !important; }
}
@media (max-width: 991px) {
    .hide-md { display: none !important; }
}
@media (min-width: 992px) {
    .show-md-only { display: none !important; }
}

/* ==========================================================================
   11.17  PRODUCT GALLERY TRACK, SPECS & BUY BAR
   ==========================================================================
   Extends 11.11 rather than repeating it: .product-detail, .gallery-thumb
   and .product-gallery__thumbs are already defined there. This section adds
   the swipeable track that replaced the single swapped <img>, the spec list
   and the sticky mobile buy bar.
   ========================================================================== */

/* --- Swipeable gallery track --------------------------------------------- */

/* On desktop the gallery stays with the reader through long spec lists.
   The offset clears the sticky site header. */
@media (min-width: 992px) {
    .product-gallery {
        position: sticky;
        top: calc(var(--header-height) + var(--space-4));
    }
}

.product-gallery__track {
    display: flex;
    width: 100%;
    height: 100%;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    /* Firefox; the WebKit rule follows. */
    scrollbar-width: none;
}
.product-gallery__track::-webkit-scrollbar { display: none; }

/* The track is focusable for arrow-key navigation, so it needs a ring. */
.product-gallery__track:focus-visible {
    outline: 2px solid var(--primary-600);
    outline-offset: 2px;
}

.product-gallery__slide {
    flex: 0 0 100%;
    scroll-snap-align: center;
    display: grid;
    place-items: center;
}

/* The zoom trigger wraps the image so the whole picture is the hit area. */
.product-gallery__zoom {
    display: grid;
    place-items: center;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    background: none;
    cursor: zoom-in;
    overflow: hidden;
}

.product-gallery__zoom img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    transition: transform var(--duration) var(--ease);
}

.product-gallery__zoom.is-zoomed { cursor: zoom-out; }
.product-gallery__zoom.is-zoomed img { transform: scale(1.9); }

/* --- Gallery arrows ------------------------------------------------------- */

.product-gallery__nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 1;
    border-radius: 50%;
    /* Semi-opaque so the image reads through without losing the control. */
    background: rgb(255 255 255 / 0.92);
    box-shadow: var(--shadow-sm);
}
.product-gallery__nav:disabled { opacity: 0.35; cursor: default; }
.product-gallery__nav--prev { left: var(--space-3); }
.product-gallery__nav--next { right: var(--space-3); }

/* Arrows are a pointer affordance; touch users swipe instead. */
@media (hover: none) {
    .product-gallery__nav { display: none; }
}

/* --- Specifications ------------------------------------------------------ */

.spec-list {
    margin: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

.spec-list__row {
    display: grid;
    grid-template-columns: minmax(7rem, 38%) 1fr;
    gap: var(--space-3);
    align-items: center;
    padding: var(--space-3) var(--space-4);
}

/* Zebra striping carries the row boundary without 1px borders doubling up
   against the container edge. */
.spec-list__row:nth-child(odd) { background: var(--neutral-50); }

.spec-list__row dt {
    margin: 0;
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text-muted);
}

.spec-list__row dd {
    margin: 0;
    font-size: var(--text-sm);
    color: var(--text);
}

/* --- Sticky mobile buy bar ----------------------------------------------- */

.buy-bar {
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    /* Above page content, below the nav drawer overlay (which sits at 100). */
    z-index: 60;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    /* Clears the iOS home indicator. */
    padding-bottom: calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--border);
    background: var(--card-bg);
    box-shadow: 0 -4px 16px rgb(15 23 42 / 0.08);
}

.buy-bar__info { flex: 1 1 auto; min-width: 0; }

.buy-bar__name {
    margin: 0;
    font-size: var(--text-sm);
    font-weight: 600;
    /* One line only: the bar must not grow and eat the viewport. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.buy-bar__price {
    margin: 0;
    font-size: var(--text-lg);
    font-weight: 700;
    color: var(--primary-700);
    font-variant-numeric: tabular-nums;
}

.buy-bar__cta { flex: 0 0 auto; }

/* The bar is a mobile affordance only — desktop keeps the inline form in
   view, so a second button would be redundant. */
@media (min-width: 992px) {
    .buy-bar { display: none; }
}

/* Reserve room so the bar never covers the end of the page content. */
@media (max-width: 991px) {
    body:has(.buy-bar) main { padding-bottom: 6rem; }
}

/* --- Reduced motion (WCAG 2.3.3) ---------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
    /* Transforms are the main source of vestibular discomfort here. */
    .btn:hover,
    .card-interactive:hover,
    .product-card:hover,
    .stat-card:hover,
    a .stat-card:hover { transform: none; }
    .carousel-scroll-track { scroll-behavior: auto; }
}

/* --- Windows High Contrast / forced colours ------------------------------ */
@media (forced-colors: active) {
    .btn,
    .btn-icon,
    .card,
    .badge,
    .alert,
    .product-card,
    .stat-card { border: 1px solid CanvasText; }

    /* Backgrounds are dropped in forced-colors, so restore a real outline. */
    :focus-visible { outline: 3px solid Highlight; box-shadow: none; }

    .nav-link.active::after,
    .nav-link[aria-current='page']::after { background: Highlight; }
}

/* --- Print --------------------------------------------------------------- */
@media print {
    .navbar,
    .site-footer,
    .admin-sidebar,
    .skip-link,
    .pagination,
    .product-actions-toolbar,
    .bottom-nav,
    .hero-slider__nav,
    .hero-slider__dots,
    .page-header__actions { display: none !important; }

    body { background: #fff; color: #000; }
    .card,
    .table { box-shadow: none; border: 1px solid #ccc; }
    .admin-workspace { grid-template-columns: 1fr; }
    a[href^='http']::after { content: ' (' attr(href) ')'; font-size: 0.8em; }
}

/* ==========================================================================
   11.18  LUCKY DRAWS: ELIGIBILITY, COUNTDOWN & PARTICIPATION HISTORY
   ==========================================================================
   Supports the redesigned draws page. Reuses .card, .hero, .section-header
   and .products-grid from earlier sections rather than restating them; only
   the genuinely new patterns live here.
   ========================================================================== */

/* --- Eligibility panel ---------------------------------------------------- */

.eligibility {
    /* Pulled up against the hero: the rules answer the question the hero
       provokes, so the two read as one unit rather than separate blocks. */
    margin-top: calc(var(--space-10) * -1 + var(--space-6));
    margin-bottom: var(--space-10);
}

.eligibility__title {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-4);
    font-size: var(--text-lg);
}

.eligibility__rules {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
    gap: var(--space-3);
    margin: 0;
    padding: 0;
    list-style: none;
}

.eligibility__rules > li {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    color: var(--text-subtle);
    line-height: 1.5;
}

/* The tick is decorative reinforcement; the rule text carries the meaning. */
.eligibility__rules > li > .icon {
    flex: 0 0 auto;
    margin-top: 0.15em;
    color: var(--success-text, var(--primary-600));
}

/* --- Countdown ------------------------------------------------------------ */

.countdown {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: 0 0 var(--space-4);
    font-size: var(--text-sm);
    color: var(--text-subtle);
}

.countdown__label { font-weight: 600; }

/* Tabular figures stop the row from twitching sideways as digits tick over. */
.countdown__value {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text);
}

/* An expired countdown is a state change, not just a colour change: the JS
   also rewrites the text, so this is reinforcement only (WCAG 1.4.1). */
.countdown.is-expired .countdown__value { color: var(--text-muted); }

/* --- Participation history ------------------------------------------------ */

.history-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.history-list__item {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-4) 0;
    border-bottom: 1px solid var(--border);
}
.history-list__item:first-child { padding-top: 0; }
.history-list__item:last-child { padding-bottom: 0; border-bottom: 0; }

.history-list__main {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    /* Lets a long draw name wrap instead of shoving the meta column off-row. */
    min-width: min(100%, 12rem);
    flex: 1 1 auto;
}

.history-list__main .text-muted { font-size: var(--text-sm); }

.history-list__meta {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

/* --- Winners board (11.18 continuation) --------------------------------- */

/* Live poll announcement. Remains hidden until ui.js reveals it, so it reads
   as a fresh event rather than a static banner. */
.winners-live {
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-3);
}

/* Filter bar: three controls on desktop, stacked as space tightens, and the
   actions button row always sits flush against the last control. */
.winners-filters { margin-bottom: var(--space-8); }

.winners-filters__title {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-4);
    font-size: var(--text-lg);
}

.winners-filters__form {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr auto;
    gap: var(--space-4);
    align-items: end;
}

/* The .form-group margin is for stacked forms; in the filter grid it fights
   the `align-items: end` and misaligns the button. */
.winners-filters__form .form-group { margin-bottom: 0; }

.winners-filters__actions {
    display: flex;
    gap: var(--space-2);
    /* Matches the control height so Apply aligns with the inputs' bottoms. */
    padding-top: 1.65rem;
}

@media (max-width: 700px) {
    .winners-filters__form { grid-template-columns: 1fr 1fr; }
    .winners-filters__form .form-group:first-child { grid-column: 1 / -1; }
    .winners-filters__actions { grid-column: 1 / -1; padding-top: 0; }
}

/* Individual winner card. */
.winner-card { display: flex; flex-direction: column; }

.winner-card__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}

.winner-card__name {
    font-size: var(--text-xl);
    font-weight: 700;
    margin: 0 0 var(--space-1);
}

/* Inline explanation when a winner opted out of being named. */
.winner-card__note {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    font-size: var(--text-sm);
    font-weight: 500;
}

.winner-card__share {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: auto;
    padding-top: var(--space-4);
}

/* =========================================================================
   11.19  ADMIN PAGE CONTENT EDITOR
   Section editor for the public draws and winners pages: reorderable section
   cards, a sticky save bar, the publish panel and the version change log.
   ========================================================================= */

/* --- Editor index --------------------------------------------------------- */

.page-editor-list {
    display: grid;
    gap: var(--space-5);
    /* One column until there is genuinely room for two; these cards carry a
       lot of text and read badly when squeezed. */
    grid-template-columns: 1fr;
}

@media (min-width: 900px) {
    .page-editor-list { grid-template-columns: repeat(2, 1fr); }
}

.page-editor-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.page-editor-card__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    flex-wrap: wrap;
}

.page-editor-card__title {
    margin: 0;
    font-size: var(--text-lg);
    font-weight: 600;
}

.page-editor-card__meta {
    margin: var(--space-1) 0 0;
    font-size: var(--text-sm);
}

.page-editor-card__facts {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-3);
    margin: 0;
    padding: var(--space-3) 0;
    border-top: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
}

.page-editor-card__facts dt {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

.page-editor-card__facts dd {
    margin: var(--space-1) 0 0;
    font-size: var(--text-sm);
    font-weight: 500;
}

.page-editor-card__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: auto;
}

/* --- Section editor ------------------------------------------------------- */

.page-editor__sections {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.editor-section {
    /* Reset the browser's fieldset chrome; the card supplies the framing. */
    margin: 0;
    padding: var(--space-5);
    border: 1px solid var(--border);
    min-width: 0;
    transition: box-shadow var(--duration) var(--ease),
                border-color var(--duration) var(--ease),
                opacity var(--duration) var(--ease);
}

/* Dragged card. Kept subtle so the drop target stays the focus. */
.editor-section.is-dragging {
    opacity: 0.5;
    border-color: var(--primary-600);
}

/* Where the dragged card would land. */
.editor-section.is-drop-target {
    border-color: var(--primary-600);
    box-shadow: 0 0 0 2px var(--primary-50);
}

/* A disabled section stays fully readable and editable — dimming it would
   imply the fields are unavailable, which they are not. The badge and the
   switch label carry the state instead. */
.editor-section:has([data-editor-toggle]:not(:checked)) .editor-section__title::after {
    content: " (hidden)";
    color: var(--text-muted);
    font-weight: 400;
}

.editor-section__head {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    flex-wrap: wrap;
    padding-bottom: var(--space-4);
    border-bottom: 1px solid var(--border);
}

.editor-section__handle {
    display: none; /* Shown only once JS enables drag; see .js-drag below. */
    align-items: center;
    justify-content: center;
    width: var(--tap-target);
    height: var(--tap-target);
    border-radius: var(--radius-md);
    color: var(--text-muted);
    cursor: grab;
    flex-shrink: 0;
}

.js-drag .editor-section__handle { display: flex; }
.editor-section__handle:active { cursor: grabbing; }

/* Pointer-only affordance: touch users reorder with the buttons, which are
   already large enough to hit. */
@media (hover: none) {
    .js-drag .editor-section__handle { display: none; }
}

.editor-section__heading {
    flex: 1 1 14rem;
    min-width: 0;
}

.editor-section__title {
    margin: 0;
    font-size: var(--text-base);
    font-weight: 600;
}

.editor-section__description {
    margin: var(--space-1) 0 0;
    font-size: var(--text-sm);
}

.editor-section__move {
    display: flex;
    gap: var(--space-1);
    flex-shrink: 0;
}

.editor-section__move-btn {
    /* Square tap targets meeting WCAG 2.5.5 without relying on label text. */
    width: var(--tap-target);
    height: var(--tap-target);
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.editor-section__move-btn[disabled] {
    opacity: 0.4;
    cursor: not-allowed;
}

/* The arrow icons are horizontal; rotating them keeps one icon definition
   serving both directions rather than adding near-duplicate SVGs. */
.editor-section__move-btn[data-editor-move="up"] .editor-section__move-icon {
    transform: rotate(90deg);
}
.editor-section__move-btn[data-editor-move="down"] .editor-section__move-icon {
    transform: rotate(-90deg);
}

.editor-section__toggle { flex-shrink: 0; }

.editor-section__fields {
    display: grid;
    gap: var(--space-4);
    padding-top: var(--space-4);
}

@media (min-width: 720px) {
    .editor-section__fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    /* Long-form copy gets the full width; short labels pair up. */
    .editor-field--textarea { grid-column: 1 / -1; }
}

.editor-field--bool { align-self: end; }

/* --- Sticky save bar ------------------------------------------------------ */

.page-editor__actions {
    position: sticky;
    bottom: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-top: var(--space-5);
    padding: var(--space-4);
    /* Clears the iOS home indicator when the bar sits at the viewport edge. */
    padding-bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0px));
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
}

.page-editor__status {
    margin: 0;
    font-size: var(--text-sm);
    color: var(--text-muted);
}

.page-editor__status.is-saving { color: var(--text); }
.page-editor__status.is-error { color: var(--danger, #b42318); font-weight: 500; }

.page-editor__buttons {
    display: flex;
    gap: var(--space-2);
    flex-wrap: wrap;
}

/* --- Publish panel -------------------------------------------------------- */

.page-editor__publish,
.page-editor__recent {
    margin-top: var(--space-5);
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.page-editor__publish-title {
    margin: 0;
    font-size: var(--text-lg);
    font-weight: 600;
}

.page-editor__publish-form {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    max-width: 34rem;
}

.page-editor__publish-buttons {
    display: flex;
    gap: var(--space-2);
    flex-wrap: wrap;
}

/* --- Change log ----------------------------------------------------------- */

.version-entry {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}

.version-entry__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    flex-wrap: wrap;
}

.version-entry__title {
    margin: 0;
    font-size: var(--text-base);
    font-weight: 600;
}

.version-entry__summary { margin: 0; }

.version-entry__details summary {
    cursor: pointer;
    font-size: var(--text-sm);
    font-weight: 500;
    padding: var(--space-2) 0;
    border-radius: var(--radius-md);
}

.version-entry__details summary:focus-visible { outline: var(--focus-ring); }

.version-entry__sections {
    margin: var(--space-3) 0 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.version-entry__values {
    margin: var(--space-2) 0 0;
    display: grid;
    gap: var(--space-2);
}

.version-entry__values dt {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

.version-entry__values dd {
    margin: 0;
    font-size: var(--text-sm);
    /* Admin copy can contain long unbroken URLs. */
    overflow-wrap: anywhere;
}

@media (prefers-reduced-motion: reduce) {
    .editor-section { transition: none; }
}

@media (forced-colors: active) {
    .editor-section.is-drop-target { border: 2px solid Highlight; }
    .page-editor__actions { border: 1px solid CanvasText; }
}

/* =========================================================================
   11.20  QR WALLET TOP-UP
   Customer-facing scan-and-submit panel, the admin QR configuration card and
   the manual verification queue.
   ========================================================================= */

/* --- Customer: scan panel ------------------------------------------------- */

.topup-panel {
    display: grid;
    /* QR beside the form on desktop, stacked on mobile. The QR column is fixed
       so the code never scales below comfortable scanning size. */
    grid-template-columns: minmax(220px, 280px) 1fr;
    gap: var(--space-6);
    align-items: start;
}

.topup-panel__qr {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-4);
    background: #fff;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
}

/* White quiet zone around the code: scanners need the light margin, and the
   card background is not guaranteed to be white under a custom theme. */
.topup-panel__img {
    display: block;
    width: 100%;
    max-width: 240px;
    height: auto;
    padding: var(--space-3);
    background: #fff;
    border-radius: var(--radius-md);
    image-rendering: crisp-edges;
}

.topup-panel__account {
    font-size: var(--text-sm);
    font-weight: 700;
    text-align: center;
    overflow-wrap: anywhere;
}

.topup-panel__steps {
    margin: 0 0 var(--space-5);
    padding-left: var(--space-5);
    display: grid;
    gap: var(--space-2);
    font-size: var(--text-sm);
    color: var(--text-muted);
}

.topup-panel__instructions {
    margin: 0 0 var(--space-4);
    padding: var(--space-3) var(--space-4);
    background: var(--primary-50);
    border-radius: var(--radius-md);
    font-size: var(--text-sm);
    white-space: pre-line;
}

/* --- Customer: request history ------------------------------------------- */

.topup-history {
    display: grid;
    gap: var(--space-3);
}

.topup-history__item {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    align-items: center;
    justify-content: space-between;
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}

.topup-history__meta {
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: var(--text-sm);
}

.topup-history__ref {
    font-size: var(--text-xs);
    color: var(--text-muted);
    overflow-wrap: anywhere;
}

.topup-history__amount { font-weight: 800; }

.topup-history__note {
    flex-basis: 100%;
    font-size: var(--text-sm);
    color: var(--text-muted);
}

/* --- Admin: QR configuration card ---------------------------------------- */

.qr-config__grid {
    display: grid;
    grid-template-columns: minmax(200px, 240px) 1fr;
    gap: var(--space-6);
    align-items: start;
}

.qr-config__preview {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

.qr-config__img {
    width: 100%;
    max-width: 200px;
    height: auto;
    padding: var(--space-2);
    background: #fff;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}

.qr-config__placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 180px;
    padding: var(--space-4);
    color: var(--text-muted);
    background: var(--card-bg);
    border: 2px dashed var(--border);
    border-radius: var(--radius-md);
}

/* --- Admin: verification queue ------------------------------------------- */

.topup-queue__stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--space-4);
    margin-bottom: var(--space-5);
}

.topup-queue__stat {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-4) var(--space-5);
}

.topup-queue__stat-label {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

.topup-queue__stat-value {
    font-size: var(--text-lg);
    font-weight: 800;
}

.topup-queue__filters {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-bottom: var(--space-5);
}

.topup-queue__filter {
    /* Meets the 44px tap target on touch devices without looking oversized on
       a desktop pointer. */
    display: inline-flex;
    align-items: center;
    min-height: var(--tap-target);
    padding: 0 var(--space-4);
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text-muted);
    text-decoration: none;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    transition: background var(--duration) var(--ease), color var(--duration) var(--ease);
}

.topup-queue__filter:hover { background: var(--primary-50); }
.topup-queue__filter:focus-visible { outline: var(--focus-ring); }

.topup-queue__filter.is-active {
    color: #fff;
    background: var(--primary-600);
    border-color: var(--primary-600);
}

/* --- Admin: review detail ------------------------------------------------ */

.topup-review {
    display: grid;
    grid-template-columns: 1fr minmax(300px, 380px);
    gap: var(--space-5);
    align-items: start;
}

.topup-review__list {
    margin: 0;
    display: grid;
    gap: var(--space-3);
}

.topup-review__row {
    display: grid;
    grid-template-columns: minmax(120px, 34%) 1fr;
    gap: var(--space-3);
    padding-bottom: var(--space-3);
    border-bottom: 1px solid var(--border);
}

.topup-review__row:last-child { border-bottom: none; padding-bottom: 0; }

.topup-review__row dt {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

.topup-review__row dd {
    margin: 0;
    font-size: var(--text-sm);
    overflow-wrap: anywhere;
}

.topup-review__proof {
    display: block;
    width: 100%;
    max-width: 320px;
    height: auto;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}

@media (max-width: 900px) {
    .topup-panel,
    .qr-config__grid,
    .topup-review { grid-template-columns: 1fr; }

    /* Keep the QR at a scannable size once it is full width. */
    .topup-panel__qr { max-width: 320px; margin-inline: auto; }
}

@media (forced-colors: active) {
    .topup-queue__filter.is-active { border: 2px solid Highlight; }
    .qr-config__placeholder { border: 2px dashed CanvasText; }
}

/* --- 12. Payment gateways -------------------------------------------------- */
/*
 * Admin payment-methods settings page:
 *   - Summary tiles
 *   - Gateway cards with toggle switches
 *   - Settings/credentials form
 *   - Audit trail table
 *
 * WCAG 1.4.1 / 4.1.2: Toggle uses role="switch" + aria-checked.
 * Progressive enhancement: every toggle is a real <form> POST so it works
 * without JavaScript; ui.js upgrades to fetch + toast.
 */

/* 12.1 Summary tiles ---------------------------------------------------------- */

.gateway-summary {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-4);
    margin-bottom: var(--space-8);
}

.gateway-summary__tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-6) var(--space-4);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--card-bg);
    text-align: center;
}

.gateway-summary__tile--on { border-color: var(--success-border); background: var(--success-surface); }
.gateway-summary__tile--off { border-color: var(--danger-border); background: var(--danger-surface); }

.gateway-summary__value {
    font-family: var(--font-display);
    font-size: var(--text-4xl);
    font-weight: 900;
    line-height: 1;
    color: var(--text);
}

.gateway-summary__tile--on .gateway-summary__value { color: var(--success-text); }
.gateway-summary__tile--off .gateway-summary__value { color: var(--danger-text); }

.gateway-summary__label {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

@media (max-width: 640px) {
    .gateway-summary { grid-template-columns: repeat(3, 1fr); gap: var(--space-2); }
    .gateway-summary__value { font-size: var(--text-2xl); }
}

/* 12.2 Danger banner ---------------------------------------------------------- */

.gateway-danger-banner {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    margin-bottom: var(--space-6);
    border: 1px solid var(--danger-border);
    border-radius: var(--radius-md);
    background: var(--danger-surface);
    color: var(--danger-text);
    font-size: var(--text-sm);
}

.gateway-danger-banner p { margin: 0; }

/* 12.3 Gateway cards ---------------------------------------------------------- */

.gateway-cards {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    margin-bottom: var(--space-8);
}

.gateway-card {
    padding: var(--space-5);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--card-bg);
    transition: border-color var(--duration) var(--ease), box-shadow var(--duration) var(--ease);
}

.gateway-card--on { border-color: var(--success-border); }

.gateway-card__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    margin-bottom: var(--space-3);
}

.gateway-card__info {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

.gateway-card__name {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0;
    font-size: var(--text-lg);
    font-weight: 700;
}

.gateway-card__description {
    margin: 0 0 var(--space-3);
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.gateway-card__tags {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}

.gateway-status {
    display: inline-flex;
    align-items: center;
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.gateway-status--on {
    background: var(--success-surface);
    color: var(--success-text);
}

.gateway-status--off {
    background: var(--surface-2, var(--neutral-100));
    color: var(--text-muted);
}

/* 12.4 Toggle switch ---------------------------------------------------------- */

.gateway-switch {
    position: relative;
    display: inline-flex;
    align-items: center;
    width: 2.75rem;
    height: 1.5rem;
    padding: 0;
    border: none;
    border-radius: var(--radius-pill);
    background: var(--border-strong);
    cursor: pointer;
    transition: background var(--duration) var(--ease);
    /* Tap target: 44x44px hit area (WCAG 2.5.5) */
    min-width: var(--tap-target, 44px);
    min-height: var(--tap-target, 44px);
    justify-content: center;
}

.gateway-switch:focus-visible {
    outline: 2px solid var(--primary-600);
    outline-offset: 2px;
}

.gateway-switch__track {
    position: relative;
    width: 2.25rem;
    height: 1.125rem;
    border-radius: var(--radius-pill);
    background: var(--neutral-200);
    transition: background var(--duration) var(--ease);
}

.gateway-switch__thumb {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 0.875rem;
    height: 0.875rem;
    border-radius: 50%;
    background: var(--neutral-0);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
    transition: transform var(--duration) var(--ease);
}

.gateway-switch.is-on { background: var(--success-text); }
.gateway-switch.is-on .gateway-switch__track { background: rgba(255, 255, 255, 0.3); }
.gateway-switch.is-on .gateway-switch__thumb { transform: translateX(0.75rem); }

/* 12.5 Settings panel -------------------------------------------------------- */

.gateway-settings {
    margin-top: var(--space-4);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.gateway-settings__toggle {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-3) var(--space-4);
    border: none;
    background: var(--surface-2, var(--neutral-50));
    color: var(--text);
    font-size: var(--text-sm);
    font-weight: 600;
    cursor: pointer;
    text-align: left;
    transition: background var(--duration) var(--ease);
}

.gateway-settings__toggle:hover { background: var(--neutral-100); }
.gateway-settings__toggle:focus-visible { outline: 2px solid var(--primary-600); outline-offset: -2px; }

.gateway-settings[open] .gateway-settings__toggle { border-bottom: 1px solid var(--border); }

.gateway-settings__body { padding: var(--space-5); }

.gateway-settings__fieldset {
    border: none;
    padding: 0;
    margin: 0 0 var(--space-5);
}

.gateway-settings__fieldset > legend {
    font-size: var(--text-sm);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
    margin-bottom: var(--space-3);
}

.gateway-settings__actions {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-4);
    padding-top: var(--space-4);
    border-top: 1px solid var(--border);
}

.gateway-settings__saved {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--success-text);
}

/* 12.6 Audit table ------------------------------------------------------------ */

.gateway-audit {
    margin-top: var(--space-10);
}

.table--audit td,
.table--audit th {
    padding: var(--space-3) var(--space-4);
    font-size: var(--text-sm);
}

/* 12.7 Audit diff modal ------------------------------------------------------- */

.audit-diff {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-4);
}

.audit-diff__col h4 { margin: 0 0 var(--space-2); font-size: var(--text-sm); text-transform: uppercase; letter-spacing: 0.06em; }
.audit-diff__row {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-2);
    padding: var(--space-2) 0;
    border-bottom: 1px solid var(--border);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
}

.audit-diff__key { font-weight: 600; }
.audit-diff__old { color: var(--danger-text); }
.audit-diff__new { color: var(--success-text); }

/* 12.8 Toast container -------------------------------------------------------- */

/*
 * Bottom-right toast stack. Uses CSS place-items so it auto-stacks vertically.
 * Animations respect prefers-reduced-motion (WCAG 2.2).
 */
#toast-container {
    position: fixed;
    z-index: 99999;
    bottom: var(--space-6);
    right: var(--space-6);
    display: grid;
    place-items: end;
    gap: var(--space-3);
    pointer-events: none;
}

.toast {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    min-width: 280px;
    max-width: 420px;
    border-radius: var(--radius-lg);
    background: var(--neutral-800);
    color: var(--neutral-0);
    font-size: var(--text-sm);
    font-weight: 600;
    box-shadow: var(--shadow-md);
    pointer-events: auto;
    animation: toast-in var(--duration) var(--ease) both;
}

.toast.is-leaving { animation: toast-out var(--duration) var(--ease) both; }

.toast--success { border-left: 4px solid var(--success-solid); }
.toast--error   { border-left: 4px solid var(--danger-solid); }

.toast__msg { flex: 1; }
.toast__msg p { margin: 0; }

.toast__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--neutral-300);
    cursor: pointer;
    transition: color var(--duration), background var(--duration);
    pointer-events: auto;
}
.toast__close:hover { color: var(--neutral-0); background: var(--neutral-700); }

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

@keyframes toast-out {
    from { opacity: 1; transform: translateX(0); }
    to   { opacity: 0; transform: translateX(100%); }
}

@media (max-width: 640px) {
    #toast-container { inset: auto; bottom: var(--space-4); left: var(--space-4); right: var(--space-4); place-items: end center; }
    .toast { min-width: unset; width: 100%; max-width: 100%; }
}

/* 12.9 Accessibility --------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    .toast,
    .toast.is-leaving { animation: none; }
    .gateway-switch.is-on .gateway-switch__thumb { transition: none; }
}

@media (forced-colors: active) {
    .gateway-switch { border: 2px solid CanvasText; }
    .gateway-switch.is-on { border-color: Highlight; }
    .gateway-summary__tile--on { border: 2px solid Highlight; }
}

@media (max-width: 900px) {
    .table--audit th:last-child,
    .table--audit td:last-child { display: none; }
}

