/* product.css - product-page styles: media gallery, variant picker, buy controls (ST-M3).
 *
 * OWNED BY ST-M3. Do not edit from another milestone.
 *
 * Consumes the design tokens declared inline by the layout (--primary/--bg/--text/--maxw)
 * and the per-section style props stamped on .nscms-section (see base.css). Served
 * fingerprinted + immutable via {{ 'product.css' | asset_url }}.
 *
 * Merchants never write CSS (D2 in STOREFRONT_THEME_PARITY_PLAN.md), so every layout choice
 * here is driven by a class the section's SCHEMA controls (media position/width, image shape,
 * thumbnail placement, picker style) - never by a free-text style hook.
 */

/* --- layout ------------------------------------------------------------------------- */

.product-main__layout {
  display: grid;
  gap: 1.5rem;
  align-items: start;
}

/* Two columns from the tablet breakpoint up; a single stacked column on phones. The
 * media_width setting picks the split, media_position picks the side. */
@media (min-width: 750px) {
  .product-main__layout {
    grid-template-columns: 1fr 1fr;
    gap: 2.5rem;
  }

  .product-main--mw-small .product-main__layout {
    grid-template-columns: 4fr 6fr;
  }

  .product-main--mw-large .product-main__layout {
    grid-template-columns: 6fr 4fr;
  }

  .product-main--media-right .product-main__media {
    order: 2;
  }

  .product-main--no-media .product-main__layout {
    grid-template-columns: minmax(0, 46rem);
    justify-content: center;
  }
}

.product-main__info > * + * {
  margin-top: 1rem;
}

.product-breadcrumbs {
  font-size: 0.85rem;
  opacity: 0.75;
  margin-bottom: 1rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.product-breadcrumbs__sep {
  opacity: 0.5;
}

/* --- media gallery ------------------------------------------------------------------ */

.product-media__stage {
  position: relative;
  border-radius: 12px;
  overflow: hidden;
  background: rgba(0, 0, 0, 0.03);
}

.product-media__item {
  display: none;
  margin: 0;
}

.product-media__item.is-active {
  display: block;
}

.product-media__item img,
.product-media__zoom {
  display: block;
  width: 100%;
}

.product-media__item img {
  height: auto;
  object-fit: cover;
}

/* Dawn's `constrain_to_viewport`, on by default. Without it the stage is `width:100%;
 * height:auto`, so a large source image renders as tall as its own aspect ratio demands and
 * shoves the price and Add-to-cart button below the fold - which is exactly what a 1500x1500
 * product photo did here. Dawn caps it at max(min-height, calc(100vh - offset)); same idea.
 * width:auto + max-width:100% letterboxes instead of cropping, so `natural` shapes are safe. */
.product-main--constrain .product-media__item img,
.product-main--constrain .product-media__zoom {
  max-height: calc(100vh - 11rem);
  width: auto;
  max-width: 100%;
  margin-left: auto;
  margin-right: auto;
}

/* Image shape (block setting "ratio"). "natural" leaves the file's own aspect ratio. */
.product-media--square .product-media__item img {
  aspect-ratio: 1 / 1;
}

.product-media--portrait .product-media__item img {
  aspect-ratio: 3 / 4;
}

.product-media--landscape .product-media__item img {
  aspect-ratio: 4 / 3;
}

.product-media__thumbs {
  list-style: none;
  padding: 0;
  margin: 0.6rem 0 0;
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.product-media__thumb {
  padding: 0;
  border: 2px solid transparent;
  border-radius: 8px;
  background: none;
  cursor: pointer;
  overflow: hidden;
  line-height: 0;
  width: 4.25rem;
}

.product-media__thumb img {
  width: 100%;
  height: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  display: block;
}

.product-media__thumb.is-active {
  border-color: var(--primary);
}

.product-media__thumb:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* Thumbnails beside the stage (block setting "thumbnails: left"), desktop only. */
@media (min-width: 750px) {
  .product-media--thumbs-left {
    display: grid;
    grid-template-columns: 4.75rem minmax(0, 1fr);
    gap: 0.75rem;
  }

  .product-media--thumbs-left .product-media__stage {
    grid-column: 2;
    grid-row: 1;
  }

  .product-media--thumbs-left .product-media__thumbs {
    grid-column: 1;
    grid-row: 1;
    margin: 0;
    flex-direction: column;
  }
}

/* --- title / price ------------------------------------------------------------------ */

.product__vendor {
  margin: 0;
  font-size: 0.85rem;
  text-transform: var(--caps-transform, uppercase);
  letter-spacing: var(--caps-spacing, 0.06em);
  opacity: 0.7;
}

.product__title {
  margin: 0;
  font-size: 1.9rem;
  line-height: 1.2;
}

/* The shared `price` snippet renders here too. card.css scopes its own price rules under
 * .product-card and leaves .price to this file for the product page, so these are the
 * product-page presentation of the SAME markup - the amounts still come from one snippet. */
.product-main .price {
  font-size: 1.35rem;
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.product-main .price__now {
  font-weight: 600;
}

.product-main .price s {
  font-weight: 400;
  font-size: 1rem;
  opacity: 0.65;
}

.product-main .price__badge {
  font-size: 0.95rem;
}

.product-main .unit-price {
  font-size: 0.85rem;
  opacity: 0.7;
}

.product__price-range,
.product__note,
.product__availability,
.product__trust,
.product__meta {
  margin: 0;
  font-size: 0.9rem;
  opacity: 0.75;
}

.product__meta p {
  margin: 0.15rem 0;
}

/* --- variant pickers ---------------------------------------------------------------- */

.variant-picker {
  display: grid;
  gap: 0.9rem;
}

.variant-picker__option {
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;
}

.variant-picker__legend {
  padding: 0;
  font-size: 0.9rem;
  margin-bottom: 0.4rem;
  display: flex;
  gap: 0.4rem;
}

.variant-picker__name {
  font-weight: 600;
}

.variant-picker__chosen {
  opacity: 0.7;
}

.variant-picker__select {
  font: inherit;
  padding: 0.55rem 0.7rem;
  border: 1px solid rgba(0, 0, 0, 0.25);
  border-radius: 8px;
  background: var(--bg);
  color: inherit;
  width: 100%;
  max-width: 22rem;
}

.variant-picker__values {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* The radio is the accessible control; the chip is its visible skin. */
.variant-picker__value {
  position: relative;
  display: inline-flex;
  margin: 0;
  cursor: pointer;
}

.variant-picker__value input {
  position: absolute;
  inset: 0;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}

.variant-picker__chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: 1px solid rgba(0, 0, 0, 0.25);
  border-radius: 999px;
  padding: 0.4rem 0.85rem;
  font-size: 0.9rem;
  line-height: 1.2;
  background: var(--bg);
}

.variant-picker__value input:checked + .variant-picker__chip {
  border-color: var(--primary);
  box-shadow: inset 0 0 0 1px var(--primary);
}

.variant-picker__value input:focus-visible + .variant-picker__chip {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* A combination with no variant at all. "disable" strikes it through but keeps it
 * selectable (so the shopper sees why); "hide" removes it - product.js sets both. */
.variant-picker__value.is-unavailable .variant-picker__chip {
  opacity: 0.45;
  text-decoration: line-through;
}

.variant-picker__value[hidden],
.variant-picker__select option[hidden] {
  display: none;
}

/* Swatches: a curated palette keyed off data-swatch. Merchant option values reach only the
 * ATTRIBUTE, never a CSS declaration, so nothing can be injected; an unrecognised value
 * keeps the neutral dot and reads as a labelled chip. */
.variant-picker--swatches .variant-picker__swatch {
  width: 1.05rem;
  height: 1.05rem;
  border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, 0.2);
  background: linear-gradient(135deg, #d4d4d8, #a1a1aa);
  flex: none;
}

.variant-picker--swatches [data-swatch="black"] .variant-picker__swatch { background: #111111; }
.variant-picker--swatches [data-swatch="white"] .variant-picker__swatch { background: #ffffff; }
.variant-picker--swatches [data-swatch="grey"] .variant-picker__swatch,
.variant-picker--swatches [data-swatch="gray"] .variant-picker__swatch { background: #9ca3af; }
.variant-picker--swatches [data-swatch="silver"] .variant-picker__swatch { background: #d1d5db; }
.variant-picker--swatches [data-swatch="red"] .variant-picker__swatch { background: #dc2626; }
.variant-picker--swatches [data-swatch="merah"] .variant-picker__swatch { background: #dc2626; }
.variant-picker--swatches [data-swatch="pink"] .variant-picker__swatch { background: #ec4899; }
.variant-picker--swatches [data-swatch="orange"] .variant-picker__swatch { background: #f97316; }
.variant-picker--swatches [data-swatch="yellow"] .variant-picker__swatch { background: #facc15; }
.variant-picker--swatches [data-swatch="green"] .variant-picker__swatch { background: #16a34a; }
.variant-picker--swatches [data-swatch="hijau"] .variant-picker__swatch { background: #16a34a; }
.variant-picker--swatches [data-swatch="teal"] .variant-picker__swatch { background: #0d9488; }
.variant-picker--swatches [data-swatch="blue"] .variant-picker__swatch { background: #2563eb; }
.variant-picker--swatches [data-swatch="biru"] .variant-picker__swatch { background: #2563eb; }
.variant-picker--swatches [data-swatch="navy"] .variant-picker__swatch { background: #1e3a8a; }
.variant-picker--swatches [data-swatch="purple"] .variant-picker__swatch { background: #7c3aed; }
.variant-picker--swatches [data-swatch="brown"] .variant-picker__swatch { background: #92400e; }
.variant-picker--swatches [data-swatch="beige"] .variant-picker__swatch { background: #e7d8c0; }
.variant-picker--swatches [data-swatch="cream"] .variant-picker__swatch { background: #f5efdc; }
.variant-picker--swatches [data-swatch="gold"] .variant-picker__swatch { background: #d4af37; }

/* --- quantity ----------------------------------------------------------------------- */

.product-qty__label {
  display: block;
  font-size: 0.9rem;
  font-weight: 600;
  margin-bottom: 0.4rem;
}

.product-qty__control {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid rgba(0, 0, 0, 0.25);
  border-radius: 999px;
  overflow: hidden;
}

.product-qty__step {
  font: inherit;
  border: 0;
  background: transparent;
  color: inherit;
  padding: 0.4rem 0.8rem;
  cursor: pointer;
  line-height: 1.4;
}

.product-qty__step:hover {
  background: rgba(0, 0, 0, 0.06);
}

.product-qty__input {
  font: inherit;
  width: 3.5rem;
  text-align: center;
  border: 0;
  background: transparent;
  color: inherit;
  padding: 0.4rem 0.2rem;
  -moz-appearance: textfield;
}

.product-qty__input::-webkit-outer-spin-button,
.product-qty__input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.product-qty--plain .product-qty__control {
  border-radius: 8px;
}

.product-qty--plain .product-qty__input {
  width: 5rem;
  text-align: left;
  padding-left: 0.6rem;
}

/* --- buy button + availability ------------------------------------------------------ */

/* THE product-page button. .reviews-form__submit is in the same selector group on purpose,
 * not a second rule that happens to look similar: "Submit review" sits a few hundred pixels
 * under "Add to cart", and when it was the browser's default grey button that gap was the most
 * obvious unfinished thing on the page. Sharing the rule means it cannot drift again. */
.product__submit,
.reviews-form__submit {
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  border-radius: 999px;
  padding: 0.8rem 1.6rem;
  border: 1px solid var(--primary);
  background: var(--primary);
  color: #fff;
}

.product__submit--outline {
  background: transparent;
  color: var(--primary);
}

.product__submit--full {
  display: block;
  width: 100%;
}

.product__submit:hover,
.reviews-form__submit:hover {
  filter: brightness(1.08);
}

.product__submit[disabled],
.product__submit[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  filter: none;
}

.product__availability--out {
  opacity: 1;
}

/* Low-stock line ("Only 2 left"). Full opacity and a warm accent because it is the one line
   in this column meant to be READ rather than scanned; the availability line above it stays
   muted so the two do not compete. Server-rendered `hidden` when there is nothing to say. */
.product__inventory {
  margin: 0;
  font-size: 0.9rem;
  font-weight: 600;
  color: #b45309;
}

.product__inventory[hidden] {
  display: none;
}

html[data-theme="dark"] .product__inventory {
  color: #fbbf24;
}

/* --- maximum per order (0611, snippets/quantity-input.liquid) ---------------------------------
   "Maks. 5 per pesanan" under the quantity, and the soft-yellow "Kamu sudah punya 5 di keranjang"
   product.js shows when the shopper tries to go past it. Rendered only for a product with a limit. */
.product-qty__max {
  margin: 0.4rem 0 0;
  font-size: 0.8125rem;
  opacity: 0.75;
}

.product-qty__max.is-hit {
  opacity: 1;
  font-weight: 600;
}

.product-qty__limit-msg {
  margin: 0.5rem 0 0;
  padding: 0.5rem 0.75rem;
  border-radius: 8px;
  background: #fff4d6;
  color: #3b2a05;
  font-size: 0.8125rem;
  line-height: 1.5;
}

.product-qty__limit-msg[hidden] {
  display: none;
}

.product-qty__step.is-at-max {
  opacity: 0.4;
}

/* --- back-in-stock capture (audit F10.6) ---------------------------------------------
   Rendered only on the sold-out path, directly under the disabled buy button. Boxed and
   inset rather than styled as a second buy button: it is a consolation, not a purchase, and
   dressing it like the primary action on a page whose primary action is disabled reads as a
   bait-and-switch. Spacing lives here rather than inline so the ST-M1a per-section padding
   props stay authoritative (see the header of sections/main_product.liquid).

   The controls are form-associated to a <form> elsewhere in the document (the one-form
   invariant), so this container is a plain div and must supply its own layout. */
.back-in-stock {
  margin: 0.9rem 0 0;
  padding: 0.85rem 0.9rem;
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.02);
}

.back-in-stock__heading {
  margin: 0 0 0.55rem;
  font-weight: 600;
}

.back-in-stock__field {
  display: block;
  margin: 0 0 0.55rem;
}

.back-in-stock__label {
  display: block;
  font-size: 0.85rem;
  margin-bottom: 0.2rem;
  opacity: 0.8;
}

.back-in-stock__input,
.back-in-stock__select {
  width: 100%;
  padding: 0.55rem 0.7rem;
  border: 1px solid rgba(0, 0, 0, 0.25);
  border-radius: 8px;
  font: inherit;
  background: #fff;
  color: inherit;
}

.back-in-stock__submit {
  padding: 0.55rem 1rem;
  border-radius: 8px;
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.back-in-stock__note {
  margin: 0.6rem 0 0;
  font-size: 0.8rem;
  opacity: 0.7;
}

html[data-theme="dark"] .back-in-stock {
  border-color: rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.04);
}

html[data-theme="dark"] .back-in-stock__input,
html[data-theme="dark"] .back-in-stock__select {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.25);
}

/* --- collapsible rows / description ------------------------------------------------- */

.product__row {
  border-top: 1px solid rgba(0, 0, 0, 0.12);
  padding: 0.6rem 0;
}

.product__row > summary {
  cursor: pointer;
  font-weight: 600;
  list-style: none;
}

.product__row > summary::-webkit-details-marker {
  display: none;
}

.product__row > summary::after {
  content: " +";
  opacity: 0.6;
}

.product__row[open] > summary::after {
  content: " \2212";
}

.product__share {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.9rem;
}

.product__share-copy {
  font: inherit;
  cursor: pointer;
  border: 1px solid rgba(0, 0, 0, 0.25);
  background: transparent;
  color: inherit;
  border-radius: 999px;
  padding: 0.25rem 0.7rem;
}

/* --- reviews (sections/product_reviews.liquid) ---------------------------------------
 * The review list + "Write a review" form. Everything here used to be an inline `style=`
 * attribute on the section, which meant it ignored the merchant's palette AND dark mode, and
 * the form rendered as raw browser controls under a fully styled Add-to-cart button.
 *
 * The field frame is deliberately the SAME treatment as the variant picker's <select> and the
 * cart's checkout inputs (1px border at 25% ink, 8px radius, `font: inherit`, transparent
 * background) so all three read as one form language. The submit button shares the
 * .product__submit rule above rather than restating it.
 */

.reviews {
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(0, 0, 0, 0.12);
  --reviews-star: #f5a623;
}

.reviews__head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.reviews__title {
  margin: 0;
  font-size: 1.35rem;
  line-height: 1.2;
}

.reviews__rating {
  display: flex;
  align-items: baseline;
  gap: 0.35rem;
  margin: 0;
  font-size: 0.95rem;
}

.reviews__stars {
  color: var(--reviews-star);
  letter-spacing: 0.06em;
}

.reviews__average {
  font-weight: 600;
}

.reviews__count {
  opacity: 0.7;
}

.reviews__notice {
  margin: 1rem 0 0;
  padding: 0.7rem 0.9rem;
  border: 1px solid rgba(22, 121, 76, 0.35);
  border-radius: 10px;
  background: rgba(22, 121, 76, 0.08);
  color: #16794c;
  font-size: 0.9rem;
}

.reviews__empty {
  margin: 1rem 0 0;
  opacity: 0.7;
}

.reviews__list {
  list-style: none;
  margin: 1.25rem 0 0;
  padding: 0;
  display: grid;
  gap: 1rem;
}

.review {
  padding: 0.9rem 1rem;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 12px;
}

.review__meta {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0;
  font-size: 0.9rem;
}

.review__date {
  opacity: 0.6;
}

.review__body {
  margin: 0.4rem 0 0;
  line-height: 1.5;
}

/* --- the write-a-review form --------------------------------------------------------- */

.reviews-form {
  margin-top: 1.75rem;
  max-width: 34rem;
}

.reviews-form__title {
  margin: 0 0 0.9rem;
  font-size: 1.05rem;
}

.reviews-form__row {
  display: grid;
  gap: 0.9rem;
}

@media (min-width: 600px) {
  .reviews-form__row {
    /* Name takes the room; Rating only needs to fit five stars. */
    grid-template-columns: minmax(0, 1fr) auto;
  }
}

.reviews-form__field {
  margin: 0 0 0.9rem;
}

.reviews-form__row .reviews-form__field {
  margin: 0;
}

.reviews-form__row + .reviews-form__field {
  margin-top: 0.9rem;
}

.reviews-form__label {
  display: block;
  font-size: 0.9rem;
  font-weight: 600;
  margin-bottom: 0.35rem;
}

.reviews-form__control {
  font: inherit;
  width: 100%;
  box-sizing: border-box;
  padding: 0.55rem 0.7rem;
  border: 1px solid rgba(0, 0, 0, 0.25);
  border-radius: 8px;
  background: var(--bg);
  color: inherit;
}

.reviews-form__field--rating .reviews-form__control {
  width: auto;
  min-width: 9rem;
}

.reviews-form__control:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
}

.reviews-form__textarea {
  resize: vertical;
  line-height: 1.5;
}

.reviews-form__captcha {
  margin-bottom: 0.9rem;
}

/* --- sticky mobile buy bar ----------------------------------------------------------- */

.product-buybar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.6rem 1rem;
  background: var(--bg);
  border-top: 1px solid rgba(0, 0, 0, 0.14);
  box-shadow: 0 -6px 18px rgba(0, 0, 0, 0.12);
  /* Hidden until product.js reveals it; never shown at all with JS disabled, which loses
   * nothing because the primary Add-to-cart button is the same submit. */
  visibility: hidden;
  transform: translateY(110%);
  transition: transform 0.18s ease-out;
}

.product-buybar.is-active {
  visibility: visible;
  transform: none;
}

.product-main .product-buybar__price .price {
  font-size: 1rem;
  gap: 0.4rem;
}

.product-main .product-buybar__price .price s {
  font-size: 0.85rem;
}

/* The bar is a compact mirror of the price block; the unit price would not fit. */
.product-buybar__price .unit-price {
  display: none;
}

.product-buybar__submit {
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  border: 0;
  border-radius: 999px;
  padding: 0.6rem 1.2rem;
  background: var(--primary);
  color: var(--solid-button-text, #fff); /* 10-16 G2: the scheme's Solid button text; white when unset */
  white-space: nowrap;
}

/* The bar is a phone affordance only. */
@media (min-width: 750px) {
  .product-buybar {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .product-buybar {
    transition: none;
  }
}

/* --- dark mode (shopper preference; mirrors base.css) -------------------------------- */

html[data-theme="dark"] .product-media__stage {
  background: rgba(255, 255, 255, 0.05);
}

html[data-theme="dark"] .variant-picker__chip,
html[data-theme="dark"] .product-qty__control,
html[data-theme="dark"] .product__share-copy {
  border-color: #334155;
}

html[data-theme="dark"] .product__row {
  border-top-color: #334155;
}

html[data-theme="dark"] .product-qty__step:hover {
  background: rgba(255, 255, 255, 0.08);
}

html[data-theme="dark"] .product-buybar {
  border-top-color: #334155;
}

html[data-theme="dark"] .reviews {
  border-top-color: #334155;
}

html[data-theme="dark"] .review,
html[data-theme="dark"] .reviews-form__control {
  border-color: #334155;
}

html[data-theme="dark"] .reviews__notice {
  border-color: #1d4d33;
  background: rgba(134, 239, 172, 0.1);
  color: #86efac;
}

/* --- promos disclosure (product page) ----------------------------------------------------
 * The offers available on this product, under the price. A native <details>, so it works with
 * JavaScript off; the marker is replaced with our own chevron because the UA triangle differs
 * per browser and this sits directly beside money.
 *
 * Content is composed in Go (storefront/promos.go) — nothing here formats anything.
 */
.promos {
  margin: 0.75rem 0 0;
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.015);
}

.promos__summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.75rem;
  cursor: pointer;
  font-size: 0.9rem;
  font-weight: 600;
  list-style: none; /* Firefox */
}

/* Safari/Chrome draw their own triangle through this pseudo-element. */
.promos__summary::-webkit-details-marker {
  display: none;
}

.promos__summary::after {
  content: "";
  margin-left: auto;
  width: 0.5rem;
  height: 0.5rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-0.1rem, -0.1rem);
  opacity: 0.6;
  transition: transform 0.15s ease;
}

.promos[open] .promos__summary::after {
  transform: rotate(-135deg) translate(-0.15rem, -0.15rem);
}

/* The "%" mark. A glyph rather than an icon file: one less asset, and it scales with the text. */
.promos__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 999px;
  background: var(--primary, #1a1a1a);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  flex: none;
}

.promos__body {
  padding: 0 0.75rem 0.7rem;
}

.promos__group + .promos__group {
  margin-top: 0.6rem;
}

.promos__group-label {
  margin: 0 0 0.25rem;
  font-size: 0.72rem;
  letter-spacing: var(--caps-spacing, 0.06em);
  text-transform: var(--caps-transform, uppercase);
  opacity: 0.55;
}

.promos__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.4rem;
}

/* Each offer is three stacked facts: the terms, any condition, then whose promo it is. The
   label leads because it is the part the shopper is deciding on. */
.promos__item {
  display: grid;
  gap: 0.1rem;
  padding-left: 0.8rem;
  position: relative;
  font-size: 0.85rem;
}

.promos__item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.5rem;
  width: 4px;
  height: 4px;
  border-radius: 999px;
  background: currentColor;
  opacity: 0.4;
}

.promos__label {
  font-weight: 600;
}

.promos__terms {
  font-size: 0.8rem;
  opacity: 0.7;
}

.promos__title {
  font-size: 0.78rem;
  opacity: 0.55;
}

.promos__note {
  margin: 0.6rem 0 0;
  font-size: 0.75rem;
  opacity: 0.6;
}

html[data-theme="dark"] .promos {
  border-color: rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.03);
}

/* A members-only offer, called out so it cannot be mistaken for a universal one. */
.promos__exclusive {
  display: inline-block;
  margin-left: 0.35rem;
  padding: 0.05rem 0.3rem;
  border-radius: 3px;
  background: var(--primary, #1a1a1a);
  color: #fff;
  font-style: normal;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: var(--caps-spacing, 0.04em);
  text-transform: var(--caps-transform, uppercase);
  vertical-align: 0.05rem;
}

/* Whether an offer stacks. A small, low-contrast line rather than a badge: it is a caveat the
   shopper needs when reconciling three offers against one discount, not a selling point. */
.promos__stack {
  font-size: 0.72rem;
  letter-spacing: 0.02em;
}

.promos__stack--yes {
  color: #1c7c4a;
}

.promos__stack--no {
  opacity: 0.6;
}

html[data-theme="dark"] .promos__stack--yes {
  color: #6ecf9b;
}

/* ===================================================================================== *
 * BASIC (ST-M10a) — the product page as the design draws it (Figma 311:3502).
 *
 * Appended rather than interleaved so everything above keeps its cascade position; each rule
 * below is the design's measurement, cited by node. At 1920: two 738px columns 64px apart, the
 * gallery a stack of 3:4 images 20px apart, the info column a quiet stack of 14px type in the
 * design's warm greys, with one dark full-width button.
 * ===================================================================================== */

@media (min-width: 750px) {
  .product-main__layout {
    column-gap: clamp(2.5rem, 3.33vw, 4rem);
  }
}

/* The info column follows the reader down the stacked gallery. */
@media (min-width: 990px) {
  .product-main__info {
    position: sticky;
    top: 1.5rem;
  }

  /* 10-15-C §2 (S7): the section's "Keep the details in view…" switch and its gap. The rule above
     stays the default (pinned, 1.5rem = 24px); a merchant who turns it off or picks another gap gets
     one of these classes from main_product.liquid. */
  .product-main--info-static .product-main__info {
    position: static;
  }

  .product-main--info-top .product-main__info {
    top: var(--product-info-top, 1.5rem);
  }
}

/* 10-15-C §5 (X4): the decorative image block, pinned to the bottom corner of the details column.
   The column becomes its positioning box only when the block prints (main_product.liquid adds
   --decor); on a wide screen it stays sticky, which is a positioning box too. Taps go through the
   picture (pointer-events: none). Hidden on phones: there the details sit under the photos at full
   width, so a corner picture would land on the last block's words. */
.product-main__info--decor {
  position: relative;
}

@media (min-width: 990px) {
  .product-main:not(.product-main--info-static) .product-main__info--decor {
    position: sticky;
  }
}

.product-main__info > .product__decor {
  position: absolute;
  bottom: var(--decor-y, 0px);
  right: var(--decor-x, 0px);
  z-index: 1;
  width: var(--decor-w, 96px);
  max-width: 50%;
  margin: 0;
  pointer-events: none;
}

.product-main__info > .product__decor--left {
  right: auto;
  left: var(--decor-x, 0px);
}

.product__decor img {
  display: block;
  width: 100%;
  height: auto;
}

@media (max-width: 749px) {
  .product-main__info > .product__decor {
    display: none;
  }
}

/* Breadcrumb (311:3133): small tracked capitals in the caption grey, 48px above the columns. */
.product-breadcrumbs {
  margin-bottom: 3rem;
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: var(--caps-spacing, 0.0875rem);
  text-transform: var(--caps-transform, uppercase);
  color: #767069;
  opacity: 1;
}

.product-breadcrumbs a {
  color: inherit;
}

.product-breadcrumbs a:hover {
  color: #0f0c0b;
  text-decoration: none;
}

.product-breadcrumbs__sep {
  opacity: 1;
}

/* Gallery (311:3136), layout "stacked": every image, one under the next. */
.product-media__stage {
  border-radius: 0;
  background: transparent;
}

.product-media--thumbs-stacked .product-media__stage {
  display: grid;
  gap: var(--gallery-gap, 1.25rem); /* gallery "Space between photos"; 20px when unset */
}

.product-media--thumbs-stacked .product-media__item {
  display: block;
  background: #e7e7e9;
}

.product-media--thumbs-stacked .product-media__item img {
  height: 100%;
}

/* 10-15-C §5 (X3): small thumbnails on a white card over the stacked photos. The card follows the
   gallery in the markup; sticky pins it --jump-gap above the bottom of the screen while the photos
   scroll, and the negative top margin (its own height plus the gap) lays it over the last photo's
   foot at rest, so it adds no height to the column. The thumbnails take the photos' shape (natural:
   4:5). The chosen photo's thumbnail is full strength, the others half. Sits above the phone buy
   bar on a phone. */
.product-jump {
  --jump-gap: 2rem;
  --jump-pad: 4px;
  --jump-h: calc(var(--jump-w, 32px) * 1.25);
  position: sticky;
  bottom: var(--jump-gap);
  z-index: 2;
  display: flex;
  gap: 4px;
  width: fit-content;
  max-width: calc(100% - 2rem);
  margin: calc(-1 * (var(--jump-h) + 2 * var(--jump-pad) + var(--jump-gap))) auto var(--jump-gap);
  padding: var(--jump-pad);
  overflow-x: auto;
  background: #fff;
  border-radius: calc(var(--jump-r, 8px) + var(--jump-pad));
  scrollbar-width: none;
}

.product-jump[hidden] {
  display: none;
}

/* 10-16 §8: "Only the chosen option's photos". The other options' photos, their thumbnails and their
   cards are printed (and later toggled) with the hidden attribute. !important beats the stacked
   layout's display:block and the no-script rule that shows every photo. Nothing carries the
   attribute with the setting off. */
.product-media__item[hidden],
.product-media__thumbs li[hidden],
.product-jump__thumb[hidden] {
  display: none !important;
}

.product-jump--square {
  --jump-h: var(--jump-w, 32px);
}

.product-jump--portrait {
  --jump-h: calc(var(--jump-w, 32px) * 4 / 3);
}

.product-jump--landscape {
  --jump-h: calc(var(--jump-w, 32px) * 3 / 4);
}

.product-jump__thumb {
  position: relative;
  flex: none;
  width: var(--jump-w, 32px);
  height: var(--jump-h);
  padding: 0;
  border: 0;
  border-radius: var(--jump-r, 8px);
  overflow: hidden;
  background: #e7e7e9;
  cursor: pointer;
  opacity: 0.5;
  transition: opacity 0.2s ease;
}

.product-jump__thumb:hover,
.product-jump__thumb.is-active {
  opacity: 1;
}

.product-jump__thumb:focus-visible {
  opacity: 1;
  outline: 2px solid var(--primary);
  outline-offset: 1px;
}

.product-jump__thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.product-jump__label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* A thumbnail scrolls its photo to the top, below the space the details column keeps above it
   (the sticky offset, where a pinned header's height goes). */
.product-main__media:has(> .product-jump) .product-media__item {
  scroll-margin-top: var(--product-info-top, 1.5rem);
}

@media (max-width: 749px) {
  .product-jump {
    --jump-gap: 5rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .product-jump__thumb {
    transition: none;
  }
}

/* Title block (311:3359): a small tracked line above (vendor), then the name in the heading face
   at 40px, uppercase, 1.6px tracking. 8px between them, 16px to the price. */
.product__vendor {
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: var(--caps-spacing, 0.125rem);
  color: #767069;
  opacity: 1;
}

.product__title {
  font-family: var(--font-heading, var(--font-body));
  font-size: clamp(1.75rem, 1.2rem + 1.2vw, 2.5rem);
  font-weight: 400;
  line-height: 1.22;
  letter-spacing: var(--caps-spacing, 0.1rem);
  text-transform: var(--caps-transform, uppercase);
}

.product__vendor + .product__title {
  margin-top: 0.5rem;
}

/* Price (311:3154): 20px medium with 2px tracking, the original struck through in the caption grey,
   and the discount as an outlined chip — "15% OFF" in 11px capitals. */
.product-main .price {
  align-items: center;
  gap: 0.5rem 0.75rem;
  font-size: 1.25rem;
  letter-spacing: 0.125rem;
}

.product-main .price__now {
  font-weight: 500;
}

.product-main .price s {
  order: 2;
  font-size: 1.25rem;
  color: #595550;
  opacity: 1;
}

.product-main .price__now {
  order: 1;
}

.product-main .price__badge {
  order: 3;
  padding: 0.1875rem 0.4375rem;
  border: 1px solid #0f0c0b;
  color: #0f0c0b;
  font-size: 0.6875rem;
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: var(--caps-spacing, 0.06875rem);
  text-transform: var(--caps-transform, uppercase);
}

.product__tax-note {
  margin: 0.5rem 0 0;
  font-size: 0.875rem;
  line-height: 1.5;
  color: #414148;
}

/* "Earn Rp 5.000 gift points" (BUILD_BRIEF_2026-10-12-J §6): a quiet line under the price. */
.product__earn {
  margin: 0.5rem 0 0;
  font-size: 0.875rem;
  line-height: 1.5;
  font-weight: 600;
  color: #1f7a4d;
}
.product__earn[hidden] {
  display: none;
}

.product__description {
  font-size: 0.875rem;
  line-height: 1.5;
  color: #414148;
}

.product__description > :first-child {
  margin-top: 0;
}

.product__description > :last-child {
  margin-bottom: 0;
}

/* The column's rhythm: 24px between the groups (311:3148). */
.product-main__info > * + * {
  margin-top: 1.5rem;
}

.product-main__info > .product__vendor + .product__title,
.product-main__info > .product__title + .product__price-block {
  margin-top: 1rem;
}

/* Pickers (311:3163 / 311:3172): the option name in 14px medium capitals at the left and the
   chosen value at the right, then square chips — 42px tall, a 1px warm-grey rule, 8px apart,
   the chosen one drawn in black. A struck-through, faded chip is a combination that does not
   exist. */
.variant-picker {
  gap: 1.5rem;
}

.variant-picker__legend {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  margin-bottom: 0.75rem;
  font-size: 0.875rem;
}

.variant-picker__name {
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: var(--caps-spacing, 0.0875rem);
  text-transform: var(--caps-transform, uppercase);
  color: #0f0c0b;
}

.variant-picker__chosen {
  font-size: 1rem;
  color: #595550;
  opacity: 1;
}

.variant-picker__chip {
  justify-content: center;
  min-width: 3.25rem;
  height: 2.625rem;
  padding: 0 0.75rem;
  border: 1px solid #dcdad8;
  border-radius: 0;
  font-size: 0.78125rem;
  letter-spacing: 0.0625rem;
  color: #595550;
}

.variant-picker__value:hover .variant-picker__chip {
  border-color: #767069;
}

.variant-picker__value input:checked + .variant-picker__chip {
  border-color: #0f0c0b;
  box-shadow: inset 0 0 0 1px #0f0c0b;
  color: #0f0c0b;
}

.variant-picker__select {
  height: 2.625rem;
  border: 1px solid #dcdad8;
  border-radius: 0;
}

/* Swatches (311:3167): a 34px square frame with a 26px colour inside it. Only a chip that carries
   data-swatch is a swatch — the template sets it for known colours of a colour option, so a Size
   option in the same picker keeps the ordinary text chip above. */
.variant-picker--swatches .variant-picker__chip[data-swatch] {
  min-width: 0;
  width: 2.125rem;
  height: 2.125rem;
  padding: 3px;
}

.variant-picker--swatches [data-swatch] .variant-picker__swatch {
  width: 100%;
  height: 100%;
  border: 0;
  border-radius: 0;
}

.variant-picker--swatches [data-swatch] .variant-picker__text {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

/* Quantity beside the buy button beside the wishlist heart (311:3373): the stepper is 124px wide
   with its label above it, the button takes the rest of the row, the 48px heart closes it, all
   three bottoms aligned. On a phone the stepper stacks above; the button and heart share a row. */
.product__submit:has(+ .product__wish) {
  display: inline-flex;
  width: calc(100% - 3.75rem);
  vertical-align: top;
}

.product__wish {
  margin-left: 0.75rem;
  vertical-align: top;
}

@media (min-width: 750px) {
  .product-main__info {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    column-gap: 1.5rem;
  }

  .product-main__info > * {
    grid-column: 1 / -1;
  }

  .product-main__info > .product__submit:has(+ .product__wish) {
    grid-column: 1 / 3;
    width: auto;
  }

  .product-main__info > .product-qty:has(+ .product__submit) {
    grid-column: 1;
  }

  .product-main__info > .product-qty + .product__submit {
    grid-column: 2;
    align-self: end;
  }

  .product-main__info > .product__submit + .product__wish {
    grid-column: 3;
    align-self: end;
    margin-left: -0.75rem;
  }
}

.product-qty__label {
  margin-bottom: 0.75rem;
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: var(--caps-spacing, 0.0875rem);
  text-transform: var(--caps-transform, uppercase);
  color: #0b0b0e;
}

.product-qty__control {
  height: 3rem;
  border: 1px solid #dcdad8;
  border-radius: 0;
}

.product-qty__step {
  width: 2.75rem;
  padding: 0;
  color: #595550;
  font-size: 1rem;
}

.product-qty__input {
  width: 2.125rem;
  font-size: 0.84375rem;
  font-weight: 500;
}

/* The buy button (311:3207): black, square, 48px, a bag glyph and tracked capitals. */
.product__submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5625rem;
  min-height: 3rem;
  padding: 0 1.5rem;
  border: 1px solid #0f0c0b;
  border-radius: var(--button-radius, 0); /* 10-15-C §1: Button shape; square when unset */
  background: #0f0c0b;
  color: #fff;
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: 0.124rem;
  text-transform: var(--button-text-transform, uppercase); /* 10-15-C §3: Button text; capitals when unset */
}

.product__submit--full {
  display: flex;
}

.product__submit:hover {
  filter: none;
  background: #2b2724;
}

.product__submit--outline {
  background: transparent;
  color: #0f0c0b;
}

.product__submit-icon {
  width: 1rem;
  height: 1rem;
  flex: none;
}

/* 10-15-C §2 (S8): "Add to bag · Rp 128.000". The price keeps its own case (the label above is set
   in capitals, which would turn "Rp" into "RP") and its digits do not jump as the quantity changes. */
.product__submit-price {
  display: inline-flex;
  align-items: center;
  gap: 0.5625rem;
  text-transform: none;
  font-variant-numeric: tabular-nums;
}

/* 10-15-C fix4 (S8): the label is never cut or squeezed. The label and the price each stay whole
   (nowrap: the price moves as one unit), and when the two do not fit on one line in the button,
   product.js sets `hidden` on the price, so the button is exactly today's button without the price:
   every rule below is limited to a button whose price is SHOWN. Without script a narrow priced
   button simply wraps the price under the label. Between 750 and 1199px the buy row is at its
   narrowest, so a priced button is set a little smaller and tighter there. */
.product__submit-price[hidden] {
  display: none;
}

.product__submit:has(> .product__submit-price:not([hidden])) {
  flex-wrap: wrap;
  column-gap: 0.5625rem;
  row-gap: 0.125rem;
}

.product__submit:has(> .product__submit-price:not([hidden])) > span {
  white-space: nowrap;
}

@media (min-width: 750px) and (max-width: 1199px) {
  .product__submit:has(> .product__submit-price:not([hidden])) {
    padding-inline: 1rem;
    font-size: 0.8125rem;
    letter-spacing: 0.06rem;
  }
}

.product__availability {
  font-size: 0.875rem;
  color: #595550;
  opacity: 1;
}

/* Assurance lines (311:3219): a hairline above the first, 24px under it, then 16px glyphs in the
   caption grey beside 14px lines, 8px apart. */
.product__assurance {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  margin: 0;
  font-size: 0.875rem;
  color: #595550;
}

.product-main__info > .product__assurance + .product__assurance {
  margin-top: 0.5rem;
}

.product-main__info > :not(.product__assurance) + .product__assurance {
  padding-top: 1.5rem;
  border-top: 1px solid #e9e8e7;
}

.product__assurance-icon {
  width: 1rem;
  height: 1rem;
  flex: none;
  color: #767069;
}

/* Collapsible rows (311:3237): a hairline under each, the heading in 14px medium capitals with a
   thin chevron at the far right that turns over when open, the body in 14px caption grey. */
.product__row {
  padding: 0;
  border-top: 0;
  border-bottom: 1px solid #e7e7e9;
}

.product-main__info > :not(.product__row) + .product__row {
  border-top: 1px solid #e7e7e9;
}

.product-main__info > .product__row + .product__row {
  margin-top: 0;
}

.product__row > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 1.0625rem 0.125rem;
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: var(--caps-spacing, 0.0875rem);
  text-transform: var(--caps-transform, uppercase);
  color: #0b0b0e;
}

.product__row > summary::after,
.product__row[open] > summary::after {
  content: "";
  flex: none;
  width: 0.875rem;
  height: 0.875rem;
  opacity: 1;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M11.68 5.56 7.31 9.93a.44.44 0 0 1-.62 0L2.32 5.56a.44.44 0 0 1 .62-.62L7 9.01l4.07-4.07a.44.44 0 0 1 .61.62Z' fill='%23767069'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform 0.15s ease;
}

.product__row[open] > summary::after {
  transform: rotate(180deg);
}

.product__row > .rte,
.product__row > .body {
  padding: 0 0.125rem 1.25rem;
  font-size: 0.875rem;
  line-height: 1.5;
  color: #595550;
}

.product__row > .rte > :first-child,
.product__row > .body > :first-child {
  margin-top: 0;
}

.product__row > .rte > :last-child,
.product__row > .body > :last-child {
  margin-bottom: 0;
}

/* Custom field (metafield) rows: the same box as a collapsible row (height, hairline), so a field
   sits in the list beside "Shipping & returns" instead of a bare line squeezed between two rules.
   Label on the left in the row-heading capitals; value on the right in the caption grey. Before
   this the row borrowed .product__row's zero padding and the two spans had no style at all. */
.product__metafield {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.0625rem 0.125rem;
  font-size: 0.875rem;
  line-height: 1.5;
}

.product__metafield-label {
  flex: none;
  font-weight: 500;
  letter-spacing: var(--caps-spacing, 0.0875rem);
  text-transform: var(--caps-transform, uppercase);
  color: #0b0b0e;
}

.product__metafield-value {
  min-width: 0;
  text-align: right;
  overflow-wrap: anywhere;
  /* A multi-line text field keeps the line breaks the merchant typed. */
  white-space: pre-line;
  color: #595550;
}

/* An image file field (metafield_display.go): drawn, not printed as its URL. */
.product__metafield-value img {
  display: inline-block;
  max-width: 100%;
  max-height: 16rem;
  height: auto;
  vertical-align: top;
}

/* No label typed: the value stands alone, so it reads from the left like any other line. */
.product__metafield-value:only-child {
  text-align: left;
}

/* In the theme editor only (request.design_mode): a Custom field with no value for the previewed
   product, in grey, so the block can be found (BUILD_BRIEF_2026-10-09-B §6). Shoppers never get it. */
.product__metafield--empty {
  justify-content: flex-start;
  gap: 0.35rem;
  color: #8a8681;
  font-style: italic;
}

/* Reviews sit under the design's page (it does not draw them); they take its square, quiet
   controls so the page does not change language halfway down. */
.reviews-form__submit {
  min-height: 3rem;
  padding: 0 1.5rem;
  border: 1px solid #0f0c0b;
  border-radius: var(--button-radius, 0); /* 10-15-C §1: Button shape; square when unset */
  background: #0f0c0b;
  color: #fff;
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: 0.124rem;
  text-transform: var(--button-text-transform, uppercase); /* 10-15-C §3: Button text; capitals when unset */
}

.reviews-form__control {
  border-radius: 0;
  border-color: #dcdad8;
}

/* ===================================================================================== *
 * parity_snifl_product — product page look options, every one off by default. Each rule below is
 * scoped to a class or attribute that main_product.liquid / variant-picker.liquid print only when
 * the merchant picked the option, so a page without them is styled exactly as before.
 * ===================================================================================== */

/* Gallery "Image shape: Portrait 4:5". */
.product-media--tall .product-media__item img {
  aspect-ratio: 4 / 5;
}

/* Media width "Wide": half and half on tablets, 7:5 from 1440px. */
@media (min-width: 1440px) {
  .product-main--mw-wide .product-main__layout {
    grid-template-columns: 7fr 5fr;
  }
}

/* "Photos reach the edge of the screen": the two columns break out of the page margin. The photo
   side starts at the window edge; the details side keeps the page margin on tablets and the column
   gap (80px) from 1440px. 50% - 50vw is the distance from the content column to the window edge. */
@media (min-width: 750px) {
  .product-main--bleed .product-main__layout {
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    padding-right: calc(50vw - 50%);
    column-gap: 2rem;
  }

  .product-main--bleed.product-main--media-right .product-main__layout {
    padding-right: 0;
    padding-left: calc(50vw - 50%);
  }
}

@media (min-width: 1440px) {
  .product-main--bleed .product-main__layout {
    column-gap: 5rem;
    padding-right: 5rem;
  }

  .product-main--bleed.product-main--media-right .product-main__layout {
    padding-right: 0;
    padding-left: 5rem;
  }
}

/* "Details position: Middle of the screen" (computers): the column is a screen tall and its blocks
   sit in the middle of it, so they stay centred beside the photos while pinned. */
@media (min-width: 1440px) {
  .product-main--info-center .product-main__info {
    min-height: 100vh;
    align-content: center;
  }
}

/* "Swipe the photos sideways on phones" (stacked layout): one row the shopper swipes, each photo
   the screen width less 30px so the next one peeks in; the row reaches the right edge. */
@media (max-width: 749px) {
  .product-main--swipe .product-media--thumbs-stacked .product-media__stage {
    display: flex;
    gap: 0;
    margin-right: calc(50% - 50vw);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }

  .product-main--swipe .product-media--thumbs-stacked .product-media__stage::-webkit-scrollbar {
    display: none;
  }

  .product-main--swipe .product-media--thumbs-stacked .product-media__item {
    flex: 0 0 calc(100vw - 30px);
    scroll-snap-align: start;
  }

  .product-main--swipe .product-jump {
    display: none;
  }
}

/* Price "Show the discount badge" off. */
.product__price-block--no-badge .price__badge {
  display: none;
}

/* "Green dot before the availability message" (red when the choice cannot be bought). */
.product__availability--dot {
  display: flex;
  align-items: center;
  gap: 0.375rem;
}

.product__availability--dot::before {
  content: "";
  flex: none;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #5cb176;
  box-shadow: 0 0 0 1.3px rgba(92, 177, 118, 0.59);
}

.product__availability--dot.product__availability--out::before {
  background: #d1453b;
  box-shadow: 0 0 0 1.3px rgba(209, 69, 59, 0.5);
}

.product__price-block > .product__availability {
  margin-top: 1rem;
}

/* Quantity "Own row above the buy button". */
@media (min-width: 750px) {
  .product-main--qty-row .product-main__info > .product-qty + .product__submit {
    grid-column: 1 / -1;
  }
}

/* Variant picker "Variant photos": each value a 4:5 photo tile, the chosen one framed. */
.variant-picker--photos .variant-picker__values {
  gap: 0.5rem;
}

.variant-picker__chip.variant-picker__chip--photo {
  position: relative;
  width: var(--vp-photo-w, 80px);
  min-width: 0;
  height: calc(var(--vp-photo-w, 80px) * 1.25);
  padding: 0;
  border: 0;
  border-radius: 6px;
  overflow: hidden;
  background: #e7ece5;
}

@media (max-width: 1439px) {
  .variant-picker__chip.variant-picker__chip--photo {
    width: calc(var(--vp-photo-w, 80px) * 0.8);
    height: var(--vp-photo-w, 80px);
  }
}

.variant-picker__photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.variant-picker__chip--photo .variant-picker__text {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

.variant-picker__chip--photo::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 2px solid transparent;
  border-radius: inherit;
  pointer-events: none;
}

.variant-picker__value input:checked + .variant-picker__chip--photo {
  box-shadow: none;
}

.variant-picker__value input:checked + .variant-picker__chip--photo::after {
  border-color: var(--product-accent, var(--text, #0f0c0b));
}

.variant-picker__value:hover .variant-picker__chip--photo::after {
  border-color: rgba(0, 0, 0, 0.2);
}

.variant-picker__value:hover input:checked + .variant-picker__chip--photo::after {
  border-color: var(--product-accent, var(--text, #0f0c0b));
}

/* "Highlight colour". */
.product-main--accent .price s {
  color: var(--product-accent);
}

.product-main--accent .product-breadcrumbs [aria-current="page"] {
  color: var(--product-accent);
}

.product-main--accent .product__submit:not([disabled]):hover {
  border-color: var(--product-accent);
  background: var(--product-accent);
}

/* "Details look: Soft" — larger plain text in the colour scheme's colours (--text, and --text at
   80% for the secondary lines), labels as typed, no rules between rows. */
.product-main--soft {
  --pm-soft-muted: color-mix(in srgb, var(--text, #451504) 80%, transparent);
}

.product-main--soft .product-breadcrumbs {
  align-items: center;
  gap: 0.375rem;
  margin-bottom: 1.5rem;
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0;
  text-transform: none;
  color: var(--pm-soft-muted);
}

.product-main--soft .product-breadcrumbs a:hover {
  color: var(--text);
}

.product-main--soft .product-breadcrumbs__sep {
  width: 16px;
  height: 16px;
  overflow: hidden;
  font-size: 0;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='m6 3.5 4.5 4.5L6 12.5' fill='none' stroke='%23000' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='m6 3.5 4.5 4.5L6 12.5' fill='none' stroke='%23000' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
}

.product-main--soft .product__title {
  font-size: 1.75rem;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text);
}

.product-main--soft .price {
  align-items: center;
  gap: 0.75rem;
  font-size: 1.125rem;
  line-height: 1.4;
  letter-spacing: 0;
}

.product-main--soft .price__now {
  font-weight: 500;
}

.product-main--soft .price s {
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.4;
}

.product-main--soft:not(.product-main--accent) .price s {
  color: var(--pm-soft-muted);
}

.product-main--soft .product__availability {
  font-size: 0.875rem;
  line-height: normal;
  color: var(--text);
}

.product-main--soft .variant-picker__legend {
  justify-content: flex-start;
  align-items: baseline;
  gap: 0.25rem;
  margin-bottom: 0.5rem;
}

.product-main--soft .variant-picker__name {
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0;
  text-transform: none;
  color: var(--pm-soft-muted);
}

.product-main--soft .variant-picker__chosen {
  font-size: 1rem;
  font-weight: 500;
  line-height: 1.6;
  letter-spacing: -0.02em;
  color: var(--text);
}

.product-main--soft .product-qty__label {
  margin-bottom: 0.25rem;
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0;
  text-transform: none;
  color: var(--pm-soft-muted);
}

.product-main--soft .product-qty__control {
  height: 3rem;
  border: 1px solid color-mix(in srgb, var(--text, #451504) 7%, var(--bg, #fff));
  border-radius: 2rem;
  overflow: hidden;
}

.product-main--soft .product-qty__step,
.product-main--soft .product-qty__input {
  width: 3rem;
  height: 100%;
  background: #fff;
  color: #000;
}

.product-main--soft .product-qty__step {
  font-size: 1.125rem;
}

.product-main--soft .product-qty__step:hover {
  background: #f4f4f4;
}

.product-main--soft .product-qty__input {
  padding: 0;
  font-size: 0.875rem;
  font-weight: 500;
}

.product-main--soft .product__submit {
  gap: 0.625rem;
  min-height: 2.875rem;
  font-size: 1rem;
  font-weight: 500;
  line-height: 1.6;
  letter-spacing: -0.02em;
}

.product-main--soft .product__submit-icon {
  width: 1.5rem;
  height: 1.5rem;
}

.product-main--soft .product__submit:has(> .product__submit-price:not([hidden])) {
  column-gap: 0.25rem;
}

.product-main--soft .product__submit-price {
  gap: 0;
}

.product-main--soft .product__submit-sep {
  font-size: 0;
}

.product-main--soft .product__submit-sep::before {
  content: "\30FB";
  font-size: 1rem;
}

.product-main--soft .product__assurance {
  gap: 0.375rem;
  font-size: 1rem;
  line-height: 1.4;
  color: var(--pm-soft-muted);
}

.product-main--soft .product__assurance-icon {
  width: 1.5rem;
  height: 1.5rem;
  color: var(--text);
}

.product-main--soft .product-main__info > .product__assurance + .product__assurance {
  margin-top: 1rem;
}

.product-main--soft .product-main__info > .product__submit + .product__assurance {
  margin-top: 1rem;
}

.product-main--soft .product-main__info > :not(.product__assurance) + .product__assurance {
  padding-top: 0;
  border-top: 0;
}

/* Rows: inset 16px, no rules, a plus that turns into a cross; the first row 88px under what is
   above it (an 80px gap plus the rows' own 8px top padding). */
.product-main--soft .product__row,
.product-main--soft .product-main__info > :not(.product__row) + .product__row {
  margin-inline: 1rem;
  border: 0;
}

.product-main--soft .product-main__info > :not(.product__row) + .product__row {
  margin-top: 5.5rem;
}

.product-main--soft .product__row > summary {
  padding: 0.625rem 0 0.9375rem;
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text);
}

.product-main--soft .product__row > summary::after,
.product-main--soft .product__row[open] > summary::after {
  width: 1.25rem;
  height: 1.25rem;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M10 3v14M3 10h14' stroke='%23000' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M10 3v14M3 10h14' stroke='%23000' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
  color: #000;
}

.product-main--soft .product__row[open] > summary::after {
  transform: rotate(45deg);
}

.product-main--soft .product__row > .rte,
.product-main--soft .product__row > .body {
  padding: 0 0 0.9375rem;
  font-size: 0.875rem;
  line-height: 1.2;
  color: #605f5f;
}

@media (max-width: 749px) {
  .product-main--soft .product__title {
    font-size: 1.5rem;
  }
}
/* Buy button "Show a Buy it now button": an outlined pill under the buy button, the same height. */
.product__buy-now {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 3rem;
  padding: 0 1.5rem;
  border: 1px solid var(--color-button, #0f0c0b);
  border-radius: var(--button-radius, 0);
  text-transform: var(--button-text-transform, uppercase);
  background: transparent;
  color: var(--color-button, #0f0c0b);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  transition: color 0.2s ease;
}

.product__buy-now[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

.product-main--accent .product__buy-now:not([disabled]):hover {
  color: var(--product-accent);
}

@media (min-width: 750px) {
  .product-main__info > .product__buy-now {
    grid-column: 1 / -1;
  }
}

.product-main__info > .product__submit + .product__buy-now,
.product-main__info > .product__wish + .product__buy-now {
  margin-top: 1rem;
}

.product-main--soft .product__buy-now {
  min-height: 2.875rem;
  font-size: 1rem;
  line-height: 1.6;
  letter-spacing: -0.02em;
}

/* Soft: the buy button takes the colour scheme's button colours. */
.product-main--soft .product__submit {
  border-color: var(--color-button, #0f0c0b);
  background: var(--color-button, #0f0c0b);
  color: var(--color-button-text, #fff);
}

/* Soft: the quantity box's hairline is drawn over the white cells, inside its 48px. */
.product-main--soft .product-qty__control {
  border: 0;
  outline: 1px solid color-mix(in srgb, var(--text, #451504) 7%, var(--bg, #fff));
  outline-offset: -1px;
}

.product-main--soft .product-main__info > .product__assurance {
  margin-top: 1rem;
}
.product-main--soft .product-qty__step.is-at-min {
  color: rgba(0, 0, 0, 0.25);
}
.product-main--soft .product__row {
  border-bottom: 1px solid transparent;
}

.product-main--soft .product__row:not(:has(+ .product__row)) {
  margin-bottom: 0.5rem;
}
/* Soft below 1200px: 14px text, a 44px buy button with 13px words (14px on phones). */
@media (max-width: 1199px) {
  .product-main--soft .product-breadcrumbs,
  .product-main--soft .variant-picker__name,
  .product-main--soft .variant-picker__chosen,
  .product-main--soft .product-qty__label,
  .product-main--soft .product__assurance,
  .product-main--soft .product__row > summary {
    font-size: 0.875rem;
  }

  .product-main--soft .product__submit,
  .product-main--soft .product__buy-now {
    min-height: 2.75rem;
    font-size: 0.8125rem;
  }

  .product-main--soft .product__submit-sep::before {
    font-size: 0.8125rem;
  }
}

@media (max-width: 749px) {
  .product-main--soft .product__submit,
  .product-main--soft .product__buy-now,
  .product-main--soft .product__submit-sep::before {
    font-size: 0.875rem;
  }

  /* Swipe row: the one column must not grow to the row's full length. */
  .product-main--swipe .product-main__layout {
    grid-template-columns: minmax(0, 1fr);
  }
}
/* Swipe dots (product.js initSwipeDots): 6px dots 16px apart, centred over the foot of the photos,
   the shown photo's dot full strength. Phones only. */
.product-swipe-dots {
  display: none;
}

@media (max-width: 749px) {
  .product-main--swipe .product-main__media {
    position: relative;
  }

  .product-main--swipe .product-swipe-dots:not([hidden]) {
    position: absolute;
    left: 50%;
    bottom: 1.0625rem;
    z-index: 2;
    display: flex;
    transform: translateX(-50%);
  }

  .product-swipe-dots button {
    width: 16px;
    height: 26px;
    margin: -10px 0;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
  }

  .product-swipe-dots button::before {
    content: "";
    display: block;
    width: 6px;
    height: 6px;
    margin: 0 auto;
    border-radius: 50%;
    background: #000;
    opacity: 0.5;
  }

  .product-swipe-dots button.is-active::before {
    opacity: 1;
  }
}