/* Screen 04 — product. Layout only; components live in their own files. */

/* The tabs sat flush against the gallery and buy column — measured 0px. They
   are a separate band of the page and need the section rhythm, not a hairline. */
.st-product__tabs {
  margin-top: var(--st-section-y);
}

/* "Comprar agora" was touching the add-to-cart row at 0px. */
.st-product__buy-now {
  margin-top: 12px;
}

@media (max-width: 899px) {
  .st-product__tabs {
    margin-top: var(--st-section-y-mobile);
  }
}

.st-product {
  display: grid;
  grid-template-columns: 1fr 520px;
  gap: 40px;
  align-items: start;
}

.st-product__buy {
  display: grid;
  gap: 20px;
  align-content: start;
}

@media (max-width: 1199px) {
  .st-product {
    grid-template-columns: 1fr 420px;
  }
}

@media (max-width: 899px) {
  /* Gallery above, buy column below — handoff, "Responsividade". */
  .st-product {
    grid-template-columns: 1fr;
    gap: 24px;
  }
}

.st-product__title {
  font-size: 38px;
  font-weight: var(--st-weight-black);
  letter-spacing: var(--st-track-h1);
  line-height: 1.05;
}

.st-product__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  margin-top: 10px;
}

.st-product__sku {
  color: var(--st-muted);
  font-size: var(--st-size-caption);
}

@media (max-width: 599px) {
  .st-product__title {
    font-size: 24px;
  }
}

.st-shipping-card {
  display: grid;
  gap: 14px;
  padding: 18px;
  background: var(--st-surface);
  border: var(--st-border-width) solid var(--st-ink);
}

.st-shipping-card__heading {
  font-size: var(--st-size-caption);
  font-weight: var(--st-weight-bold);
}

.st-shipping-card__row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px;
}

.st-shipping-card__unavailable,
.st-shipping-card__results {
  font-size: var(--st-size-caption);
  color: var(--st-ink-2);
}

/* ShippingEstimate's answer: one line per rate the zone offers. */
.st-shipping-card__destination {
  margin: 0 0 8px;
  color: var(--st-muted);
}

.st-shipping-card__rates {
  display: grid;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.st-shipping-card__rate {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  font-size: var(--st-size-body-sm);
}

.st-shipping-card__rate strong {
  font-weight: var(--st-weight-extrabold);
}

.st-shipping-card__free {
  color: var(--st-accent-deep);
}

/* A CEP was submitted and nothing answered it — distinct from the neutral
   "not tried yet" prompt above, so a shopper who just typed a CEP does not
   read the same generic message back. */
.st-shipping-card__unavailable--failed {
  color: var(--st-accent-deep);
}

.st-shipping-card__seals {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  padding: 14px 0 0;
  margin: 0;
  border-top: var(--st-rule-thin);
  list-style: none;
}

.st-shipping-card__seal {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--st-size-caption);
}

.st-shipping-card__seal svg {
  flex: none;
  color: var(--st-accent);
}

/* "Complete o quarto" cross-sell grid: four cards, the same shared .st-card
   every grid in the project uses (components/card.css). Only the column
   count is set here — everything else about the grid and the card is that
   shared component, unmodified. */
.st-product__crosssell .st-products {
  --st-card-columns: 4;
}

/*
 * Fix (found running this task's own narrow-viewport check, see report):
 * a CSS grid track's implicit min-width is `auto` -- the min-content size
 * of whatever sits in it -- not 0. That is invisible on the shop archive's
 * three-column grid at the widths it is ever seen at, but this section's
 * four columns shrink each card enough, at narrow viewports, that its
 * min-content (an unwrapped size chip, in the 1024x600 case; a longer
 * title elsewhere) now exceeds the available track width, pushing
 * `.st-card-item`/`.st-card` past the container edge and the WHOLE page
 * into horizontal scroll -- confirmed live: exactly this regressed an
 * already-green Task 11 test (`tests/visual/product.spec.js`, "the tab
 * row wraps rather than overflowing the page at a narrow viewport"),
 * which checks page-wide overflow on this same product page, not
 * anything scoped to the tab row itself. Scoped to this section only, not
 * card.css's shared `.st-card-item`, since nothing else currently
 * exhibits this at any width it is actually viewed at.
 */
.st-product__crosssell .st-card-item {
  min-width: 0;
}

@media (max-width: 899px) {
  .st-product__crosssell .st-products {
    --st-card-columns: 2;
  }
}

/* --- Mobile fixed buy bar (Task 13) ------------------------------------- */

/*
 * Hidden by default: the partial renders unconditionally (ProductScreen::
 * render_buy_bar()) so its DOM position stays inside the buy column at
 * every viewport, but it is only ever the mobile control -- above 599px
 * Task 8's inline `.st-product__actions` row is what a shopper sees.
 */
.st-buy-bar {
  display: none;
}

@media (max-width: 599px) {
  /*
   * Fix round 1 (task-13-report.md): the handoff's own "96px stepper"
   * value cannot hold both 44px controls AND a legible quantity at once
   * -- 44 + 44 = 88, leaving 8px for the number, confirmed live
   * (getBoundingClientRect(): the qty input rendered 4px wide, the
   * digit unreadable). The 44px touch-target floor is a hard project
   * constraint (global-constraints.md) that a soft handoff dimension does
   * not override, so the column was widened -- rather than shrinking
   * either button below the floor.
   *
   * Fix round 3 (task-13-report.md): 120px (round 1's own widened value)
   * turned out to still be short: it gives the QTY INPUT only 120 - 88 =
   * 32px, which comfortably shows a legible number but stops short of the
   * input itself being a legal 44px touch target (this input is
   * focusable and directly editable, so the 44px floor applies to it
   * too, not only to the two buttons flanking it -- confirmed live:
   * 28x48, 16px under the width floor). `.st-stepper`'s own shared
   * `grid-template-columns` (components/variations.css:
   * `var(--st-h-touch) 1fr var(--st-h-touch)`, i.e. 44px/1fr/44px) is
   * untouched here -- it is shared with the desktop `.st-product__actions`
   * row, and 44 + 44 = 88 subtracted from a WIDER outer column simply
   * grows the middle `1fr` track by exactly the difference, with no
   * change to the shared component at all. `.st-stepper` also carries its
   * own `border: var(--st-border-width) solid` (2px, all sides -- same
   * file), which a first attempt at this arithmetic (44 * 3 = 132) missed
   * and measured live as a 40px-wide input, 4px short -- the border eats
   * into the content box under this project's global `box-sizing:
   * border-box`. 136px is 44 * 3 + 4 (the border), confirmed live as
   * exactly 44px. The extra width comes from `.st-buy-bar`'s own side
   * padding shrinking from 16px to `--st-grid-gap-mobile` (12px, an
   * existing token, not a new value) on each side -- 8px of real width
   * freed, most of it absorbed by the stepper's growth, the remainder
   * from the Add button's own track, confirmed live to still fit with
   * margin to spare (see "the Add control's right edge..." and "the
   * button text fits without truncation", below, both re-verified after
   * this change).
   */
  .st-buy-bar {
    position: fixed;
    inset-inline: 0;
    inset-block-end: 0;
    z-index: 80;
    display: grid;
    grid-template-columns: 136px 1fr;
    gap: 10px;
    padding: 10px var(--st-grid-gap-mobile) calc(10px + env(safe-area-inset-bottom, 0px));
    background: var(--st-surface);
    border-top: var(--st-rule);
    box-shadow: var(--st-shadow-bar);
  }

  .st-buy-bar .st-stepper {
    height: var(--st-h-button-mobile);
  }

  /*
   * Fix round 1: `min-width: 0` is the actual fix for the button clipping
   * past the bar's own right edge -- a grid item's default min-width is
   * `auto` (its content's min-content size), so before this rule the
   * button refused to shrink to its 1fr track and pushed the bar itself
   * wider than the viewport, exactly the "23px sideways scroll" shape
   * named in this project's own verification bar (product.spec.js's
   * cross-sell fix, two tasks earlier). `justify-content: center`
   * replaces `.st-btn`'s own `space-between` (fine for a two-line desktop
   * button with room to spread; wrong for one short line of centred
   * text).
   *
   * Fix round 2 (task-13-report.md): `text-overflow: ellipsis` is
   * deliberately GONE from here and from `.st-buy-bar__price` (removed
   * entirely, not merely retained) -- it was never a safety net, it was
   * the bug: with cents included the price silently ellipsised away to
   * "R$ …", passing every existing test while the shopper saw no price
   * at all. `overflow: hidden` and `white-space: nowrap` stay -- they
   * only prevent a genuine overflow from re-clipping the bar's edge or
   * wrapping to a second line; they do not hide missing content behind
   * "...". Dropping the cents (mobile-buy-bar.php, product.js) is the
   * handoff's own fix ("Adicionar · R$ 2.699", no cents) and shrinks the
   * string most of the way, but measured live it was still 21px wider
   * than the box even with cents gone (200px content in a 179px box) --
   * `font-size: var(--st-size-caption)` (12.5px, an existing token, not a
   * new magic number) and a smaller `padding-inline` (4px, down from
   * `.st-btn`'s own 18px) close the rest of that gap, confirmed live with
   * real margin to spare (~23px), not merely equal. The text is asserted
   * (not merely hoped) to occupy no more width than the box provides --
   * see product.spec.js, "the button's rendered text fits without
   * truncation".
   */
  .st-buy-bar__add {
    min-height: var(--st-h-button-mobile);
    min-width: 0;
    justify-content: center;
    gap: 6px;
    padding-inline: 4px;
    overflow: hidden;
    white-space: nowrap;
    font-size: var(--st-size-caption);
  }

  /*
   * Reserve the bar's height (plus the iOS-style safe-area inset it now
   * also pads for) at the foot of the document. Without this the footer's
   * last line sits underneath the bar permanently and can never be read or
   * tapped -- confirmed by deliberately removing this rule: the "does not
   * cover the last element of the page" test below goes RED the instant it
   * is gone (see task-13-report.md).
   *
   * Four terms have to at least match the bar's own box model, each for a
   * real reason found live, not assumed: `--st-h-button-mobile` (52px) is
   * the stepper/button row; `20px` is the bar's own 10px top + 10px bottom
   * padding; `--st-border-width` (2px) is `border-top: var(--st-rule)` on
   * `.st-buy-bar`, which is easy to read past in the rule above --
   * omitting it left the reserved space 2px shorter than the bar's real
   * rendered height, confirmed live with getBoundingClientRect() (390x844,
   * this product's real fabric-less variation): the bar measured 74px
   * tall while this rule reserved only 72px, leaving the footer's last 2px
   * still covered. The final `+ 1px` is deliberate slack, also found live:
   * even with the three terms above matching the bar's height exactly,
   * the footer's own bottom edge landed at a fractional sub-pixel
   * (770.015625px) a hair PAST the bar's top (770px) -- ordinary
   * line-height/font-metric rounding accumulated over the page, not
   * anything wrong in this rule -- which a strict `footer.bottom >
   * bar.top` check (the shape this task's own test uses) would still flag
   * as "covered". 1px of slack is imperceptible as blank space and
   * absorbs that rounding with room to spare.
   */
  body.single-product {
    padding-bottom: calc(var(--st-h-button-mobile) + 20px + var(--st-border-width) + 1px + env(safe-area-inset-bottom, 0px));
  }
}
