/**
 * WooCommerce: product detail page.
 *
 * Ported from .docs/mockup/css/pdp.css (640 lines, frozen signed-off contract).
 * Values are the mockup's. Where the mockup wrote a literal that has a token
 * (11px eyebrows -> --text-eyebrow, #fff -> --white) the token is used instead,
 * so the surface follows Theme Settings; everything else is byte-for-byte.
 *
 * Not ported, deliberately:
 *   .pdp-rating, .pdp-reviews  — star ratings and reviews were removed by the
 *                                design team (product-build-audit §3).
 *   .pdp-detail, .pdp-detail-grid — the old full-width details band, superseded
 *                                by the in-column layout on 17 July. Its only
 *                                remaining user was the Roadtripper quote,
 *                                which now has .pdp-testimonial below.
 *
 * Added, not in the mockup:
 *   .v-input / .v-btn radio pairing — the mockup's variant "buttons" are real
 *                                radio inputs here so the page is purchasable
 *                                without JavaScript. Rendered pixels unchanged.
 *   .pdp-form, .qty-stepper input   — the buy box is a real <form>.
 *   .pdp-notices                    — WooCommerce's own add-to-cart messages.
 *   img rules inside .pdp-main-img / .pdp-thumb / .bt-thumb — the mockup paints
 *                                these as background-image; real <img> elements
 *                                render identically under object-fit: cover.
 */

.pdp {
  padding-block: var(--section-space-s);
  padding-inline: var(--space-gutter);
}

/* --- Breadcrumb --- */
.pdp-breadcrumb {
  max-width: var(--container);
  margin-inline: auto;
  margin-bottom: var(--space-l);
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--graphite);
}

.pdp-breadcrumb a {
  color: var(--deep-ocean);
  transition: color var(--duration-fast);
}

.pdp-breadcrumb a:hover {
  color: var(--terracotta);
}

.pdp-crumb-sep {
  margin-inline: var(--space-3xs);
}

/* --- WooCommerce notices --- */
.pdp-notices {
  max-width: var(--container);
  margin-inline: auto;
}

.pdp-notices:empty {
  display: none;
}

.pdp-notices .woocommerce-message,
.pdp-notices .woocommerce-info,
.pdp-notices .woocommerce-error {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-s);
  margin-bottom: var(--space-l);
  padding: var(--space-s) var(--space-m);
  border-left: 4px solid var(--eucalypt);
  border-radius: var(--radius-md);
  background: var(--coastal-soft);
  color: var(--charcoal);
  font-size: var(--text-small);
  line-height: 1.5;
}

.pdp-notices .woocommerce-error {
  border-left-color: var(--terracotta);
  background: var(--pebble);
}

.pdp-notices .woocommerce-message a,
.pdp-notices .woocommerce-info a,
.pdp-notices .woocommerce-error a {
  color: var(--deep-ocean);
  font-weight: 600;
  text-decoration: underline;
}

.pdp-top {
  max-width: var(--container);
  margin-inline: auto;
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: var(--space-2xl);
  align-items: start;
}

/* --- Gallery --- */
.pdp-gallery {
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
  min-width: 0;
}

/* Desktop: keep the gallery in view while the buy/detail column scrolls.
   Sticks below the 74px sticky nav, within the .pdp-top grid row. */
@media (min-width: 901px) {
  .pdp-gallery {
    position: sticky;
    top: calc(74px + var(--space-s));
    align-self: start;
  }
}

.pdp-main-img {
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background-color: var(--coastal-soft);
  border-radius: var(--radius-lg);
}

/* Absolute + object-fit, the same technique .kit-img-photo uses.
   Selector-nested on purpose: WooCommerce's own stylesheet ships
   `.woocommerce img { height: auto }` at (0,1,1), which outranks a lone class,
   and the square box takes its height from aspect-ratio so a bare
   `height: 100%` would fall back to auto and letterbox the photo. */
.pdp-main-img .pdp-main-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.pdp-main-img--placeholder {
  display: grid;
  place-items: center;
}

.pdp-img-note {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3xs);
  color: var(--deep-ocean);
  font-size: var(--text-small);
  font-weight: 600;
}

.pdp-thumbs {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-2xs);
}

.pdp-thumb {
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background-color: var(--coastal-soft);
  border: 2px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  padding: 0;
  transition: border-color var(--duration-fast), transform var(--duration-fast) var(--ease-out);
}

.pdp-thumb .pdp-thumb-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.pdp-thumb:hover {
  transform: translateY(-2px);
}

.pdp-thumb.is-active {
  border-color: var(--terracotta);
}

.pdp-thumb:focus-visible {
  outline: 2px solid var(--deep-ocean);
  outline-offset: 2px;
}

/* --- Right column: buy box + details, scrolls past the sticky gallery --- */
.pdp-main-col {
  display: flex;
  flex-direction: column;
  gap: var(--space-l);
  min-width: 0;
}

/* Inline detail blocks (were a separate full-width band; now beside the image) */
.pdp-overview,
.pdp-included,
.pdp-specs {
  border-top: 1px solid var(--hairline);
  padding-top: var(--space-l);
}

/* Full product description (from the docx) */
.pdp-overview p {
  font-size: var(--text-lead);
  color: var(--charcoal);
  line-height: 1.7;
  max-width: 62ch;
}

.pdp-overview p + p {
  margin-top: var(--space-s);
}

/* Several store descriptions still carry old catalogue markup — bullet lists
   and a stray heading. base.css strips list markers globally, so they are put
   back here rather than leaving an unreadable run of lines. See the report:
   this content needs a pass, the styling is a holding position. */
.pdp-overview ul,
.pdp-overview ol {
  margin-top: var(--space-s);
  padding-left: var(--space-m);
  color: var(--charcoal);
  font-size: var(--text-small);
  line-height: 1.6;
}

.pdp-overview ul {
  list-style: disc;
}

.pdp-overview ol {
  list-style: decimal;
}

.pdp-overview h2 {
  margin-top: var(--space-s);
  font-size: var(--text-h4);
  font-weight: 700;
  color: var(--deep-ocean);
}

.pdp-included h2,
.pdp-specs h2 {
  font-size: var(--text-h3);
  font-weight: 800;
  margin-bottom: var(--space-m);
}

.pdp-included h2 em,
.pdp-specs h2 em {
  font-style: italic;
  font-weight: 500;
  color: var(--terracotta);
}

/* --- Info column --- */
.pdp-info {
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
  align-items: flex-start;
}

.pdp-eyebrow {
  font-size: var(--text-eyebrow);
  font-weight: 700;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--terracotta);
}

.pdp-info h1 {
  font-size: clamp(32px, 3.6vw, 48px);
  font-weight: 800;
  letter-spacing: -0.025em;
  line-height: 1.03;
}

.pdp-price {
  display: flex;
  align-items: baseline;
  gap: var(--space-s);
  width: 100%;
  margin-top: var(--space-2xs);
  padding-top: var(--space-m);
  border-top: 1px solid var(--hairline);
}

.pdp-price .amount {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: clamp(30px, 3.4vw, 42px);
  color: var(--deep-ocean);
  line-height: 1;
}

.pdp-price .from {
  font-size: var(--text-small);
  color: var(--graphite);
}

.pdp-desc {
  color: var(--charcoal);
  line-height: 1.65;
  max-width: 52ch;
}

.pdp-unavailable {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2xs);
  width: 100%;
  padding: var(--space-s) var(--space-m);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  background: var(--pebble);
  color: var(--charcoal);
  font-size: var(--text-small);
  line-height: 1.5;
  max-width: 52ch;
}

.pdp-unavailable .material-symbols-outlined {
  color: var(--terracotta);
}

/* --- The cart form -------------------------------------------------------
   The mockup has the variant groups and the buy row as direct children of
   .pdp-info. Wrapping them in a real <form> would swallow that flex gap, so
   the form repeats its parent's layout and the spacing is unchanged. */
.pdp-form {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-s);
  width: 100%;
}

/* --- Variants --- */
.pdp-variants {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  margin-top: var(--space-2xs);
}

.v-fieldset {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  min-width: 0;
  border: 0;
  margin: 0;
  padding: 0;
}

.v-label {
  display: block;
  padding: 0;
  font-size: var(--text-eyebrow);
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--graphite);
}

.v-btns {
  position: relative;
  display: flex;
  gap: var(--space-s);
  flex-wrap: wrap;
}

/* The radio is the real control; the label is the mockup's button. Kept in the
   layout (not display:none) so it stays reachable by keyboard. */
.v-input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
  pointer-events: none;
}

.v-btn {
  flex: 1 1 0;
  min-width: 160px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  text-align: left;
  background: var(--off-white);
  border: 1.5px solid var(--hairline);
  border-radius: var(--radius-md);
  padding: var(--space-s) var(--space-m);
  font-family: var(--font-heading);
  font-weight: 700;
  color: var(--charcoal);
  cursor: pointer;
  transition: border-color var(--duration-fast), background var(--duration-fast),
              box-shadow var(--duration-fast);
}

.v-btn small {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: var(--text-small);
  color: var(--graphite);
}

.v-btn:hover {
  border-color: var(--coastal-blue);
}

.v-input:checked + .v-btn {
  border-color: var(--deep-ocean);
  background: var(--coastal-soft);
  box-shadow: inset 0 0 0 1px var(--deep-ocean);
}

.v-input:checked + .v-btn small {
  color: var(--deep-ocean);
}

.v-input:focus-visible + .v-btn {
  outline: 2px solid var(--deep-ocean);
  outline-offset: 2px;
}

/* A combination the store does not sell. Struck through rather than hidden, so
   the range on offer still reads as a range. */
.v-btn.is-unavailable {
  opacity: 0.45;
  cursor: not-allowed;
  text-decoration: line-through;
}

.v-btn.is-unavailable:hover {
  border-color: var(--hairline);
}

.v-note {
  font-size: var(--text-small);
  color: var(--graphite);
  margin-top: var(--space-2xs);
}

/* --- Buy row --- */
.pdp-buy {
  display: flex;
  align-items: stretch;
  gap: var(--space-s);
  width: 100%;
  flex-wrap: wrap;
  margin-top: var(--space-2xs);
}

.qty-stepper {
  display: inline-flex;
  align-items: center;
  border: 1.5px solid var(--hairline);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.qty-stepper .qty-step {
  width: 46px;
  min-height: 50px;
  display: grid;
  place-items: center;
  color: var(--deep-ocean);
  background: var(--off-white);
  border: 0;
  cursor: pointer;
  transition: background var(--duration-fast);
}

.qty-stepper .qty-step:hover {
  background: var(--pebble);
}

.qty-stepper .qty-step:focus-visible {
  outline: 2px solid var(--deep-ocean);
  outline-offset: -2px;
}

.qty-stepper .qv {
  width: 42px;
  min-width: 42px;
  padding: 0;
  text-align: center;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--text-body);
  color: var(--charcoal);
  background: var(--white);
  border: 0;
  -moz-appearance: textfield;
  appearance: textfield;
}

.qty-stepper .qv::-webkit-outer-spin-button,
.qty-stepper .qv::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.qty-stepper .qv:focus-visible {
  outline: 2px solid var(--deep-ocean);
  outline-offset: -2px;
}

.pdp-buy .btn-primary {
  flex: 1 1 auto;
  justify-content: center;
}

/* --- Trust row --- */
.pdp-trust {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-s);
  width: 100%;
  margin-top: var(--space-s);
  padding-top: var(--space-m);
  border-top: 1px solid var(--hairline);
}

.t-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.t-item .material-symbols-outlined {
  font-size: 26px;
  color: var(--eucalypt);
  margin-bottom: 4px;
}

.t-item strong {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--text-small);
  color: var(--deep-ocean);
}

.t-item span {
  font-size: 12px;
  color: var(--graphite);
  line-height: 1.35;
}

/* --- Detail: included + specs --- */
.included-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
  list-style: none;
  margin: 0;
  padding: 0;
}

.included-list li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-s);
  align-items: start;
  color: var(--charcoal);
  line-height: 1.5;
  font-size: var(--text-small);
}

.included-list li .material-symbols-outlined {
  color: var(--eucalypt);
  font-size: 22px;
  margin-top: 1px;
}

.spec-table {
  width: 100%;
  border-collapse: collapse;
}

.spec-table th,
.spec-table td {
  text-align: left;
  padding: var(--space-s) 0;
  border-bottom: 1px solid var(--hairline);
  vertical-align: top;
  font-size: var(--text-small);
  line-height: 1.45;
}

.spec-table th {
  width: 38%;
  color: var(--deep-ocean);
  font-family: var(--font-heading);
  font-weight: 700;
  padding-right: var(--space-s);
}

.spec-table td {
  color: var(--graphite);
}

/* --- Owner's note ---------------------------------------------------------
   The mockup builds this out of .pdp-detail plus five inline style attributes.
   Same values, lifted out of the markup so nothing is hardcoded in a template. */
.pdp-testimonial {
  padding-block: var(--section-space-s);
  padding-inline: var(--space-gutter);
  background: var(--off-white);
}

.pdp-testimonial-inner {
  max-width: var(--container);
  margin-inline: auto;
}

.pdp-quote p {
  font-family: var(--font-heading);
  font-size: var(--text-h3);
  font-weight: 500;
  font-style: italic;
  color: var(--deep-ocean);
  max-width: 60ch;
  line-height: 1.4;
}

.pdp-quote cite {
  display: block;
  margin-top: var(--space-s);
  font-size: var(--text-small);
  font-style: normal;
  font-weight: 600;
  color: var(--graphite);
}

/* --- Upsell sections --- */
.pdp-upsell {
  padding-block: var(--section-space-s);
  padding-inline: var(--space-gutter);
}

.pdp-upsell.alt {
  background: var(--pebble);
}

.pdp-upsell .section-head {
  max-width: var(--container);
  margin-inline: auto;
}

.pdp-upsell .kit-grid {
  max-width: var(--container);
  margin-inline: auto;
}

/* Trade-up banner */
.trade-up {
  max-width: var(--container);
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-l);
  flex-wrap: wrap;
  background: var(--deep-ocean);
  border-radius: var(--radius-lg);
  padding: var(--space-l);
}

.tu-text h2 {
  color: var(--off-white);
  font-size: var(--text-h3);
  font-weight: 700;
  max-width: 24ch;
}

.tu-text h2 em {
  font-style: italic;
  font-weight: 500;
  color: var(--coastal-blue);
}

.tu-text p {
  color: var(--coastal-blue);
  line-height: 1.6;
  margin-top: var(--space-2xs);
  max-width: 56ch;
}

.trade-up .btn-primary {
  flex-shrink: 0;
}

/* Frequently bought together */
.bought {
  max-width: var(--container);
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-l);
  flex-wrap: wrap;
  background: var(--off-white);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
  padding: var(--space-l);
}

.bought-items {
  display: flex;
  align-items: center;
  gap: var(--space-s);
  flex-wrap: wrap;
  flex: 1 1 auto;
}

.bt-item {
  display: grid;
  grid-template-columns: 56px 1fr;
  column-gap: var(--space-s);
  align-items: center;
  min-width: 190px;
}

.bt-thumb {
  grid-column: 1;
  grid-row: 1 / span 3;
  width: 56px;
  height: 56px;
  overflow: hidden;
  border-radius: var(--radius-sm);
  background-color: var(--coastal-soft);
}

.bought .bt-thumb img {
  width: 56px;
  height: 56px;
  object-fit: cover;
  display: block;
}

.bt-name {
  grid-column: 2;
  font-weight: 600;
  font-size: var(--text-small);
  color: var(--charcoal);
  line-height: 1.2;
}

.bt-price {
  grid-column: 2;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--text-small);
  color: var(--deep-ocean);
}

.bt-check {
  grid-column: 2;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--graphite);
  cursor: pointer;
}

.bt-check input {
  width: 15px;
  height: 15px;
  accent-color: var(--terracotta);
}

.bt-check input:focus-visible {
  outline: 2px solid var(--deep-ocean);
  outline-offset: 2px;
}

.bt-plus {
  flex-shrink: 0;
  font-size: 24px;
  font-weight: 300;
  color: var(--graphite);
}

.bought-buy {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-2xs);
  flex-shrink: 0;
  text-align: right;
}

.bt-total-label {
  font-size: var(--text-eyebrow);
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--graphite);
}

.bt-total {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: clamp(24px, 3vw, 32px);
  color: var(--deep-ocean);
  line-height: 1;
}

/* --- Responsive --- */
@media (max-width: 900px) {
  .pdp-top {
    grid-template-columns: 1fr;
    gap: var(--space-xl);
  }

  /* --- Sticky add-to-cart bar ---------------------------------------------
     Driven by assets/js/woo/sticky-add-to-cart.js. Once the buy row scrolls
     out of view the script wraps the SAME `.pdp-buy` element (no clone —
     one quantity input, one submit button, same as always) in
     `.pdp-buy-slot` and adds `.is-pdp-buy-pinned` to pin it here. The slot
     keeps reserving `.pdp-buy`'s normal-flow height for as long as it is
     pinned, so removing it from flow does not shift anything below it.

     With JavaScript off, or above this breakpoint, neither the wrapper nor
     the class ever exist — `.pdp-buy` renders and submits exactly as the
     normal-flow row defined above. */
  .pdp-buy-slot {
    width: 100%;
  }

  .pdp-buy.is-pdp-buy-pinned {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 90;
    margin-top: 0;
    background: var(--white);
    border-top: 1.5px solid var(--hairline);
    padding: var(--space-s) var(--space-gutter) calc(var(--space-s) + env(safe-area-inset-bottom));
  }

  /* The pinned bar spans the full viewport width at the bottom, which would
     otherwise sit on top of the floating back-to-top button (components.css)
     — both are `position: fixed; bottom: ~0`. Lift back-to-top clear of the
     pinned bar's height rather than hide it: a shopper deep in the page
     still has a fast way back to the top, without the two controls
     overlapping.

     The bar's height isn't constant — the quantity stepper and "Add to
     cart" button sit side by side on wider phones but wrap onto two lines
     on narrower ones (`.pdp-buy` is `flex-wrap: wrap`), which roughly
     doubles it. sticky-add-to-cart.js publishes the real measured height as
     --catnip-pinned-buy-height while pinned, so this stays correct at every
     width in the breakpoint instead of guessing one static offset. The
     140px fallback only matters if that script fails to load. */
  body:has(.pdp-buy.is-pdp-buy-pinned) .back-to-top {
    bottom: calc(var(--catnip-pinned-buy-height, 140px) + var(--space-s) + env(safe-area-inset-bottom));
  }
}

@media (max-width: 560px) {
  .bought,
  .trade-up {
    flex-direction: column;
    align-items: stretch;
    text-align: left;
  }

  .bought-buy {
    align-items: stretch;
    text-align: left;
  }

  .bought-buy .btn-primary {
    justify-content: center;
  }

  /* Keep the trust row as a single row (3 columns) on mobile too */
  .pdp-trust {
    gap: var(--space-2xs);
  }

  .pdp-trust .t-item strong {
    font-size: 12px;
  }

  .pdp-trust .t-item span {
    font-size: 10.5px;
  }

  .pdp-trust .t-item .material-symbols-outlined {
    font-size: 22px;
  }
}

/* ---------------------------------------------------------------------------
   NO-SCRIPT PRICE MATRIX
   ---------------------------------------------------------------------------
   Only ever rendered inside <noscript>, so it never reaches a scripted page.
   Styled anyway: a bare table on a designed PDP looks like a fault, and this
   is the one place a JS-off shopper reads prices for anything other than the
   default variation. */

.v-matrix {
  width: 100%;
  border-collapse: collapse;
  margin-block: var(--space-xs);
  font-size: var(--text-small);
}

.v-matrix caption {
  text-align: left;
  font-weight: 700;
  color: var(--graphite);
  padding-block-end: var(--space-3xs);
}

.v-matrix th,
.v-matrix td {
  text-align: left;
  padding: var(--space-3xs) var(--space-2xs);
  border-block-end: 1px solid var(--hairline);
}

.v-matrix th {
  font-weight: 700;
  color: var(--deep-ocean);
}

.v-matrix td:last-child {
  font-family: var(--font-heading);
  font-weight: 800;
  color: var(--deep-ocean);
  white-space: nowrap;
}
