/* ================================================================
   PRODUCT FILTER & SHOP LAYOUT
   All values reference design tokens from style.css
   ================================================================ */

/* ── Shop banner ──────────────────────────────────────────────
   Rotating YouTube background (playlist cycled by product-filter.js),
   dimmed by a scrim so the title stays readable over whatever the
   current frame looks like. True full-bleed — extends up behind the
   fixed utility bar + nav instead of just sitting flush below them, the
   same "hero fills behind the header" treatment the homepage already
   uses (see body.home in main.css). --header-h mirrors whatever body's
   own padding-top is at each breakpoint (main.css); pulling the banner
   up by that amount and padding its content back down by the same
   amount keeps "Shop" positioned exactly where it was, just with real
   banner (video) behind the header instead of the page's flat
   background color showing through there. */

.shop-page {
    padding-top: 0;
    /* Contains the banner's negative top margin below so it doesn't
       collapse through and drag the whole page up with it — .shop-page
       is main's own element and has no padding/border of its own to stop
       that collapse otherwise. */
    display: flow-root;
}

.shop-banner {
    --header-h: calc(var(--utility-bar-h) + var(--mobile-brand-bar-h));
    position: relative;
    margin-top: calc(-1 * var(--header-h));
    padding-top: var(--header-h);
    height: calc(clamp(220px, 34vw, 380px) + var(--header-h));
    background: var(--color-navy-dark);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

@media (min-width: 768px) {
    .shop-banner {
        --header-h: calc(var(--utility-bar-h) + var(--nav-h) + var(--sp-4) * 2);
    }
}

/* Before the YouTube API swaps it for an iframe, this is a plain mount
   div — after, YT.Player() replaces it outright with an <iframe> that
   inherits this same class/id rather than nesting inside it, so the
   sizing rule below has to target the class directly, not as a
   descendant. 16:9-cover trick, oversized a further ~18% beyond a plain
   cover fit: partly so the banner is never letterboxed at any aspect
   ratio, partly so YouTube's own corner watermark/UI chrome (still
   present even with controls=0 — the API doesn't allow fully removing
   it) gets pushed outside the cropped, visible area instead of poking
   into a corner. */
.shop-banner__video {
    position: absolute;
    top: 50%;
    left: 50%;
    width: calc(177.78vh * 1.18);
    height: calc(56.25vw * 1.18);
    min-width: 118%;
    min-height: 118%;
    transform: translate(-50%, -50%);
    pointer-events: none;
    /* Hidden by default — covers both the native play-button/thumbnail
       YouTube briefly shows before playback actually starts, and the
       buffering spinner it'd otherwise show mid-swap between videos.
       product-filter.js adds .is-visible only once a video is actually
       PLAYING (or, under reduced-motion, once the first frame is ready),
       so what the visitor sees is a soft crossfade on the navy background
       instead of either of those. */
    opacity: 0;
    transition: opacity 0.9s ease;
}

.shop-banner__video.is-visible { opacity: 1; }

.shop-banner__scrim {
    position: absolute;
    inset: 0;
    background: rgba(7, 25, 41, 0.55);
}

.shop-banner__content {
    position: relative;
    z-index: 1;
    padding: var(--sp-6);
    text-align: center;
}

.shop-banner__eyebrow {
    font-size: var(--text-xs);
    font-weight: var(--fw-bold);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--color-blue-light);
    margin-bottom: var(--sp-2);
}

.shop-banner__title {
    font-size: clamp(2.5rem, 7vw, 4.5rem);
    font-weight: var(--fw-black);
    letter-spacing: var(--ls-display);
    color: var(--color-white);
    line-height: var(--lh-tight);
}

@media (min-width: 768px) {
    .shop-banner__content { padding: var(--sp-8) var(--sp-8) var(--sp-6); }
}

/* ── Brand strip ──────────────────────────────────────────────────
   Real brand tiles (16:9 photo + wordmark, assets/images/brand-strip/).
   Scrolls horizontally rather than wrapping if it doesn't fit; on a wide
   enough screen all 9 stretch to share the row evenly with no scroll. */

.shop-brand-strip {
    display: flex;
    gap: var(--sp-3);
    margin-top: var(--sp-5);
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.shop-brand-strip::-webkit-scrollbar { display: none; }

.shop-brand-strip__item {
    flex: 0 0 auto;
    scroll-snap-align: start;
    width: 128px;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: var(--r-md);
    box-shadow: var(--shadow-sm);
    transition: transform var(--t-spring), box-shadow var(--t-fast);
}

.shop-brand-strip__item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform var(--t-slow);
}

.shop-brand-strip__item:hover {
    box-shadow: var(--shadow-card-hover);
}

.shop-brand-strip__item:hover img {
    transform: scale(1.06);
}

.shop-brand-strip__item:active {
    transform: scale(0.96);
    transition: transform var(--t-press);
}

@media (min-width: 900px) {
    .shop-brand-strip {
        overflow-x: visible;
    }

    .shop-brand-strip__item {
        flex: 1 1 0;
        width: auto;
        min-width: 0;
    }
}

/* ── Toolbar ──────────────────────────────────────────────────── */

.shop-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3) var(--sp-4);
    padding-top: var(--sp-6);
    margin-bottom: var(--sp-6);
}

.result-count {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    white-space: nowrap;
}

.shop-toolbar__controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-3);
    flex-shrink: 0;
    /* Keeps this right-aligned whether it shares the row with
       .result-count or, on a narrow phone, wraps onto its own line
       below it — plain justify-content:space-between only affects
       items still sharing a line. */
    margin-left: auto;
}

/* Longest sort option ("Name: 0-9, A-Z") could otherwise push this
   past the edge of a narrow phone screen and force the whole toolbar
   into horizontal overflow. */
.shop-sort {
    max-width: 100%;
    text-overflow: ellipsis;
}

@media (max-width: 374px) {
    .shop-sort { max-width: 46vw; }
}

/* Filter toggle button (always visible; hides on ≥1024px) */
.filter-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-2) var(--sp-4);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--r-full);
    font-family: var(--font);
    font-size: var(--text-sm);
    font-weight: var(--fw-medium);
    color: var(--color-text);
    cursor: pointer;
    transition: border-color var(--t-fast), background var(--t-fast);
}

.filter-toggle:hover { border-color: var(--color-blue); }
.filter-toggle:active { transform: scale(0.96); transition: transform var(--t-press); }

@media (min-width: 1024px) { .filter-toggle { display: none; } }

.active-filter-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.25rem;
    height: 1.25rem;
    padding-inline: var(--sp-1);
    background: var(--color-blue);
    color: var(--color-white);
    border-radius: var(--r-full);
    font-size: 0.625rem;
    font-weight: var(--fw-bold);
}

/* Sort dropdown */
.shop-sort {
    appearance: none;
    padding: var(--sp-2) var(--sp-8) var(--sp-2) var(--sp-3);
    background: var(--color-surface)
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%230B2540' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E")
        no-repeat right var(--sp-3) center;
    border: 1px solid var(--color-border);
    border-radius: var(--r-full);
    font-family: var(--font);
    font-size: var(--text-sm);
    color: var(--color-text);
    cursor: pointer;
    transition: border-color var(--t-fast);
}

.shop-sort:focus { outline: none; border-color: var(--color-blue); }

/* ── Shop layout: sidebar + grid ─────────────────────────────── */

.shop-layout {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--sp-8);
    align-items: start;
    position: relative;
}

@media (min-width: 1024px) {
    .shop-layout {
        grid-template-columns: 260px 1fr;
    }

    /* Explicit placement — once the sidebar goes position:fixed to pin
       itself (see product-filter.js), it's out-of-flow and grid
       auto-placement would otherwise slide .products-area into its now-
       empty first track instead of leaving it in the second. */
    .filter-column { grid-column: 1; }
    .products-area { grid-column: 2; }
}

/* ── Filter column (accuracy notice + sidebar) ───────────────────── */

.filter-column {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
}

/* Small heads-up above the filter box — plain flow, so it scrolls away
   normally once the sidebar itself pins; it only needs to be seen once,
   not permanently occupy space in the pinned box. Soft/informational,
   not a warning — pairs with the same blue-subtle tone used for "active"
   states elsewhere (filter pills, focused price inputs) rather than an
   alarming yellow/red. */
.filter-notice {
    display: flex;
    align-items: flex-start;
    gap: var(--sp-2);
    padding: var(--sp-3);
    background: var(--color-blue-subtle);
    border-radius: var(--r-md);
    font-size: var(--text-xs);
    line-height: var(--lh-normal);
    color: var(--color-navy);
}

.filter-notice svg {
    flex-shrink: 0;
    width: 15px;
    height: 15px;
    margin-top: 1px;
    color: var(--color-blue);
}

/* ── Filter sidebar ───────────────────────────────────────────── */

/* One single card holding every filter row, divided by hairlines rather
   than each filter being its own separate floating card. */
.filter-sidebar {
    background: var(--color-surface);
    border-radius: var(--r-xl);
    box-shadow: var(--shadow-sm);
}

/* Desktop: pinned in place (via JS, not CSS position:sticky — the
   sitewide overflow-x:hidden on <html> silently defeats native sticky in
   Chromium, same issue already worked around on the About page) so it
   stays in view while only the product grid scrolls past it — see
   product-filter.js. */
@media (min-width: 1024px) {
    .filter-sidebar.is-pinned,
    .filter-sidebar.is-released {
        overflow-y: auto;
    }

    .filter-sidebar.is-pinned {
        z-index: var(--z-dropdown);
    }
}

/* Mobile: slide-out drawer */
@media (max-width: 1023px) {
    .filter-sidebar {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        width: min(320px, 85vw);
        border-radius: 0 var(--r-2xl) var(--r-2xl) 0;
        box-shadow: var(--shadow-xl);
        z-index: var(--z-modal);
        transform: translateX(-100%);
        transition: transform var(--t-base);
        overflow-y: auto;
    }

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

.filter-sidebar__inner {
    padding: var(--sp-5);
    display: flex;
    flex-direction: column;
}

/* Wrapper JS appends the generated attribute-filter cards into — no gap
   of its own, since every row (static or dynamic) shares one continuous
   divided list rather than sitting in separate spaced-out cards. */
#dynamic-filters {
    display: flex;
    flex-direction: column;
}

#dynamic-filters .filter-dropdown:last-child { border-bottom: none; }

.filter-sidebar__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-bottom: var(--sp-4);
    margin-bottom: var(--sp-1);
    border-bottom: 1px solid var(--color-border);
}

.filter-sidebar__heading {
    font-size: var(--text-md);
    font-weight: var(--fw-bold);
    color: var(--color-navy);
}

.filter-close {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: var(--r-full);
    color: var(--color-text-muted);
    transition: background var(--t-fast), color var(--t-fast);
}

.filter-close:hover { background: var(--color-gray-100); color: var(--color-text); }

@media (min-width: 1024px) { .filter-close { display: none; } }

/* ── Dual price range slider ──────────────────────────────────── */

.price-range { display: flex; flex-direction: column; gap: var(--sp-4); }

.price-range__slider {
    position: relative;
    height: 36px;
    display: flex;
    align-items: center;
}

.price-range__track,
.price-range__fill {
    position: absolute;
    left: 0;
    right: 0;
    height: 4px;
    border-radius: var(--r-full);
    pointer-events: none;
}

.price-range__track { background: var(--color-gray-200); }

.price-range__fill {
    background: var(--color-blue);
    /* left + width set inline by JS */
}

.price-range__thumb {
    position: absolute;
    width: 100%;
    height: 4px;
    appearance: none;
    background: transparent;
    pointer-events: none;
    outline: none;
}

.price-range__thumb::-webkit-slider-thumb {
    appearance: none;
    width: 20px;
    height: 20px;
    border-radius: var(--r-full);
    background: var(--color-white);
    border: 2.5px solid var(--color-blue);
    box-shadow: var(--shadow-sm);
    cursor: grab;
    pointer-events: all;
    transition: box-shadow var(--t-fast), transform var(--t-spring);
}

.price-range__thumb::-moz-range-thumb {
    width: 20px;
    height: 20px;
    border-radius: var(--r-full);
    background: var(--color-white);
    border: 2.5px solid var(--color-blue);
    box-shadow: var(--shadow-sm);
    cursor: grab;
    pointer-events: all;
}

.price-range__thumb::-webkit-slider-thumb:hover,
.price-range__thumb:focus::-webkit-slider-thumb {
    box-shadow: 0 0 0 6px var(--color-blue-subtle);
    transform: scale(1.1);
}

.price-range__vals {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
}

.price-range__sep {
    color: var(--color-text-muted);
    flex-shrink: 0;
}

.price-input {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1px;
    flex: 1;
    min-width: 0;
    padding: var(--sp-1) var(--sp-2);
    background: var(--color-bg);
    border: 1.5px solid var(--color-border);
    border-radius: var(--r-md);
    transition: border-color var(--t-fast);
}

.price-input:focus-within { border-color: var(--color-blue); }

.price-input__currency {
    font-size: 0.625rem;
    font-weight: var(--fw-bold);
    color: var(--color-text-muted);
    flex-shrink: 0;
    letter-spacing: 0.04em;
}

.price-input input[type="number"] {
    width: 100%;
    min-width: 0;
    border: none;
    background: none;
    font-family: var(--font);
    font-size: var(--text-xs);
    font-weight: var(--fw-semi);
    color: var(--color-navy);
    /* Firefox keeps default number-input padding/margin even with the
       reset above unless explicitly zeroed here too. */
    padding: 0;
    margin: 0;
}

.price-input input[type="number"]:focus { outline: none; }

/* Hide the native spinner arrows — a slider already sits right above
   these, so the stepper buttons are redundant and cramp the box. */
.price-input input[type="number"]::-webkit-outer-spin-button,
.price-input input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.price-input input[type="number"] {
    appearance: textfield;
    -moz-appearance: textfield;
}

/* ── Filter pills ─────────────────────────────────────────────────
   Gender's always-visible pill row, and the same pill treatment reused
   inside every attribute dropdown below (Band Type, Case Material, Case
   Size, Dial Color, Movement, Watch Type) — one consistent "tap to
   toggle, highlight on select" control everywhere instead of checkbox
   rows for attributes and pills for gender. */

.filter-pills {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
}

.filter-pills--swatches { gap: var(--sp-3); }

.filter-pill {
    padding: var(--sp-2) var(--sp-3);
    background: var(--color-gray-100);
    border: 1.5px solid transparent;
    border-radius: var(--r-full);
    font-family: var(--font);
    font-size: var(--text-sm);
    font-weight: var(--fw-medium);
    color: var(--color-text-muted);
    cursor: pointer;
    transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
    line-height: 1;
}

.filter-pill:hover {
    border-color: var(--color-blue);
    color: var(--color-navy);
}

.filter-pill:active {
    transform: scale(0.95);
    transition: transform var(--t-press);
}

.filter-pill.is-active {
    background: var(--color-blue-subtle);
    border-color: var(--color-blue);
    color: var(--color-navy);
    font-weight: var(--fw-semi);
}

/* Color terms — a plain swatch circle instead of a text pill; the color
   itself is the label, so a name alongside it would be redundant. Sized
   up a little from the gender/attribute pill's line-height so the circle
   reads clearly rather than looking like a tiny dot. */
.filter-pill--swatch {
    width: 30px;
    height: 30px;
    padding: 0;
    border-radius: var(--r-full);
    border: 2px solid var(--color-white);
    box-shadow: 0 0 0 1.5px var(--color-border);
    background-clip: padding-box;
}

.filter-pill--swatch:hover {
    box-shadow: 0 0 0 1.5px var(--color-blue);
}

.filter-pill--swatch.is-active {
    border-color: var(--color-white);
    box-shadow: 0 0 0 2px var(--color-blue);
}

/* ── Filter dropdowns ─────────────────────────────────────────────
   Every filter (Price, Gender, and every attribute — Movement, Dial
   Color, Case Material, Band Type, Watch Type, Case Size) is a row in
   one continuous list, divided by hairlines rather than each sitting in
   its own separate card — one line of label + chevron until opened. */

.filter-dropdown {
    padding: var(--sp-4) 0;
    border-bottom: 1px solid var(--color-border);
}

.filter-dropdown.is-open .filter-dropdown__label { color: var(--color-blue); }

.filter-dropdown__toggle {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    width: 100%;
    padding: 0;
    background: none;
    border: none;
    font-family: var(--font);
    cursor: pointer;
    text-align: left;
}

.filter-dropdown__label {
    font-size: var(--text-sm);
    font-weight: var(--fw-bold);
    color: var(--color-navy);
}

.filter-dropdown__value {
    margin-left: auto;
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 40%;
}

.filter-dropdown.is-open .filter-dropdown__value { color: var(--color-blue); }

.filter-dropdown__chevron {
    width: 14px;
    height: 14px;
    color: var(--color-text-muted);
    transition: transform var(--t-base);
    flex-shrink: 0;
}

.filter-dropdown.is-open .filter-dropdown__chevron { transform: rotate(180deg); }

.filter-dropdown__panel {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows var(--t-base);
}

.filter-dropdown__panel > div {
    overflow: hidden;
}

.filter-dropdown.is-open .filter-dropdown__panel {
    grid-template-rows: 1fr;
}

.filter-dropdown__panel > div > * {
    padding-top: var(--sp-4);
}

/* ── Mobile sidebar footer ────────────────────────────────────── */

.filter-sidebar__footer {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    padding-top: var(--sp-4);
    border-top: 1px solid var(--color-border);
}

@media (min-width: 1024px) { .filter-sidebar__footer { display: none; } }

.btn-apply {
    padding: var(--sp-3) var(--sp-4);
    background: var(--color-navy);
    color: var(--color-white);
    border-radius: var(--r-lg);
    font-family: var(--font);
    font-weight: var(--fw-bold);
    font-size: var(--text-sm);
    cursor: pointer;
    transition: background var(--t-fast);
}

.btn-apply:hover { background: var(--color-navy-light); }
.btn-apply:active { transform: scale(0.97); transition: transform var(--t-press); }

.btn-reset {
    padding: var(--sp-3) var(--sp-4);
    background: transparent;
    color: var(--color-text-muted);
    border-radius: var(--r-lg);
    font-family: var(--font);
    font-weight: var(--fw-medium);
    font-size: var(--text-sm);
    cursor: pointer;
    border: 1px solid var(--color-border);
    transition: border-color var(--t-fast), color var(--t-fast);
}

.btn-reset:hover { border-color: var(--color-gray-500); color: var(--color-text); }
.btn-reset:active { transform: scale(0.97); transition: transform var(--t-press); }

/* ── Mobile overlay ───────────────────────────────────────────── */

.filter-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: var(--color-overlay);
    z-index: calc(var(--z-modal) - 1);
    opacity: 0;
    transition: opacity var(--t-base);
}

.filter-overlay.is-visible {
    display: block;
    opacity: 1;
}

/* ── Products grid ────────────────────────────────────────────── */

.products-area {
    display: flex;
    flex-direction: column;
    gap: var(--sp-8);
    min-width: 0;
}

.products-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--sp-4);
}

@media (min-width: 640px)  { .products-grid { grid-template-columns: repeat(2, 1fr); gap: var(--sp-5); } }
@media (min-width: 900px)  { .products-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1280px) { .products-grid { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1024px) and (max-width: 1279px) {
    /* Sidebar present — 3 cols max in that viewport range */
    .shop-layout .products-grid { grid-template-columns: repeat(3, 1fr); }
}

/* .product-card and its skeleton state now live in product-card.css —
   shared sitewide (shop grid, homepage, related products, cart
   cross-sell) rather than duplicated per page type. */

/* ── Infinite scroll loading indicator ───────────────────────────
   A small clock face — ticking hour + minute hands — fits a watch shop
   better than a generic spinner. Shown while a background page fetch is
   topping up the buffer; see the proactive scroll-buffer loader in
   product-filter.js. */

.load-more-spinner {
    display: flex;
    justify-content: center;
    padding: var(--sp-6) 0;
    color: var(--color-navy);
}

.load-more-spinner__clock {
    width: 36px;
    height: 36px;
}

.load-more-spinner__hand { transform-origin: 24px 24px; }
.load-more-spinner__hand--hour   { animation: clock-tick 3s   linear infinite; }
.load-more-spinner__hand--minute { animation: clock-tick 1.1s linear infinite; }

@keyframes clock-tick {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .load-more-spinner__hand { animation: none; }
}

.no-more-label {
    text-align: center;
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    padding: var(--sp-4) 0;
}
