/* ================================================================
   PRODUCT SINGLE PAGE
   Mobile-first. Sticky add-to-cart bar replaces the bottom tab bar
   on this page type (main.css hides .tab-bar via body.single-product
   below) so there's one clear, uncluttered call to action.
   ================================================================ */

.product-page {
    padding-bottom: var(--sp-12);
}

/* ── Breadcrumb ───────────────────────────────────────────────── */

.product-breadcrumb {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-1);
    padding-block: var(--sp-4);
    font-size: var(--text-xs);
    color: var(--color-text-muted);
}

.product-breadcrumb a {
    color: var(--color-text-muted);
    transition: color var(--t-fast);
}

.product-breadcrumb a:hover { color: var(--color-blue); }

.product-breadcrumb__sep { opacity: 0.5; }

.product-breadcrumb__current {
    color: var(--color-text);
    font-weight: var(--fw-medium);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 40vw;
}

/* ── Layout ───────────────────────────────────────────────────── */

.product-layout {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--sp-8);
}

@media (min-width: 900px) {
    .product-layout {
        grid-template-columns: 1.1fr 1fr;
        gap: var(--sp-12);
        /* Default (stretch), not start — .product-gallery opts back out
           below via align-self so its own sticky pin range is unaffected;
           this is what lets .product-info stretch to match IT when the
           image is the taller of the two (see .product-tabs/.product-specs
           flex:1 below — that's what actually consumes the extra height,
           so the specs card's bottom lines up with the image's bottom
           instead of ending well short of it). */
    }
}

/* Grid items default to a min-width of "auto" (their content's
   min-content size), not 0 — normally invisible, but the trust strip's
   negative-margin bleed (.product-trust__row) inflates this column's
   min-content contribution enough to blow the gallery column down to
   almost nothing. min-width: 0 makes this column respect the 1fr
   track sizing instead of fighting it. */
.product-info {
    min-width: 0;
    display: flex;
    flex-direction: column;
}

/* Opts out of the row's default stretch — the image should stay its
   own natural square size (never taller than its content) so there's
   actual scroll room for position:sticky to do anything. When
   .product-info is the shorter column, IT is what stretches instead
   (the default above), with .product-tabs (flex:1 below) absorbing
   the extra height. */
.product-gallery {
    align-self: start;
}

/* ================================================================
   GALLERY — native scroll-snap swipe, no JS needed for the motion
   itself (JS only syncs dots/thumbs). Real touch momentum beats a
   hand-rolled crossfade here.
   ================================================================ */

.product-gallery {
    position: sticky;
    top: calc(var(--utility-bar-h) + var(--nav-h) + var(--sp-4));
}

/* ── "Personal touch" ambient glow ──────────────────────────────
   --accent-1/--accent-2 come from THIS product's own dial color and
   case/band finish (single-product.php) — two flat, heavily blurred
   circles, not a gradient (standing rule): softness comes from the
   blur filter, not a color-to-color blend. Falls back to fully
   transparent when a product has no color data, so it's invisible
   rather than wrong on products we couldn't extract a color for. */
.product-gallery::before,
.product-gallery::after {
    content: "";
    position: absolute;
    width: 50%;
    aspect-ratio: 1;
    border-radius: 50%;
    filter: blur(70px);
    opacity: 0.22;
    z-index: 0;
    pointer-events: none;
}

.product-gallery::before {
    background: var(--accent-1, transparent);
    top: -8%;
    left: -8%;
}

.product-gallery::after {
    background: var(--accent-2, transparent);
    bottom: -8%;
    right: -8%;
}

.product-gallery__scroller,
.product-gallery__dots,
.product-gallery__thumbs {
    position: relative;
    z-index: 1;
}

/* Was previously full-bleed edge-to-edge (negative margin, square
   corners) — for a 390px-wide phone screen that meant the source photo
   got stretched across the full device width, which shows every soft/
   low-res supplier photo at its worst. Framed and capped narrower
   instead: less upscaling for the same photo, and it reads as a
   deliberately-sized product shot instead of a stretched hero image. */
@media (max-width: 899px) {
    .product-gallery {
        /* Not static — this is still the containing block for its own
           ::before/::after ambient glow (position:absolute, offset via
           %, blurred 70px past that). Without a positioning context
           here, they escaped to a much larger ancestor instead, landing
           far outside this now-small card and adding real horizontal
           overflow to the whole page (confirmed live: this exact rule
           was the one thing that, when removed, brought
           document.documentElement.scrollWidth back down to the true
           viewport width). Desktop already uses sticky for the same
           reason, just for a different purpose (the scroll-pin), so
           this bug never showed up there.

           top must be reset too — the base rule's top: calc(utility-bar
           + nav + sp-4) (~112px) only meant something under sticky; a
           relatively positioned element still honors top as a real
           offset from its normal spot, so without resetting it the
           gallery rendered ~112px lower than it should, with a big
           empty gap above it — confirmed live, that exact number. */
        position: relative;
        top: auto;
        max-width: min(320px, 100%);
        margin-inline: auto;
    }
}

.product-gallery__scroller {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    -ms-overflow-style: none;
    border-radius: var(--r-xl);
    /* Plain white — see product-card.css's __img-wrap for why (the
       background-removal pass' edge fringe blends into white but
       shows as a halo against gray). */
    background: var(--color-white);
    position: relative;
}

.product-gallery__scroller::-webkit-scrollbar { display: none; }

.product-gallery__slide {
    flex: 0 0 100%;
    scroll-snap-align: start;
    /* Taller than square — brings the gallery's own height closer to
       the info column's (brand/title/price/actions/trust/specs) so the
       two sides read as one balanced layout instead of a short square
       photo next to a much taller text column. */
    aspect-ratio: 4 / 5;
    display: flex;
    align-items: center;
    justify-content: center;
    /* The img's parallax transform (scale + translateY) paints beyond
       its own box on all sides — without clipping that here, the
       scaled-up pixels extend past the slide's right edge and the
       scroller's overflow-x:auto treats that extra painted area as
       real scrollable content, letting a single-photo product scroll
       sideways into empty space that was never meant to be reachable. */
    overflow: hidden;
}

/* On mobile the gallery and info are stacked, not side-by-side, so the
   4:5 "match the info column's height" reasoning above doesn't apply —
   it just ate over half the screen and pushed brand/price/model past
   the fold. Square instead, now that the gallery itself is a smaller
   framed card (.product-gallery above) rather than full-bleed — keeps
   the photo substantial while leaving room to see it, the price and
   the Add to Cart button together without scrolling. */
@media (max-width: 899px) {
    .product-gallery__slide {
        aspect-ratio: 1;
        height: auto;
        max-height: 320px;
    }
}

.product-gallery__slide img {
    width: 100%;
    height: 100%;
    /* contain, not cover — the product page is the one place a shopper
       actually decides whether to buy, so the whole watch (full strap,
       both lug ends) needs to actually be there, even though source
       photos come from many suppliers with inconsistent margins and so
       won't all read at quite the same apparent size. product-card.css
       keeps its own __img on cover deliberately — the small grid photo
       everywhere else on the site — this override only touches the
       single-product gallery. */
    object-fit: contain;
    object-position: center;
    /* Parallax drift only, no scale — see product-single.js's PARALLAX
       section, which writes --parallax-y on scroll (±30px). Defaults
       to 0 so the image sits still until JS is ready (and stays still
       entirely under prefers-reduced-motion). The old scale(1.15) was
       overscan to cover this same swing without exposing background at
       the edge, which only mattered under cover's edge-to-edge crop —
       contain already frames the photo with margin, so there's nothing
       left to expose and scaling would just zoom back in on the watch. */
    transform: translateY(var(--parallax-y, 0px));
}

.product-gallery__badge {
    position: absolute;
    top: var(--sp-4);
    left: var(--sp-4);
    background: var(--color-blue);
    color: var(--color-white);
    font-size: var(--text-xs);
    font-weight: var(--fw-bold);
    padding: var(--sp-1) var(--sp-3);
    border-radius: var(--r-md);
    z-index: 2;
}

.product-gallery__dots {
    display: flex;
    justify-content: center;
    gap: var(--sp-2);
    padding-block: var(--sp-3);
}

@media (min-width: 900px) { .product-gallery__dots { display: none; } }

.product-gallery__dot {
    width: 6px;
    height: 6px;
    border-radius: var(--r-full);
    background: var(--color-gray-300);
    transition: background var(--t-fast), width var(--t-base);
}

.product-gallery__dot.is-active {
    background: var(--color-blue);
    width: 18px;
}

.product-gallery__thumbs {
    display: none;
}

@media (min-width: 900px) {
    .product-gallery__thumbs {
        display: flex;
        gap: var(--sp-3);
        margin-top: var(--sp-3);
    }
}

.product-gallery__thumb {
    width: 64px;
    height: 64px;
    flex-shrink: 0;
    border-radius: var(--r-md);
    overflow: hidden;
    background: var(--color-white);
    border: 1.5px solid transparent;
    transition: border-color var(--t-fast), transform var(--t-press);
}

.product-gallery__thumb img { width: 100%; height: 100%; object-fit: cover; object-position: center; }
.product-gallery__thumb:hover { border-color: var(--color-gray-300); }
.product-gallery__thumb.is-active { border-color: var(--color-blue); }
.product-gallery__thumb:active { transform: scale(0.94); }

/* ================================================================
   INFO PANEL
   ================================================================ */

.product-info__brand-row {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin-bottom: var(--sp-2);
}

.product-info__brand {
    display: inline-block;
    font-size: var(--text-xs);
    font-weight: var(--fw-bold);
    color: var(--color-blue);
    text-transform: uppercase;
    letter-spacing: var(--ls-wide);
    transition: color var(--t-fast);
}

/* This product's own two accent colors, quietly — not a legend, just a
   little "this one's a green/black watch" cue next to the brand name. */
.product-info__accent-dots {
    display: inline-flex;
    gap: 3px;
}

.product-info__accent-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    border: 1px solid rgba(11, 37, 64, 0.10);
}

.product-info__brand:hover { color: var(--color-blue-dark); }

.product-info__title {
    font-size: clamp(var(--text-xl), 3vw, var(--text-2xl));
    font-weight: var(--fw-black);
    letter-spacing: var(--ls-display);
    line-height: var(--lh-tight);
    color: var(--color-text);
    margin-bottom: var(--sp-3);
}

.product-info__meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-3);
    margin-bottom: var(--sp-3);
}

.product-info__rating {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    transition: opacity var(--t-fast);
}

.product-info__rating:hover { opacity: 0.75; }

.product-info__rating .star-rating { color: var(--color-blue); }

.product-info__sku {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
}

.product-info__price {
    display: flex;
    align-items: baseline;
    gap: var(--sp-3);
    margin-bottom: var(--sp-3);
    flex-wrap: wrap;
}

.product-info__price-current {
    font-size: var(--text-2xl);
    font-weight: var(--fw-black);
    color: var(--color-text);
}

.product-info__price-current--sale { color: var(--color-blue-dark); }

.product-info__price-regular {
    font-size: var(--text-md);
    color: var(--color-gray-500);
    text-decoration: line-through;
}

.product-info__discount {
    background: var(--color-blue-subtle);
    color: var(--color-blue-dark);
    font-size: var(--text-xs);
    font-weight: var(--fw-bold);
    padding: 2px var(--sp-2);
    border-radius: var(--r-md);
}

.product-info__stock {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    font-size: var(--text-sm);
    font-weight: var(--fw-medium);
    margin-bottom: var(--sp-4);
}

.product-info__stock-dot {
    width: 7px;
    height: 7px;
    border-radius: var(--r-full);
    background: #22c55e;
    flex-shrink: 0;
}

.product-info__stock.is-out .product-info__stock-dot { background: #ef4444; }
.product-info__stock.is-in { color: #16a34a; }
.product-info__stock.is-out { color: #dc2626; }
.product-info__stock.is-low { color: #d97706; }
.product-info__stock.is-low .product-info__stock-dot { background: #f59e0b; }

.product-info__excerpt {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    line-height: var(--lh-relaxed);
    margin-bottom: var(--sp-6);
}

/* ── Variations ───────────────────────────────────────────────── */

.product-variation {
    margin-bottom: var(--sp-5);
}

.product-variation__label {
    display: flex;
    align-items: baseline;
    gap: var(--sp-2);
    font-size: var(--text-xs);
    font-weight: var(--fw-bold);
    color: var(--color-text);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: var(--sp-3);
}

.product-variation__value {
    text-transform: none;
    font-weight: var(--fw-medium);
    color: var(--color-text-muted);
    letter-spacing: normal;
}

.product-variation__options {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
}

.product-variation__pill {
    padding: var(--sp-2) var(--sp-4);
    background: var(--color-surface);
    border: 1.5px 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), color var(--t-fast), transform var(--t-press);
}

.product-variation__pill:hover { border-color: var(--color-blue); }
.product-variation__pill:active { transform: scale(0.96); }

.product-variation__pill.is-active {
    background: var(--color-navy);
    border-color: var(--color-navy);
    color: var(--color-white);
}

.product-variation__pill:disabled {
    opacity: 0.35;
    text-decoration: line-through;
    cursor: not-allowed;
    pointer-events: none;
}

.product-variation__swatch {
    width: 32px;
    height: 32px;
    border-radius: var(--r-full);
    border: 2px solid transparent;
    box-shadow: 0 0 0 1px var(--color-border);
    cursor: pointer;
    transition: transform var(--t-press), box-shadow var(--t-fast);
}

.product-variation__swatch:hover { transform: scale(1.1); }
.product-variation__swatch.is-active { box-shadow: 0 0 0 2px var(--color-surface), 0 0 0 4px var(--color-navy); }

/* ── Quantity + Add to cart ──────────────────────────────────── */

/* Mobile-first: qty+cart row, then a full-width Buy It Now below it —
   two buttons side by side on a phone screen get cramped fast. Desktop
   (900px+) has the room to put them on one row instead. */
.product-actions {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    margin-bottom: var(--sp-4);
}

.product-actions__row {
    display: flex;
    align-items: stretch;
    gap: var(--sp-3);
}

@media (min-width: 900px) {
    .product-actions {
        flex-direction: row;
        align-items: stretch;
    }

    .product-actions__row {
        flex: 1;
    }

    .buy-now {
        flex: 1;
        max-width: 220px;
    }
}

.product-qty {
    display: inline-flex;
    align-items: center;
    height: 3.25rem;
    background: var(--color-bg);
    border: 1.5px solid var(--color-border);
    border-radius: var(--r-full);
    flex-shrink: 0;
    padding-inline: 3px;
}

.product-qty__btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: calc(3.25rem - 6px);
    border-radius: var(--r-full);
    font-size: var(--text-lg);
    font-weight: var(--fw-semi);
    color: var(--color-text-muted);
    transition: background var(--t-fast), color var(--t-fast), transform var(--t-press);
}

.product-qty__btn:hover { background: var(--color-white); color: var(--color-navy); box-shadow: var(--shadow-sm); }
.product-qty__btn:active { transform: scale(0.88); }

.product-qty__val {
    min-width: 2.25rem;
    text-align: center;
    font-size: var(--text-md);
    font-weight: var(--fw-bold);
    color: var(--color-navy);
}

.product-add-to-cart {
    flex: 1;
    height: 3.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    padding-inline: var(--sp-4);
    min-width: 0;
    background: var(--color-blue);
    color: var(--color-white);
    border: none;
    border-radius: var(--r-full);
    font-family: var(--font);
    font-size: var(--text-sm);
    font-weight: var(--fw-bold);
    cursor: pointer;
    box-shadow: 0 8px 20px -6px rgba(38, 85, 194, 0.55);
    transition: background var(--t-fast), transform var(--t-press), box-shadow var(--t-base);
}

.product-add-to-cart__icon { display: flex; flex-shrink: 0; }
.product-add-to-cart__icon svg { width: 18px; height: 18px; }
.product-add-to-cart__label { white-space: nowrap; }

.product-add-to-cart:hover { background: var(--color-blue-dark); box-shadow: 0 10px 24px -6px rgba(38, 85, 194, 0.65); transform: translateY(-1px); }
.product-add-to-cart:active { transform: scale(0.97); }

.product-add-to-cart:disabled {
    background: var(--color-gray-300);
    color: var(--color-gray-600);
    cursor: not-allowed;
    box-shadow: none;
    transform: none;
}

.product-add-to-cart.is-loading { pointer-events: none; }
.product-add-to-cart .btn-spinner { display: none; width: 16px; height: 16px; border-radius: 50%; border: 2px solid rgba(255,255,255,0.4); border-top-color: #fff; animation: btn-spin 0.7s linear infinite; }
.product-add-to-cart.is-loading .btn-spinner { display: inline-block; }
.product-add-to-cart.is-loading .product-add-to-cart__icon,
.product-add-to-cart.is-loading .product-add-to-cart__label { display: none; }

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

/* ── Buy It Now — solid navy, same weight as Add to Cart but its own
   color so the two read as distinct actions rather than a
   primary/outline pair. Same add-to-cart call underneath, just goes
   straight to checkout after. ── */
.buy-now {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    height: 3.25rem;
    padding-inline: var(--sp-4);
    min-width: 0;
    background: var(--color-navy);
    color: var(--color-white);
    border: 1.5px solid var(--color-navy);
    border-radius: var(--r-full);
    font-family: var(--font);
    font-size: var(--text-sm);
    font-weight: var(--fw-bold);
    cursor: pointer;
    transition: background var(--t-fast), border-color var(--t-fast), transform var(--t-press), box-shadow var(--t-base);
}

.buy-now__icon { display: flex; flex-shrink: 0; }
.buy-now__icon svg { width: 16px; height: 16px; }
.buy-now__label { white-space: nowrap; }

.buy-now:hover { background: #0A1F38; box-shadow: 0 8px 20px -6px rgba(11, 37, 64, 0.5); transform: translateY(-1px); }
.buy-now:active { transform: scale(0.97); }

.buy-now:disabled {
    background: var(--color-gray-200);
    color: var(--color-gray-500);
    border-color: var(--color-gray-200);
    cursor: not-allowed;
    box-shadow: none;
    transform: none;
}

.buy-now.is-loading { pointer-events: none; }
.buy-now .btn-spinner { display: none; width: 16px; height: 16px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, 0.35); border-top-color: #fff; animation: btn-spin 0.7s linear infinite; }
.buy-now.is-loading .btn-spinner { display: inline-block; }
.buy-now.is-loading .buy-now__icon,
.buy-now.is-loading .buy-now__label { display: none; }

/* Compact variant inside the sticky mobile bar */
.product-sticky-bar__add,
.product-sticky-bar__buy-now {
    flex: 1;
    height: 2.75rem;
    padding-inline: var(--sp-4);
}

/* ── Wishlist (wcboost-wishlist plugin's own button) ────────────
   The plugin auto-inserts this right after the Add to Cart button —
   restyled here to match our pill/token system instead of its own
   plugin defaults. */
.wcboost-wishlist-button.wcboost-wishlist-single-button {
    display: flex !important;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    width: 100%;
    padding: var(--sp-3) var(--sp-4) !important;
    margin-top: var(--sp-3);
    background: var(--color-surface) !important;
    color: var(--color-navy) !important;
    border: 1.5px solid var(--color-border) !important;
    border-radius: var(--r-full) !important;
    font-family: var(--font) !important;
    font-size: var(--text-sm) !important;
    font-weight: var(--fw-semi) !important;
    transition: border-color var(--t-fast), background var(--t-fast), transform var(--t-press);
}

.wcboost-wishlist-button.wcboost-wishlist-single-button:hover {
    border-color: var(--color-blue) !important;
    color: var(--color-blue) !important;
    background: var(--color-blue-subtle) !important;
}

.wcboost-wishlist-button.wcboost-wishlist-single-button:active { transform: scale(0.98); }

/* ── WhatsApp enquiry ─────────────────────────────────────────── */

.product-whatsapp {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    width: 100%;
    padding: var(--sp-3);
    border: 1.5px solid #25D366;
    border-radius: var(--r-full);
    color: #128C4A;
    font-size: var(--text-sm);
    font-weight: var(--fw-semi);
    margin-bottom: var(--sp-4);
    transition: background var(--t-fast), transform var(--t-press);
}

.product-whatsapp svg { width: 18px; height: 18px; flex-shrink: 0; }
.product-whatsapp:hover { background: rgba(37, 211, 102, 0.08); }
.product-whatsapp:active { transform: scale(0.98); }

/* ── Trust badges ─────────────────────────────────────────────── */

/* Single line, sidescrollable — was a 2x2 grid; a horizontal strip
   reads faster (all 4 trust points visible/skimmable without stacking
   height) and the edge fade signals "more to scroll" without needing
   arrows or dots. Masked on the scrolling row itself so the fade
   blends into the box's own background rather than revealing the
   page behind it. */
.product-trust {
    padding: var(--sp-4);
    background: var(--color-bg);
    border-radius: var(--r-lg);
    overflow: hidden;
}

.product-trust__row {
    display: flex;
    align-items: center;
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
    margin-inline: calc(var(--sp-4) * -1);
    padding-inline: var(--sp-4);
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
    mask-image: linear-gradient(to right, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
}

.product-trust__row::-webkit-scrollbar { display: none; }

/* Each half of the duplicate set — see product-single.php's $copy
   loop and driftTrustRow() in product-single.js. */
.product-trust__set {
    display: flex;
    align-items: center;
    gap: var(--sp-6);
    flex-shrink: 0;
    padding-right: var(--sp-6);
}

.product-trust__item {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    font-size: var(--text-xs);
    font-weight: var(--fw-medium);
    color: var(--color-text-muted);
    line-height: var(--lh-tight);
    white-space: nowrap;
    flex-shrink: 0;
}

.product-trust__item svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    color: var(--color-blue);
}

/* ================================================================
   STICKY MOBILE ADD-TO-CART BAR
   Replaces the bottom tab bar on the product page — one clear CTA
   instead of two stacked bottom bars. Appears once the in-page
   Add to Cart button scrolls out of view (product-single.js).
   ================================================================ */

.product-sticky-bar {
    display: none;
    position: fixed;
    left: 0;
    /* Not bottom:0 — on this page (gallery + trust-strip + related-rail
       marquees all present together) position:fixed's containing block
       measures taller than the real screen, confirmed live: a bottom:0
       element's top landed at ~877px on an actual 812px-tall viewport,
       65px below the fold, invisible. 100vh itself measured correctly
       (812) even though that same containing block was wrong, so
       anchoring off vh instead of the inset side-steps the bug
       entirely: top:100vh puts this exactly at the TRUE bottom edge,
       then the same translateY slide used for the open/closed state
       just becomes the only transform needed to bring it on screen.
       100vh specifically (not 100dvh) is the LARGE viewport height on
       mobile Chrome — as if its own collapsible bottom toolbar were
       already hidden — so on first load, with that toolbar still on
       screen, this landed the bar below the toolbar (genuinely
       off-screen, not just visually covered) until scrolling made the
       toolbar auto-hide and the visual viewport grow to match. 100dvh
       tracks the real, current visual viewport instead, so the bar
       sits flush at the actual bottom edge in both states — bar is on
       screen immediately, no scroll needed, and no gap below it once
       the toolbar does hide. */
    top: 100vh;
    top: 100dvh;
    width: 100vw;
    max-width: 100vw;
    z-index: var(--z-fixed);
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    padding-bottom: max(var(--sp-3), env(safe-area-inset-bottom, 0px));
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border-top: 1px solid var(--color-border);
    box-shadow: 0 -8px 24px rgba(11, 37, 64, 0.08);
    transform: translateY(0);
    transition: transform var(--t-base);
}

@media (max-width: 899px) {
    .product-sticky-bar { display: flex; }
    body.single-product { padding-bottom: 0; } /* tab-bar's padding no longer applies — see main.css */
    /* The bar is now permanently on screen (not scroll-triggered), so
       the page needs real clearance at the bottom or the last related-
       product row sits underneath it — the ~3rem default is shorter
       than the bar itself (~4.5rem including its own padding) plus the
       home-indicator safe area on notched phones. */
    .product-page {
        padding-bottom: calc(var(--sp-16) + env(safe-area-inset-bottom, 0px));
    }
}

.product-sticky-bar.is-visible {
    /* Slides up by its own height from the top:100dvh resting position
       above — lands exactly at the true, current viewport bottom. */
    transform: translateY(-100%);
}

.product-sticky-bar__price {
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
}

.product-sticky-bar__price-label {
    font-size: 0.625rem;
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.product-sticky-bar__price-val {
    font-size: var(--text-md);
    font-weight: var(--fw-black);
    color: var(--color-text);
}

.product-sticky-bar .product-add-to-cart {
    height: 2.75rem;
}

.product-sticky-bar__actions,
.product-sticky-bar__in-cart {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex: 1;
    min-width: 0;
}

/* Same component as the inline qty stepper above, just matched to the
   sticky bar's more compact 2.75rem button height instead of 3.25rem. */
.product-sticky-bar__qty {
    height: 2.75rem;
    flex-shrink: 0;
}

.product-sticky-bar__qty .product-qty__btn {
    width: 2.25rem;
    height: calc(2.75rem - 6px);
}

.product-sticky-bar__remove {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    height: 2.75rem;
    flex: 1;
    min-width: 0;
    padding-inline: var(--sp-4);
    border: 1.5px solid rgba(239, 68, 68, 0.3);
    border-radius: var(--r-full);
    background: rgba(239, 68, 68, 0.06);
    color: #dc2626;
    font-size: var(--text-sm);
    font-weight: var(--fw-bold);
    transition: background var(--t-fast), transform var(--t-press);
}

.product-sticky-bar__remove:hover { background: rgba(239, 68, 68, 0.12); }
.product-sticky-bar__remove:active { transform: scale(0.97); }

.product-sticky-bar__in-cart.is-pending { opacity: 0.6; pointer-events: none; }

/* ================================================================
   TABS — Description / Specifications / Reviews
   ================================================================ */

/* flex:1 + min-height:0 — the piece that actually absorbs whatever
   extra height .product-info stretched to (see .product-info/
   .product-gallery above), so the active panel's own box (the specs
   card, or the reviews block) can grow to reach the image's bottom
   edge instead of leaving a gap under it. */
.product-tabs {
    margin-top: var(--sp-4);
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.product-tabs__nav {
    display: flex;
    gap: var(--sp-6);
    border-bottom: 1px solid var(--color-border);
    margin-bottom: var(--sp-6);
    overflow-x: auto;
    scrollbar-width: none;
}

.product-tabs__nav::-webkit-scrollbar { display: none; }

.product-tabs__btn {
    padding-block: var(--sp-3);
    font-size: var(--text-sm);
    font-weight: var(--fw-semi);
    color: var(--color-text-muted);
    white-space: nowrap;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    transition: color var(--t-fast), border-color var(--t-fast);
}

.product-tabs__btn:hover { color: var(--color-text); }

.product-tabs__btn.is-active {
    color: var(--color-blue);
    border-color: var(--color-blue);
}

.product-tabs__panel {
    display: none;
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    line-height: var(--lh-relaxed);
}

.product-tabs__panel.is-active {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.product-specs {
    display: flex;
    flex-direction: column;
    flex: 1;
    border: 1px solid var(--color-border);
    border-radius: var(--r-lg);
    overflow: hidden;
}

.product-specs__row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--sp-4);
    padding: var(--sp-4) var(--sp-5);
    font-size: var(--text-sm);
}

.product-specs__row:nth-child(even) { background: var(--color-bg); }

.product-specs__label {
    color: var(--color-text-muted);
    font-weight: var(--fw-medium);
}

.product-specs__value {
    color: var(--color-text);
    font-weight: var(--fw-semi);
    text-align: right;
}

/* Reviews — WooCommerce's default comment_form()/comment list markup,
   restyled to match. Class names below are WordPress/WC defaults. */
.product-reviews__summary {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    margin-bottom: var(--sp-6);
    padding-bottom: var(--sp-6);
    border-bottom: 1px solid var(--color-border);
}

.product-reviews__avg {
    font-size: var(--text-3xl);
    font-weight: var(--fw-black);
    color: var(--color-text);
    line-height: 1;
}

.product-reviews__count {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
}

#reviews .commentlist { list-style: none; display: flex; flex-direction: column; gap: var(--sp-5); }
#reviews .comment_container { display: flex; gap: var(--sp-3); }
#reviews .avatar { width: 36px; height: 36px; border-radius: var(--r-full); flex-shrink: 0; }
#reviews .comment-text { flex: 1; }
#reviews .woocommerce-review__author { font-weight: var(--fw-bold); font-size: var(--text-sm); color: var(--color-text); }
#reviews .woocommerce-review__dash { display: none; }
#reviews .woocommerce-review__published-date { font-size: var(--text-xs); color: var(--color-text-muted); }
#reviews .description p { margin-top: var(--sp-1); font-size: var(--text-sm); }
#reviews .star-rating { color: var(--color-blue); margin-bottom: var(--sp-1); }
#reviews .comment-form-rating select,
#reviews .comment-form-comment textarea,
#reviews .comment-form-author input,
#reviews .comment-form-email input {
    width: 100%;
    padding: var(--sp-3);
    border: 1px solid var(--color-border);
    border-radius: var(--r-md);
    font-family: var(--font);
    font-size: var(--text-sm);
    margin-top: var(--sp-1);
    margin-bottom: var(--sp-3);
    background: var(--color-surface);
    color: var(--color-text);
}
#reviews .form-submit input[type="submit"],
#reviews p.form-submit input#submit.submit {
    padding: var(--sp-3) var(--sp-6) !important;
    background: var(--color-blue) !important;
    color: var(--color-white) !important;
    border: none !important;
    border-radius: var(--r-full) !important;
    font-family: var(--font) !important;
    font-weight: var(--fw-bold) !important;
    font-size: var(--text-sm) !important;
    cursor: pointer;
    transition: background var(--t-fast), transform var(--t-press);
    appearance: none;
    -webkit-appearance: none;
}
#reviews .form-submit input[type="submit"]:hover { background: var(--color-blue-dark) !important; }
#reviews .form-submit input[type="submit"]:active { transform: scale(0.97); }
#reviews .comment-reply-title { font-size: var(--text-md); font-weight: var(--fw-bold); color: var(--color-text); margin-bottom: var(--sp-4); display: block; }
#reviews p.stars a { color: var(--color-blue); }
#reviews .no-reviews { color: var(--color-text-muted); font-size: var(--text-sm); }

/* ================================================================
   RELATED PRODUCTS / RECENTLY VIEWED
   Reuses the shared .product-card component from product-filter.css.
   ================================================================ */

.product-related,
.product-recent {
    margin-top: var(--sp-12);
}

.product-section__title {
    font-size: var(--text-xl);
    font-weight: var(--fw-black);
    letter-spacing: var(--ls-display);
    color: var(--color-text);
    margin-bottom: var(--sp-5);
}

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

@media (min-width: 640px)  { .product-recent__grid { grid-template-columns: repeat(3, 1fr); gap: var(--sp-5); } }
@media (min-width: 1024px) { .product-recent__grid { grid-template-columns: repeat(4, 1fr); } }

/* "You May Also Like" — auto-scrolling rail (product-single.js's
   driftRelatedRow), not a static grid: the card SET is rendered twice
   back to back (single-product.php) and the row's scrollLeft is
   nudged forward a tiny amount every frame, wrapping against one
   set's measured width — same "duplicate + modulo" technique as the
   trust strip, just moving noticeably slower (this rail has visible
   product photos to actually look at while it drifts by). */
.product-related__viewport {
    overflow: hidden;
}

.product-related__row {
    display: flex;
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.product-related__row::-webkit-scrollbar { display: none; }

.product-related__set {
    display: flex;
    gap: var(--sp-4);
    flex-shrink: 0;
    padding-right: var(--sp-4);
}

.product-related__set .product-card {
    flex: 0 0 150px;
}

@media (min-width: 640px) {
    .product-related__set { gap: var(--sp-5); padding-right: var(--sp-5); }
    .product-related__set .product-card { flex: 0 0 200px; }
}

@media (min-width: 1024px) {
    .product-related__set .product-card { flex: 0 0 230px; }
}
