/* =========================================================
   pages/product.css (T-220) — product_detail.html only.
   Linked from its {% block extra_head %}.

   NOT superseded here: style.css already ships the v3-tokened
   `.product-detail`/`.gallery-*`/`.stock-line`/`.option-*`/`.qty-*`/
   `.buy-bar` family in place (T-206a/b re-tokened every one of them
   directly, class names kept) -- there is no dead v2 block left behind
   for this page the way cart.css/home.css/orders.css/content.css found.
   This file only ADDS phone-only layout behaviour that is new with T-220
   (scroll-snap gallery + dots, hscroll related/recently-viewed strips,
   a price/stock row, the option-card wrapper + hairline, the description
   clamp) plus four small fixes carried over from gaps cart.css/a
   verification panel already flagged for this exact page.

   css_gap #1 (for T-221 -- cart.css's own header predicted this): the
   shared `.stepper button` rule (style.css) has no flex centering, so the
   {% icon %} minus/plus glyphs sit slightly off the button's optical
   center. cart.css already applies the identical fix scoped to cart.html;
   repeated here (same declaration, still page-scoped since this file
   isn't loaded there) so T-221 can fold ONE copy into the shared rule.
   css_gap #2 (for T-221): `.stepper input` and the global
   `input[type=number]{width:100%;min-height:52px;padding:13px 16px}`
   reset (style.css) have equal selector specificity and the global rule
   is declared later in the file, so it wins the cascade -- the quantity
   box was rendering 52px tall with 13px/16px padding instead of the
   stepper's own 44px/8px-0, clipped to the stepper's fixed 44px height
   (verified against the running dev server before this fix). Scoped
   below to `.qty-field .stepper` only, the sole consumer.
   css_gap #3 (for T-221 -- design-a11y verifier finding, post-ship fix):
   `.qty-field { width: 110px; }` (style.css) is narrower than the
   stepper's intrinsic content (44px + 54px + 44px = 142px for the two
   buttons and the #quantity input, plus 2px of border), and `.stepper`'s
   children keep the flexbox default `flex-shrink: 1` -- so the 110px box
   compressed both +/- buttons (and the input) below the 44px hit-area the
   MARKUP CONTRACT mandates (style.css:638), reproducing at every
   viewport (verified live at 375px and 1440px against product id 13).
   `.qty-field`'s only consumer page-wide is this template (grep
   confirmed), so widening it here removes the compression at its root;
   `flex-shrink: 0` on the stepper's own children is a second guard so the
   44px contract holds even if a future edit puts the stepper in another
   tight box on this page.
   css_gap #4 (verification-panel finding, minor -- self-documentation only):
   `.option-card`, `.option-swatch__name` and `.option-pills__name` had zero
   dedicated rule anywhere (style.css or here), rendering correctly today
   only via `.card` co-occurrence and inheritance from the legend rule --
   restated explicitly in the "Options card" rule block below (identical
   computed values; nothing changes on screen).

   Only canonical tokens are used below (see style.css :root) -- no
   @layer/nesting/IDs/!important, per the CSS contract for page files.
   Breakpoints: the four canonical ones (699 / 899-900 / 959 / 1149).
   ========================================================= */

/* ----------  Category eyebrow link (replaces the bordered chip pill)  ---------- */
.product-detail__cat {
    display: inline-block;
    font-size: .81rem;
    font-weight: 700;
    letter-spacing: .01em;
    color: var(--teal-700);
    margin-bottom: 6px;
}
.product-detail__cat:hover { color: var(--forest-800); text-decoration: underline; }

/* ----------  Price + stock row: price left, stock right-aligned  ---------- */
.product-detail__price-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 6px 14px;
}
.product-detail__price-row .price { margin: 0; }
.product-detail__price-row .stock-line { margin: 0; }

/* ----------  Description clamp + "Read more" toggle  ----------
   No-JS / .js-not-yet-run visitors always see the full description (the
   clamp only applies once document.documentElement carries .js, mirroring
   every other JS-only affordance in this codebase, e.g. .js-hide). */
.js .product-detail__desc[data-clamp] {
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.js .product-detail__desc[data-clamp].is-expanded {
    -webkit-line-clamp: unset;
    overflow: visible;
}
.link-btn[data-clamp-toggle] { gap: 4px; margin: -6px 0 10px; }

/* ----------  Options card: fieldsets + quantity row, one hairline  ---------- */
.option-card__divider { height: 1px; background: var(--line); margin: 16px 0; }

/* css_gap #4 -- see file header. No visual change: values restated below
   match what already renders via `.card` co-occurrence / inheritance. */
.option-card { margin-bottom: 24px; }

/* css_gap #1 -- see file header. */
.stepper button { display: inline-flex; align-items: center; justify-content: center; }
/* css_gap #2 -- see file header. Specificity (.qty-field .stepper input[type=number]
   = 2 classes + 1 attribute) beats the global input[type=number] reset regardless
   of source order, no !important needed. */
.qty-field .stepper input[type=number] {
    min-height: 44px;
    padding: 8px 0;
    width: 54px;
}
/* css_gap #3 -- see file header. `.stepper input`'s own `width: 54px`
   (style.css) ties in specificity with the global `input[type=number]{
   width:100%}` reset and loses on source order (same root cause as
   css_gap #2, this time for width) -- re-declared above at
   `.qty-field .stepper input[type=number]` (2 classes + attribute) so it
   reliably wins, keeping the stepper's total content at its designed
   44+54+44=142px. Widen the box to match so nothing gets squeezed or
   clipped by `.stepper`'s own `overflow:hidden`; flex-shrink:0 on the
   buttons/input is a second guard against any future container change. */
.qty-field { width: auto; min-width: 142px; }
.stepper button, .stepper input { flex-shrink: 0; }

/* ----------  Info card spacing (replaces the old .notice--green here)  ---------- */
.product-detail__info .info-card { margin-bottom: 20px; }

/* ----------  Phone-only slide indicator for the gallery  ----------
   Built/synced by the extra_js scroll listener; empty markup otherwise.
   Absolutely positioned so it never becomes a flex item of the scrolling
   row it shares a parent with (see the .js media-query block below) --
   an early draft left it in-flow and the browser folded it into the
   scroll-snap track as a fourth "slide", which also (via the interaction
   with the overflowing row's centering, fixed below) shifted the whole
   row's rendered start position. */
.gallery-dots {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    bottom: 10px;
    justify-content: center;
    gap: 6px;
    pointer-events: none;
}
.gallery-dots__dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--line-2);
    transition: background var(--t-fast), transform var(--t-fast);
}
.gallery-dots__dot.is-active { background: var(--forest-800); transform: scale(1.3); }

/* ----------  Responsive (four canonical breakpoints)  ---------- */
@media (max-width: 699px) {
    /* header_back already covers "back to shop/category" on phones. */
    .breadcrumb { display: none; }

    /* Gallery becomes the scroll-snap row itself: the main image is slide 1,
       then the thumb strip's OWN buttons become slides 2+ (the first one,
       a duplicate of the main image kept for the ≥700 stacked layout, is
       hidden so it isn't shown twice in a row).

       DELIBERATE DEVIATION from the dispatch's literal
       ".gallery-strip { display:contents }" instruction (recorded for
       T-221/QA): verified against the real dev server, that rule breaks
       here -- Chromium mis-lays-out the flex track once a `display:contents`
       wrapper's FIRST child is `display:none` in this exact combination
       (flex row + contents-flattened grandchildren + one hidden), leaving
       the main image rendered hundreds of px outside the viewport instead
       of as slide 1 (reproduced with getBoundingClientRect(); reverting
       just the `display:contents` line to `display:block` fixed it in the
       same session). `.gallery-strip` instead stays a REAL (non-contents)
       flex box one level in; extra_js measures the container's actual
       clientWidth once and writes it to the --slide-w/--strip-w custom
       properties below, which only these <700 rules consume -- the ≥700
       stacked layout ignores them entirely, so nothing here can affect it.

       Gated on .js (html.js, set by base.html before this content ever
       parses -- same guard as the description clamp above): the
       --slide-w/--strip-w custom properties only exist once extra_js's
       GallerySlideSync has measured the container, so a no-JS visitor
       keeps the plain, already-tested stacked layout (main image + a
       horizontally-scrollable but un-sliced 66px thumb row) at every
       width instead of the undersized thumbs an unset var(...,100%)
       fallback would otherwise produce here.

       justify-content: flex-start below is load-bearing, not decorative:
       the shared (frozen) `.product-detail__media` base rule sets
       `justify-content: center` for the ordinary single-image case, and
       centering an OVERFLOWING flex row starts it scrolled to its middle
       instead of its first item -- with content wider than the container
       and no override, the main image rendered ~340px into negative
       territory (verified live) even though `scrollLeft` correctly read 0. */
    .js .product-detail__media--gallery {
        display: flex;
        flex-direction: row;
        justify-content: flex-start;
        position: relative;
        gap: 0;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        padding: 0;
    }
    .js .product-detail__media--gallery::-webkit-scrollbar { display: none; }
    .js .product-detail__media--gallery > img {
        flex: 0 0 100%;
        width: 100%;
        max-height: none;
        aspect-ratio: 1 / 1;
        object-fit: contain;
        scroll-snap-align: start;
    }
    .js .product-detail__media--gallery .gallery-strip {
        display: flex;
        flex: 0 0 auto;
        width: var(--strip-w, auto);
    }
    .js .product-detail__media--gallery .gallery-thumb {
        flex: 0 0 var(--slide-w, 100%);
        width: var(--slide-w, 100%);
        height: auto;
        aspect-ratio: 1 / 1;
        border: 0;
        border-radius: 0;
        scroll-snap-align: start;
    }
    .js .product-detail__media--gallery .gallery-thumb:first-child { display: none; }
    .js .gallery-dots { display: flex; }

    /* "Continue shopping" is redundant with the header back link on phones;
       kept in markup (≥700 shows it) but hidden here. */
    .product-detail__continue { display: none; }

    /* Related / recently-viewed: horizontal scroll-snap row of narrow cards
       instead of the (frozen) 2-up grid style.css gives every other
       .product-grid at this width. Higher specificity (two classes) wins
       over that rule regardless of source order. */
    .product-grid--scroll {
        display: flex;
        overflow-x: auto;
        scroll-snap-type: x proximity;
        gap: 12px;
        padding-bottom: 4px;
        scrollbar-width: none;
    }
    .product-grid--scroll::-webkit-scrollbar { display: none; }
    .product-grid--scroll .product-card {
        flex: 0 0 168px;
        width: 168px;
        scroll-snap-align: start;
    }
}

/* Orchestrator (post-T-220 visual QA):
   1. [hidden] must beat .link-btn's display so the Read-more toggle stays
      hidden when the description is not clamped.
   2. On phones the fixed buy bar carries the primary action; the inline
      Add-to-cart button inside the quantity row would be a duplicate. */
.link-btn[hidden] { display: none; }
@media (max-width: 699px) {
    body.has-action-bar .qty-row > .btn { display: none; }
}
