/* GW PDP — sections/template--product.liquid
   Figma: page 30:10668 (desktop 1440 x 2223) / 30:10023 (mobile 393 x 2926.98),
   gallery 30:10669 / 30:10024, information column 30:10675 / 30:11004.

   Loaded AFTER template-product.min.css so equal-specificity overrides win.
   Covers three things: the page/column geometry, the gallery, and the
   information column — including the five gw_* blocks.

   WHAT IS *NOT* HERE, DELIBERATELY:
     - Per-block vertical rhythm. The theme already spaces every block with an
       inline --custom-margin-bottom written from each block's `margin_bottom`
       setting, and templates/product.json now carries the Figma intervals
       (24 inside the product card, 32 between root groups, 12 between
       accordion rows). Restating them here would fight the merchant's control.
     - The price block's markup, ids and class names. Bold Subscriptions reads
       .price__regular .price-item--regular, .price__sale .price-item--sale and
       id^="price-template--" to write live prices into the DOM; this file only
       ever changes how the price LOOKS.
     - The ATC button's class list, for the same reason — Bold's express
       add-ons widget is configured with
       button_class_names: "button button--full-width button--primary".

   LINE-HEIGHT. Figma's type tokens record lineHeight: 100 while every node
   emits leading-[normal]. 1.0 does not reconcile with the rendered boxes
   (48px title in a 63px node = 1.31; 18/23; 16/21; 14/18), and 1.31 is EB
   Garamond's own normal — so `normal` is used throughout and the node heights
   are what the style report asserts.

   THE 1px STROKE IS DRAWN INSIDE THE FRAME in Figma, while a CSS border ADDS
   to an auto height. Every bordered box below therefore carries padding minus
   one. Recorded three times now: gw-collection-grid's category pill,
   gw-collection-note's card, and here.

   1025px is the theme's desktop breakpoint (template-product.min.css and every
   other section-gw-*.min.css).

   Every colour carries the Figma literal as its var() fallback, so a blank
   colour setting keeps the design rather than voiding the property. */

[data-wetheme-section-type='template--product'] {
  /* Figma palette. None of these exist as theme globals — config/settings_data
     carries only type_base_font / type_header_font (both ebgaramond_n4, which
     is why no font work is needed) and a handful of scheme colours. Scoped to
     the section rather than :root so nothing leaks to other templates. */
  --gw-pdp-accent-50: #fdfaf4;
  --gw-pdp-accent-100: #f2ead8;
  --gw-pdp-accent-200: #e8dabd;
  /* Reviews / Accent-500 — the star fill. */
  --gw-pdp-accent-500: #c8a96a;
  --gw-pdp-accent-600: #a88e57;
  --gw-pdp-accent-700: #897244;
  --gw-pdp-accent-800: #6a5632;
  --gw-pdp-accent-900: #4a3b1f;
  --gw-pdp-neutral-100: #f1f3f5;
  --gw-pdp-neutral-600: #111111;
  --gw-pdp-neutral-700: #495057;
  --gw-pdp-neutral-800: #3c3c3c;
  --gw-pdp-neutral-900: #242424;
  --gw-pdp-secondary-500: #252626;
  --gw-pdp-secondary-600: #191a1a;

  /* Unbound in Figma — used in the frames but backed by no variable. Kept
     named rather than inlined so a later token pass has one place to look. */
  --gw-pdp-rating-ink: #343a40;
  --gw-pdp-bullet-ink: #3f3f3f;
  --gw-pdp-tarnish-ink: #555555;
  --gw-pdp-label-ink: #373c42;

  --gw-pdp-font: var(--header-font-stack, 'EB Garamond', serif);
}

/* ==========================================================================
   1 — PAGE AND COLUMNS
   Frame p-64 with a 32 gap and two flex-[1_0_0] columns → 1312 content,
   640 + 32 + 640. The theme ships 0 80px and a 20px gap.
   ========================================================================== */

@media (min-width: 1025px) {
  [data-wetheme-section-type='template--product'].wrapper-spacing--h {
    padding-inline: 64px;
  }

  /* Matched on the theme's own selector: template-product.min.css sets 20px on
     `.product-single-wrapper .product-single` at (0,3,0), which beat a bare
     `.product-single` here and left both columns 645.5 against the frame's
     640 — the gallery, and every thumb (105 against 104), with them. */
  [data-wetheme-section-type='template--product'] .product-single-wrapper .product-single {
    gap: 32px;
  }

  /* Both columns carry the theme's 50% and shrink to make room for the gap,
     but flex weighs that shrink by inner size, and the information column's
     31px padding + 1px border take 64 off its share: 639.2 / 640.8 against the
     frame's 640 / 640. The gallery column is held at its half less half the
     gap, and the information column shrinks into the rest. image_size is
     `medium` (six-twelfths) on every template that renders this section. */
  [data-wetheme-section-type='template--product'] [data-product-media-wrapper].large--six-twelfths {
    flex-shrink: 0;
    width: calc(50% - 16px);
  }
}

/* Mobile frame is 393 with px-16 → 361 content. The theme ships 24. */
@media (max-width: 1024px) {
  [data-wetheme-section-type='template--product'].wrapper-spacing--h {
    padding-inline: 16px;
  }
}

/* ==========================================================================
   2 — GALLERY  (Figma 30:10669 / 30:10024)
   The theme already renders main-on-top + thumbnails-below with a 16px gap
   (product.json carries thumbnail_position: "below"), so this is sizing and
   glyphs only — no reconfiguration and no markup change.
   ========================================================================== */

[data-wetheme-section-type='template--product'] product-media.product-media-slider-desktop {
  gap: 16px;
}

/* 640 x 624 = 1.0256. The theme's `image_shape: square` sizes the INNER <img>
   1:1 from the column width, so on a square source it came out 638x638 inside
   this 638x622 box and bled 16px into the gap, landing on the thumbnail strip.
   The box sets the frame's ratio; the image is then made to fill it exactly and
   the overflow is clipped, which is what `object-fit: cover` already expects. */
[data-wetheme-section-type='template--product']
  .product-media-slider-desktop
  .thumbnail-media--main-media {
  aspect-ratio: 640 / 624;
  overflow: hidden;
}

/* The real conflict is on the IMAGE, not the box: `image_shape: square` gives
   it `.media-ratio--square { aspect-ratio: 1/1 }`
   (component-product-media.min.css), so at 638 wide it renders 638 tall inside
   a 622 box. Setting `height: 100%` cannot fix it — the <a> wrapper between
   them is auto-height, so the percentage has nothing to resolve against. The
   image's own ratio is therefore matched to the frame. Thumbnails keep the
   theme's square ratio; this is scoped to the main media only.
   Specificity must clear the theme's (0,2,1). */
[data-wetheme-section-type='template--product']
  product-media.media-type-thumbnails
  .thumbnail-media--main-media
  .media-ratio--square {
  aspect-ratio: 640 / 624;
}

[data-wetheme-section-type='template--product']
  .thumbnail-media--main-media
  .swiper-slide > a {
  display: block;
  height: 100%;
}

/* Figma 30:10671 — the strip is inset by one arrow slot plus one gap at each
   end (12 + 16 desktop, 16 + 8 mobile), which is what leaves the five thumbs
   their 104. Swiper measures the element's own width, and the theme pins that
   width to 100%, so the inset is a width calc rather than a margin — a margin
   alone left the element at 638 and Swiper kept sizing slides from it. */
[data-wetheme-section-type='template--product']
  .product-media-slider-desktop
  .thumbnail-media--thumbnails {
  height: 105px;
  /* !important: the theme pins the swiper element to the full grid area and
     wins on its own. */
  width: calc(100% - 56px) !important;
  margin-inline: 28px;
}

[data-wetheme-section-type='template--product']
  product-media.media-type-thumbnails.thumbnails-below
  .thumbnail-media--thumbnails
  .swiper-wrapper
  .swiper-slide {
  /* Figma's strip is five 104 x 105 thumbs. The WIDTH is Swiper's — it writes
     an inline px width from slidesPerView, which the bundle derives from the
     section's image_size (small 5.5 / medium 6.5 / large 7.5,
     assets/component-product-media.js:18704-18710) and which no schema setting
     reaches without also resizing the media column. assets/gw-pdp-gallery.js
     sets it to the frame's 5 on the live instance instead, so Swiper's own
     transform maths stays consistent — a CSS width override would not.
     At the theme's 638 column: (638 - 56 - 4x16) / 5 = 103.6 against 104. */
  height: 105px;
  box-sizing: border-box;
  /* The theme pads each slide 1px vertically and clamps it with
     `min-width: 60px`; both are undone at its own specificity so the thumb
     fills the frame's 104 x 105 box exactly. */
  padding: 0;
  min-width: 0;
}

/* Figma anchors the strip at slot 1 (x 28 / 24) whatever the photo count; the
   theme centres a strip that fits (`.swiper-center-slides`, from
   centerSlidesIfNeeded in component-product-media.js). Unused slots stay
   blank — the frame's #CECECE boxes are placeholders, not content. */
[data-wetheme-section-type='template--product']
  product-media.media-type-thumbnails.thumbnails-below
  .thumbnail-media--thumbnails.swiper-center-slides
  .swiper-wrapper {
  left: 0;
  /* !important: the theme's centring transform carries it. */
  transform: none !important;
}

/* Every thumb at full strength, as the frame draws them. The theme dims each
   unselected thumb to 50% to mark the selected one; that cue is moved to a 1px
   inside stroke on the selected thumb instead — by instruction, as Figma draws
   no selected state — in the arrows' Neutral/900, so the thumb the arrows
   have stepped to reads at a glance. An overlay, so the 104 x 105 / 56.2 x 61
   box and the image in it do not move. */
[data-wetheme-section-type='template--product']
  product-media.media-type-thumbnails
  .thumbnail-media--thumbnails
  .swiper-wrapper
  .swiper-slide
  .responsive-image-wrapper {
  opacity: 1;
}

[data-wetheme-section-type='template--product']
  product-media.media-type-thumbnails
  .thumbnail-media--thumbnails
  .swiper-slide-thumb-active::after {
  content: '';
  position: absolute;
  inset: 0;
  border: 1px solid var(--gw-pdp-gallery-thumb-active, #1e1e1e);
  border-radius: var(--thumbnail-border-radius);
  pointer-events: none;
}

/* The theme's 32px edge fades — its scroll cue from before the strip had
   arrows — wash out the fifth thumb on any product with more than five
   photos. Figma draws none; the chevrons are the cue now. */
[data-wetheme-section-type='template--product']
  product-media.media-type-thumbnails.thumbnails-below
  .thumbnail-media--thumbnails::before,
[data-wetheme-section-type='template--product']
  product-media.media-type-thumbnails.thumbnails-below
  .thumbnail-media--thumbnails::after {
  display: none;
}

/* The thumb fills its box in the frame (object-cover, 104 x 105 = 0.99). The
   theme's square wrapper left 1.4px of the 105 row unpainted. */
[data-wetheme-section-type='template--product']
  .thumbnail-media--thumbnails
  .swiper-slide
  .responsive-image-wrapper,
[data-wetheme-section-type='template--product']
  .thumbnail-media--thumbnails
  .swiper-slide
  .theme-img {
  height: 100%;
  aspect-ratio: auto;
  object-fit: cover;
}

/* Arrows. The theme draws a long arrow (M21 12L3 12…) on a 44 x 44 #242424
   button absolutely positioned OVER the main image; Figma draws a bare 16 x 12
   chevron, rotated ±90°, as a flex sibling flanking the THUMBNAIL strip, with
   no button behind it at all. The SVG is masked out rather than removed so the
   hit area, the Swiper bindings and the focus ring all survive — but the
   button chrome goes, and the slot is moved down onto the thumbnail row.
   The 44px box is kept as the touch target (Figma's 12 x 16 is below the 24px
   minimum) and only the painted glyph is resized.

   The arrows have to stay INSIDE the main slider — component-product-media.js
   binds them as its navigation with this.mainMedia.querySelector, and they
   step the main image one photo at a time, the thumb strip following — but
   that slider is a .swiper, overflow: hidden, so once moved down onto the
   thumbnail row they were clipped and never painted. Taking position off the
   slider hands their containing block to product-media (relative, the whole
   640 x 745 frame), whose overflow does not clip them. Its only other
   positioned children are the badge (top 0 / left 0 — the same corner of both
   boxes) and Swiper's offscreen a11y live region.
   The slider's `.block-radius-clip` clip-path is swapped for a border-radius
   on the same token: a clip-path clips every descendant whatever its
   containing block, while overflow + radius still rounds the slides. */
[data-wetheme-section-type='template--product']
  product-media.media-type-thumbnails
  .thumbnail-media--main-media {
  position: static;
  clip-path: none;
  border-radius: var(--block-border-radius);
}

[data-wetheme-section-type='template--product'] product-media.media-type-thumbnails .thumb-prev,
[data-wetheme-section-type='template--product'] product-media.media-type-thumbnails .thumb-next {
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  background-color: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  filter: none;
  /* Placed from the bottom of the frame, so the 44px box centres on the
     thumbnail row:
       desktop  (105 - 44) / 2 = 30.5
       mobile   ( 61 - 44) / 2 =  8.5 */
  top: auto;
  bottom: 30.5px;
  transform: none;
  /* The theme hides both arrows above 1025 until the main image is hovered;
     Figma draws them at rest. */
  opacity: 1;
  /* The frame's slot is 12 wide (30:10669 x-extent 0-12), so the glyph centres
     on x 6 and the first thumb starts at 28. The theme's 44px button would
     centre it on 22. Height stays 44 as the touch target. */
  width: 12px;
  height: 44px;
  padding: 0;
}

[data-wetheme-section-type='template--product'] product-media.media-type-thumbnails .thumb-prev {
  left: 0;
  right: auto;
}

[data-wetheme-section-type='template--product'] product-media.media-type-thumbnails .thumb-next {
  right: 0;
  left: auto;
}

/* ...and on that hover slides them in by ±100% at (0,4,1), which would walk
   the chevrons 12px off their slots. */
[data-wetheme-section-type='template--product']
  product-media.media-type-thumbnails
  .thumbnail-media--main-media:hover
  .thumb-prev,
[data-wetheme-section-type='template--product']
  product-media.media-type-thumbnails
  .thumbnail-media--main-media:hover
  .thumb-next {
  transform: none;
}

[data-wetheme-section-type='template--product'] product-media.media-type-thumbnails .thumb-prev svg,
[data-wetheme-section-type='template--product'] product-media.media-type-thumbnails .thumb-next svg {
  display: none;
}

[data-wetheme-section-type='template--product'] product-media.media-type-thumbnails .thumb-prev::after,
[data-wetheme-section-type='template--product'] product-media.media-type-thumbnails .thumb-next::after {
  content: '';
  display: block;
  width: 16px;
  height: 12px;
  background-color: var(--gw-pdp-gallery-arrow, #1e1e1e);
  -webkit-mask-image: var(--gw-pdp-chevron-url);
  mask-image: var(--gw-pdp-chevron-url);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

[data-wetheme-section-type='template--product'] product-media.media-type-thumbnails .thumb-prev::after {
  transform: rotate(90deg);
}

[data-wetheme-section-type='template--product'] product-media.media-type-thumbnails .thumb-next::after {
  transform: rotate(-90deg);
}

/* Zoom / lightbox stays on, by instruction: the affordance is revealed on
   hover so a customer learns the image is zoomable, and is always present for
   keyboard users, who get no hover at all. */
[data-wetheme-section-type='template--product']
  .thumbnail-media--main-media
  [class*='zoom'] {
  opacity: 0;
  transition: opacity 0.2s ease;
}

[data-wetheme-section-type='template--product']
  .thumbnail-media--main-media:hover
  [class*='zoom'],
[data-wetheme-section-type='template--product']
  .thumbnail-media--main-media
  [class*='zoom']:focus-visible {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  [data-wetheme-section-type='template--product']
    .thumbnail-media--main-media
    [class*='zoom'] {
    transition: none;
  }
}

@media (max-width: 1024px) {
  /* Matched on the theme's own mobile class so this carries the same
     specificity as the desktop rule above it — a bare `product-media` selector
     loses to the theme's 16px. */
  [data-wetheme-section-type='template--product'] product-media.product-media-slider-mobile,
  [data-wetheme-section-type='template--product'] product-media.product-media-slider-desktop {
    gap: 8px;
  }

  [data-wetheme-section-type='template--product'] .thumbnail-media--main-media {
    aspect-ratio: 361 / 312;
  }

  /* The image follows the box here too. The 640 / 624 rule above is not
     media-scoped, so below 1025 it drew the image 361 x 352 inside this 312
     box and the photo sat 20px low against Figma's centred object-cover. */
  [data-wetheme-section-type='template--product']
    product-media.media-type-thumbnails
    .thumbnail-media--main-media
    .media-ratio--square {
    aspect-ratio: 361 / 312;
  }

  [data-wetheme-section-type='template--product'] .thumbnail-media--thumbnails {
    height: 61px;
    /* 16 arrow + 8 gap each end — Figma 30:10026. */
    width: calc(100% - 48px) !important;
    margin-inline: 24px;
  }

  /* Width comes from the same slidesPerView 5 the script sets — Swiper writes
     it inline — but the theme clamps every thumb with `min-width: 60px`
     (component-product-media.min.css), which is wider than the frame's 56.2
     and was overriding it. Matching that selector's specificity is enough; it
     carries no !important. */
  [data-wetheme-section-type='template--product']
    product-media.media-type-thumbnails.thumbnails-below
    .thumbnail-media--thumbnails
    .swiper-wrapper
    .swiper-slide {
    height: 61px;
    min-width: 0;
    padding: 0;
    box-sizing: border-box;
  }

  /* Mobile ships a different glyph, not a scaled one: a 9.33 x 4.67 chevron
     inset in a 16 box, against desktop's full-width 16 x 12. */
  [data-wetheme-section-type='template--product'] product-media.media-type-thumbnails .thumb-prev::after,
  [data-wetheme-section-type='template--product'] product-media.media-type-thumbnails .thumb-next::after {
    width: 16px;
    height: 16px;
    -webkit-mask-image: var(--gw-pdp-chevron-mobile-url);
    mask-image: var(--gw-pdp-chevron-mobile-url);
  }

  [data-wetheme-section-type='template--product'] product-media.media-type-thumbnails .thumb-prev,
  [data-wetheme-section-type='template--product'] product-media.media-type-thumbnails .thumb-next {
    bottom: 8.5px;
    /* Mobile's slot is square — Figma 112:210 / 112:212. */
    width: 16px;
  }
}

/* ==========================================================================
   3 — INFORMATION COLUMN SHELL  (Figma 30:10676 / 30:11005)
   One bordered card around the whole column: 1px #F1F3F5, radius 0,
   p-32 desktop / py-32 px-18 mobile.
   ========================================================================== */

[data-wetheme-section-type='template--product'] product-details.product-form-wrapper {
  border: 1px solid var(--gw-pdp-card-border, #f1f3f5);
  border-radius: 0;
  /* 31 / 17, not 32 / 18 — the stroke is inside the frame in Figma. */
  padding: 31px;
}

[data-wetheme-section-type='template--product'] .product-details--form-wrapper {
  --labels-font-size: 18px;
}

/* ---- vertical rhythm ---------------------------------------------------
   The block rhythm was being written into --custom-margin-bottom by the
   section and consumed by NOTHING. The theme's own rule is
   `.product-section .product-form-block{margin-bottom:var(--custom-margin-bottom)}`
   and this template renders no `.product-section` ancestor, so every block's
   margin computed to 0 and what actually spaced the column was
   assets/custom.css:

     product-details [data-updates-on-change].product-form-block { padding-bottom: 30px }
     .product--add-to-cart-form .product-block-text-field       { padding-bottom: 30px }

   — a flat 30 on every THEME block, and nothing at all on the gw_* blocks,
   which carry no data-updates-on-change. That is the whole spacing defect:
   accordion rows 30 apart against the frame's 12, and price -> review banner
   -> viewers at 0 against the frame's 24.

   The 30 is dropped inside this section only (custom.css keeps it everywhere
   else) and the interval is taken from each block's own margin_bottom, which
   is what templates/product.json has been carrying all along. */

[data-wetheme-section-type='template--product'] .product--add-to-cart-form > .product-form-block,
[data-wetheme-section-type='template--product'] .product--add-to-cart-form > .shopify-app-block {
  /* !important: custom.css is an element + attribute + class selector and is
     the thing being undone. */
  padding-bottom: 0 !important;
  /* !important on the margin too: the theme's form styles zero every
     .form-vertical child at a higher specificity than this file can reach
     without it. */
  margin-bottom: var(--custom-margin-bottom, 0px) !important;
}

/* App-block wrappers carry the section's 30px default, which no frame asks
   for. The Judge.me badge is the one app block the design draws — it takes the
   product card's 24 — and contributes nothing on a product with no reviews.
   Bold's slots are invisible until Bold hydrates them, so they take 0 and the
   widget's own markup spaces itself. */
[data-wetheme-section-type='template--product'] .product--add-to-cart-form > .product-form-block:has(.jdgm-preview-badge) {
  margin-bottom: 24px !important;
}

[data-wetheme-section-type='template--product'] .product--add-to-cart-form > .product-form-block:has(.jdgm-prev-badge[data-number-of-reviews='0']),
[data-wetheme-section-type='template--product'] .product--add-to-cart-form > .product-form-block:has(> [id*='bold_subscriptions']) {
  margin-bottom: 0 !important;
}

/* Figma wraps the accordions in a group with py-8 (30:10750) and the
   quantity + ATC block in another (30:10737). Neither wrapper exists here —
   the blocks are flat siblings — so the frame's drawn distance from the ATC
   rule to the first accordion (48 pb + 8 + 32 + 8 = 96) is carried by the
   reassurance block's 40 margin and this one. Adjacent siblings COLLAPSE, so
   the pair resolves to max(40, 48) = 48 — the value is stated whole rather
   than as the missing 8, which collapsing would have swallowed. The schema's
   margin_bottom range stops at 40, which is why the rest lives in CSS. */
[data-wetheme-section-type='template--product'] .product--add-to-cart-form > .product-form-block:not(.collapsible-tab-container) + .collapsible-tab-container {
  margin-top: 48px;
}

/* An empty block still draws its margin. The variant selector renders nothing
   on a single-variant product (the frames have no variant control at all) and
   was leaving a 30px hole between the box card and the recipient field. */
[data-wetheme-section-type='template--product'] .product--add-to-cart-form > .product-form-block:empty,
[data-wetheme-section-type='template--product'] .product--add-to-cart-form > .product-form-block[data-product-options]:not(:has(.swatch, select, input, .option-label-wrapper)) {
  margin-bottom: 0;
}

@media (max-width: 1024px) {
  [data-wetheme-section-type='template--product'] product-details.product-form-wrapper {
    padding: 31px 17px;
  }
}

/* ---- rating row (Judge.me preview badge) — Figma 30:10678 --------------- */

/* Judge.me owns this row, and two things in it are the app's rather than the
   design's: the glyph font it draws stars with, and the sentence it composes
   beside them ("5.0* from 2+ reviews", built from app settings the theme
   cannot reach). Both are replaced without touching a byte of app code —
   the stars by masking the wrapper with the frame's own star artwork, the
   copy by assets/gw-pdp-rating.js, which rewrites it from the badge's own
   data-average-rating / data-number-of-reviews attributes. */

[data-wetheme-section-type='template--product'] .jdgm-prev-badge {
  /* Judge.me re-shows the badge from its own sheet and hides it with an inline
     `display:none` when the product has no reviews. !important is what reaches
     past the sheet; the zero-review rule at the end of this block is also
     !important and more specific, so an unreviewed product still draws
     nothing. */
  display: flex !important;
  align-items: center;
  /* Figma 30:10679 — gap 8 between the star wrapper and the rating text. */
  gap: 8px;
}

/* The star row is the frame's artwork, not the app's font: JudgemeStar inks a
   rounder, wider star than Figma's, and no font-size and tracking pair lands
   both the 17.037 star and the 18.7407 pitch. gw-footer-stars.svg carries that
   exact geometry, so the wrapper becomes a 92 x 17.037 box masked with it and
   painted by a gradient — which is also what draws a partial rating, the hard
   edge sitting at --gw-pdp-stars-fill (written by the script from the score,
   defaulting to a full row). */
[data-wetheme-section-type='template--product'] .jdgm-prev-badge__stars {
  display: block;
  flex: 0 0 auto;
  width: 92px;
  height: 17.037px;
  /* Collapses the glyphs the mask is replacing; they still carry Judge.me's
     click target and aria-label. */
  font-size: 0 !important;
  letter-spacing: 0 !important;
  line-height: 0 !important;
  background-image: linear-gradient(
    90deg,
    var(--gw-pdp-accent-500, #c8a96a) 0 var(--gw-pdp-stars-fill, 100%),
    var(--gw-pdp-accent-100, #f2ead8) var(--gw-pdp-stars-fill, 100%) 100%
  );
  -webkit-mask-image: var(--gw-pdp-stars-url);
  mask-image: var(--gw-pdp-stars-url);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: left center;
  mask-position: left center;
  /* 100% 100%, not contain: the artwork is 108 x 20 and the box is the frame's
     92 x 17.037 — the same ratio, so nothing distorts, and contain would leave
     sub-pixel slack on one axis. */
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
}

/* Judge.me's own composed string, hidden rather than removed so their click
   target and aria-label survive. */
[data-wetheme-section-type='template--product'] .jdgm-prev-badge__text {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Figma 30:10691 — one line, two type sizes, baseline-aligned: "5.0" in Inter
   Medium 20 and "(2)" in Inter Regular 16, both #343A40. The 14px space span
   between them in the frame measures ~4. */
[data-wetheme-section-type='template--product'] .gw-pdp-rating__text {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  color: var(--gw-pdp-rating-ink);
}

[data-wetheme-section-type='template--product'] .gw-pdp-rating__score {
  font-family: 'Inter', var(--body-font-stack, sans-serif);
  font-size: 20px;
  font-weight: 500;
  line-height: 1.4;
}

[data-wetheme-section-type='template--product'] .gw-pdp-rating__count {
  font-family: 'Inter', var(--body-font-stack, sans-serif);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.4;
}

/* Zero reviews: Judge.me hides the badge inline, and this guards the case
   where it does not — the script writes no text on that branch either. */
[data-wetheme-section-type='template--product'] .jdgm-prev-badge[data-number-of-reviews='0'] {
  display: none !important;
}

/* ---- title — Figma 30:10783 / 30:11018 --------------------------------- */

[data-wetheme-section-type='template--product'] h1.product-details-product-title {
  margin: 0;
  font-family: var(--gw-pdp-font);
  font-size: 48px;
  font-weight: 400;
  line-height: normal;
  letter-spacing: 0;
  text-transform: none;
  color: var(--gw-pdp-neutral-600);
}

/* ---- price — Figma 30:10785 (LOOK ONLY; Bold reads this DOM) ----------- */

/* The group was already set to 24 and the amount still drew at 18: the theme
   sizes the inner [data-product-price] span from a stylesheet this file cannot
   out-specify, and font-size does not inherit past a rule that sets it. The
   amount spans are named explicitly and forced. */
[data-wetheme-section-type='template--product'] .product-price-group,
[data-wetheme-section-type='template--product'] .product-price-group [data-product-price],
[data-wetheme-section-type='template--product'] .product-price-group .money {
  font-family: var(--gw-pdp-font);
  font-size: 24px !important;
  font-weight: 400;
  line-height: normal;
  letter-spacing: 0;
  color: var(--gw-pdp-neutral-600);
}

/* .scaled-text applies a transform-based scale the design does not want. */
[data-wetheme-section-type='template--product'] .product-price-group.scaled-text {
  transform: none;
  zoom: normal;
}

/* ---- description — Figma 30:10787 -------------------------------------- */

[data-wetheme-section-type='template--product'] .product-description .text-link-animated,
[data-wetheme-section-type='template--product'] .product-description .text-link-animated p,
[data-wetheme-section-type='template--product'] .product-description .text-link-animated li {
  font-family: var(--gw-pdp-font);
  font-size: 18px;
  font-weight: 400;
  line-height: normal;
  letter-spacing: 0;
  color: var(--gw-pdp-neutral-600);
}

/* The gw_description block — the same type, on markup the merchant writes in
   a rich-text setting rather than on the product's description metafield.
   The theme's own .product-description block is disabled in
   templates/product.json; its rules above stay, so re-enabling it still
   renders to the frame. */

[data-wetheme-section-type='template--product'] .gw-pdp-description,
[data-wetheme-section-type='template--product'] .gw-pdp-description p,
[data-wetheme-section-type='template--product'] .gw-pdp-description li {
  font-family: var(--gw-pdp-font);
  font-size: 18px;
  font-weight: 400;
  line-height: normal;
  letter-spacing: 0;
  color: var(--gw-desc-text-color, var(--gw-pdp-neutral-600));
}

/* Figma separates the three paragraphs with a blank line: the desktop node is
   184 over six 23.57px lines, which leaves 42.6 across two gaps = 21.3. The
   rich-text setting emits <p>, so the blank line is a margin — and the last
   one carries none, or the block's own margin_bottom would be doubled. */
[data-wetheme-section-type='template--product'] .gw-pdp-description > p {
  margin: 0 0 var(--gw-desc-paragraph-gap, 21px);
}

[data-wetheme-section-type='template--product'] .gw-pdp-description > p:last-child {
  margin-bottom: 0;
}

/* Rich text can carry a link; the frame draws none, so it inherits the copy's
   colour and keeps only the underline. */
[data-wetheme-section-type='template--product'] .gw-pdp-description a {
  color: inherit;
  text-decoration: underline;
}

/* ---- trust bullets — Figma 30:10876 ------------------------------------ */

[data-wetheme-section-type='template--product'] .product-block-text-with-icon-group {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

[data-wetheme-section-type='template--product'] .product-block-text-with-icon-group .text-with-icon--content {
  display: flex;
  align-items: flex-start;
  /* Left-aligned. Figma puts justify-center on row 1 only, which is a no-op
     against w-full children — centring both rows is not what the frame does. */
  justify-content: flex-start;
  gap: 10px;
}

[data-wetheme-section-type='template--product'] .product-block-text-with-icon-group .text-with-icon--text {
  font-family: var(--gw-pdp-font);
  font-size: 18px;
  font-weight: 400;
  line-height: normal;
  /* The theme's .label-font uppercases these; the frame is sentence case. */
  text-transform: none;
  letter-spacing: 0;
  color: var(--gw-pdp-bullet-ink);
}

/* The theme's ICONSET has no mingcute check-fill, so the rendered outline
   check-circle is masked over with the exported glyph rather than forking the
   vendor block. 24 x 24 box per the frame. */
[data-wetheme-section-type='template--product'] .product-block-text-with-icon-group .text-with-icon--icon svg {
  display: none;
}

[data-wetheme-section-type='template--product'] .product-block-text-with-icon-group .text-with-icon--icon {
  position: relative;
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
}

/* The glyph does NOT fill its box. Figma insets the artwork inside the 24x24
   icon frame at 19.46% / 8.4% / 0.78% / 8.32% (top/right/bottom/left), which is
   exactly the exported SVG's own 19.9891 x 19.1427 at that offset. Sizing the
   pseudo-element to the box and letting `contain` scale it made the check
   noticeably larger and higher than the frame's. */
[data-wetheme-section-type='template--product'] .product-block-text-with-icon-group .text-with-icon--icon::after {
  content: '';
  position: absolute;
  top: 19.46%;
  left: 8.32%;
  display: block;
  width: 19.9891px;
  height: 19.1427px;
  background-color: var(--gw-pdp-check-color, #c8a96a);
  -webkit-mask-image: var(--gw-pdp-check-url);
  mask-image: var(--gw-pdp-check-url);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

/* ==========================================================================
   4 — GW BOX CARD  (Figma 30:10789 / 30:11038)
   ========================================================================== */

.gw-pdp-box-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 24px;
  /* 15, not 16 — stroke inside the frame. */
  padding: 15px;
  background: var(--gw-bc-bg, #fdfaf4);
  border: 1px solid var(--gw-bc-border, #f2ead8);
  border-radius: 0;
  /* Query container for the tarnish strip's fluid size below 1024 — 100cqi is
     the card's content box. */
  container-type: inline-size;
}

.gw-pdp-box-card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
  min-height: 40px;
}

.gw-pdp-box-card__heading {
  margin: 0;
  font-family: var(--gw-pdp-font);
  font-size: 18px;
  font-weight: 400;
  /* Figma's line box (384 x 23 / 293 x 46). `normal` is 23.5 for EB Garamond
     18 and pushed the mobile card 1px taller per heading line. */
  line-height: 23px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--gw-pdp-secondary-500);
}

.gw-pdp-box-card__badge {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 140px;
  height: 40px;
  padding-inline: 9px;
  background: var(--gw-bc-badge-bg, #a88e57);
  border-radius: 0;
  font-family: var(--gw-pdp-font);
  font-size: 14px;
  font-weight: 400;
  line-height: normal;
  color: var(--gw-bc-badge-text-color, #ffffff);
  white-space: nowrap;
}

/* A WRAPPING FLEX ROW, not CSS grid — Figma 30:10791 is
   flex flex-wrap gap-[23px] with w-[260px] shrink-0 items, and 544 fits
   260 + 23 + 260 = 543 exactly, so it wraps 2 x 2. */
.gw-pdp-box-card__grid {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: flex-start;
  gap: 23px;
  width: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}

.gw-pdp-box-card__item {
  display: flex;
  align-items: center;
  gap: 8px;
  /* Figma writes w-[260px] shrink-0 against a 544 container: 260 + 23 + 260 =
     543, two columns exactly. A fixed basis only holds at that one width —
     below it the row wrapped to ONE column with a dead gutter beside it, which
     is every desktop under ~1300 here. A half-of-the-row basis measures the
     same 260 at the frame's width and stays two columns at every other.
     Set --gw-bc-item-width to restore a fixed basis. */
  flex: 1 1 var(--gw-bc-item-width, calc(50% - 11.5px));
  min-width: 0;
  /* The theme puts margin-bottom on every li, which was adding 4.5px to each
     flex line and pushing the grid from 105 to 114. */
  margin: 0;
}

.gw-pdp-box-card__chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  background: var(--gw-bc-chip-bg, #897244);
  border-radius: 0;
  font-family: 'Poppins', var(--body-font-stack, sans-serif);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.4;
  color: #ffffff;
}

.gw-pdp-box-card__label {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--gw-pdp-font);
  font-size: 16px;
  font-weight: 400;
  line-height: normal;
  color: var(--gw-pdp-secondary-500);
}

/* Figma 31:60 is a ZERO-height box with the stroke drawn at inset -1px 0 0 0 —
   the rule overlaps the 24px gap above it and contributes nothing to the
   card's height. A plain border-top would occupy 1px and put the card at 271
   against the frame's 270, so the negative top margin cancels the border box
   and the stroke lands exactly where Figma paints it. The stroke is Accent/300
   #DDC9A1 (Line 1's SVG), not the card's Accent/100 border colour. */
.gw-pdp-box-card__rule {
  width: 100%;
  height: 0;
  margin: -1px 0 0;
  border: 0;
  border-top: 1px solid var(--gw-bc-rule, #ddc9a1);
}

.gw-pdp-box-card__tarnish {
  width: 100%;
  margin: 0;
  font-family: var(--gw-pdp-font);
  font-size: 16px;
  font-weight: 500;
  line-height: normal;
  text-align: center;
  text-transform: uppercase;
  color: var(--gw-pdp-tarnish-ink);
  /* The authored string carries doubled spaces around the first separator and
     is reproduced literally, so the whitespace has to survive. */
  white-space: pre-wrap;
}

@media (max-width: 1024px) {
  /* Figma drops the justify-between wrapper on mobile: heading and badge become
     separate stacked children of the card, badge left-aligned. One DOM, two
     layouts — the wrapper is unwrapped rather than duplicated. */
  .gw-pdp-box-card__header {
    display: contents;
  }

  /* Figma keeps the 260 item inside the 293 column, so labels 03 and 04 wrap
     to two lines (grid 233, card 483). One item per row as a COLUMN: in a
     wrapping row a 260 max-width packs three per row on tablets, because flex
     lines are built from the clamped size. Shrinks below 260 on narrow phones.
     Set --gw-bc-item-width-mobile: 100% for full-width items. */
  .gw-pdp-box-card__grid {
    flex-direction: column;
  }

  .gw-pdp-box-card__item {
    flex: none;
    width: 100%;
    max-width: var(--gw-bc-item-width-mobile, 260px);
  }

  /* Figma's 14px sets line 1 ("Tarnish-resistant · hypoallergenic ·", 291.7px)
     in the 293 column with 1.3px to spare, so every card narrower than the 393
     frame broke it onto three lines. Scaled to the card's content box instead:
     14px from a 293 column up, the same two-line break below it (20.84 = line 1
     width per px of font size). The 10px floor keeps that break on every screen
     from 310px up; a higher floor sends the second "·" to the start of line 2
     just below the floor's width. */
  .gw-pdp-box-card__tarnish {
    font-size: clamp(10px, (100cqi - 1px) / 20.84, 14px);
  }
}

/* ==========================================================================
   5 — GW REVIEW BANNER  (Figma 30:10959 / 30:11094)
   ========================================================================== */

.gw-pdp-review-banner {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 24px 16px;
  background: var(--gw-rb-bg, #e8dabd);
  border-radius: 0;
}

.gw-pdp-review-banner__item {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
}

.gw-pdp-review-banner__item[hidden] {
  display: none;
}

.gw-pdp-review-banner__text {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1 1 auto;
  min-width: 0;
}

.gw-pdp-review-banner__name-row {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  /* Hugs name + 8 + stars, as the frame does. A fixed 210 overflowed once the
     name rendered at 111.9 and centring pushed it 1px past the left inset. */
  width: auto;
  max-width: 100%;
  flex-wrap: nowrap;
}

.gw-pdp-review-banner__name {
  font-family: var(--gw-pdp-font);
  font-size: 14px;
  font-weight: 600;
  line-height: normal;
  letter-spacing: 2.52px;
  text-transform: uppercase;
  color: var(--gw-rb-text-color, #242424);
  /* Figma's node is 110 x 18 — one line. "BETHANY M." at 14px with 2.52px
     tracking measures 110 exactly, so it wrapped to two lines and took the
     row to 36. */
  white-space: nowrap;
}

/* Static 5-star row: gw-footer-stars.svg is the PDP star wrapper exactly —
   92/108 = 17.037/20 = 0.85185 — so the viewBox does all the scaling. */
.gw-pdp-review-banner__stars {
  display: block;
  flex: 0 0 auto;
  width: 92px;
  height: 17.037px;
  /* Accent/900 — the frame's star fill. */
  color: var(--gw-rb-star-color, #4a3b1f);
}

.gw-pdp-review-banner__stars svg {
  display: block;
  width: 92px;
  height: 17.037px;
}

/* The theme styles bare blockquotes with margin 0 0 32px and padding 16px 32px
   — 80px of chrome that put the banner at 189 against the frame's 96. Scoped
   through the section hook so it outranks that rule. */
[data-wetheme-section-type='template--product'] .gw-pdp-review-banner__quote,
.gw-pdp-review-banner__quote {
  margin: 0;
  padding: 0;
  border: 0;
  font-family: var(--gw-pdp-font);
  font-size: 14px;
  /* The theme italicises blockquotes; the frame's Body S is upright. */
  font-style: normal;
  font-weight: 400;
  line-height: normal;
  letter-spacing: 0;
  color: var(--gw-rb-text-color, #242424);
}

.gw-pdp-review-banner__next {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 0;
  border-radius: 100px;
  background: var(--gw-rb-arrow-bg, #4a3b1f);
  color: #ffffff;
  cursor: pointer;
}

.gw-pdp-review-banner__next-icon {
  display: block;
  width: 14px;
  height: 14px;
}

.gw-pdp-review-banner__next-icon svg {
  display: block;
  width: 14px;
  height: 14px;
}

/* ==========================================================================
   6 — GW VIEW COUNTER  (Figma 30:10698 / 30:11020)
   ========================================================================== */

.gw-pdp-view-counter {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding-block: 8px;
  font-family: var(--gw-pdp-font);
  font-size: 16px;
  font-weight: 400;
  line-height: normal;
  color: var(--gw-vc-text-color, #495057);
}

.gw-pdp-view-counter__dot {
  position: relative;
  flex-shrink: 0;
  width: var(--gw-vc-dot-size, 12px);
  height: var(--gw-vc-dot-size, 12px);
  border-radius: 50%;
  background-color: var(--gw-vc-dot-color, #c8a96a);
}

.gw-pdp-view-counter__dot--pulse::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background-color: inherit;
  opacity: 0.6;
  animation: gw-pdp-view-counter-pulse var(--gw-vc-pulse-speed, 2s) infinite;
}

@keyframes gw-pdp-view-counter-pulse {
  0% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.5);
    opacity: 0.7;
  }
  100% {
    transform: scale(2);
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .gw-pdp-view-counter__dot--pulse::before {
    animation: none;
  }
}

/* ==========================================================================
   7 — RECIPIENT NAME + QUANTITY + ADD TO CART
   Figma 30:10921 / 30:10737 / 30:10746
   ========================================================================== */

[data-wetheme-section-type='template--product'] .product--add-to-cart-form > .product-block-text-field {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  /* !important on the bottom half only: the rhythm rule above zeroes every
     block's padding-bottom to undo custom.css, and this group's py-8 is the
     frame's own (30:10921), not custom.css's 30. */
  padding-top: 8px;
  padding-bottom: 8px !important;
}

/* Figma 30:10737 — the quantity group is the same shape as the recipient
   group: py-8, label then controls 16 apart. The theme ships a 4px label
   margin instead. */
[data-wetheme-section-type='template--product'] quantity-input {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  padding-block: 8px;
}

[data-wetheme-section-type='template--product'] quantity-input label.quantity-selector {
  margin-bottom: 0;
}

/* The frame stacks label → helper → field (30:10922 / 30:10939 / 30:10924).
   The DOM is already in that order, but the theme gives .form-input-hint
   `order: 3`, which threw the helper below the input. Ordering all three
   explicitly rather than just resetting the hint, so the stack cannot be
   reshuffled by a rule further up. */
[data-wetheme-section-type='template--product'] .product-block-text-field > label {
  order: 1;
}

[data-wetheme-section-type='template--product'] .product-block-text-field > .form-input-hint {
  order: 2;
  margin: 0;
}

[data-wetheme-section-type='template--product'] .product-block-text-field > input {
  order: 3;
}

[data-wetheme-section-type='template--product'] .product-block-text-field label.label-font {
  margin: 0;
  font-family: var(--gw-pdp-font);
  font-size: 18px;
  font-weight: 400;
  line-height: normal;
  color: var(--gw-pdp-label-ink);
}

[data-wetheme-section-type='template--product'] .product-block-text-field .form-input-hint {
  margin: 0;
  font-family: var(--gw-pdp-font);
  font-size: 14px;
  font-weight: 400;
  line-height: normal;
  color: var(--gw-pdp-neutral-600);
}

[data-wetheme-section-type='template--product'] .product-block-text-field input.width-full,
[data-wetheme-section-type='template--product'] quantity-input .js-qty {
  box-sizing: border-box;
  height: 56px;
  background: var(--gw-pdp-accent-50);
  border: 1px solid var(--gw-pdp-accent-100);
  border-radius: 0;
}

/* !important is needed here and ONLY here. assets/custom.css carries
     product-details .product-form-block.product-block-text-field input
       { padding: 5px 12px !important; width: max-content !important }
   from earlier work, which pins the field to its content width — the opposite
   of the full-width field this design draws. The rule predates this build and
   also reaches product.hi-default-pdp.json, so it is overridden here rather
   than deleted; flagged at handover as stale for whichever template adopts
   this design next. */
[data-wetheme-section-type='template--product'] .product-block-text-field input.width-full {
  width: 100% !important;
  /* 15 / 9 — stroke inside the frame. */
  padding: 9px 15px !important;
  /* The border needs !important, and the reason is worth writing down: the
     theme's base input rule is
       input:not(.alt-input):not([type="checkbox"]):not([type="radio"])
            :not([type="file"]):not([type="submit"]):not([type="hidden"])
            :not(.btn)
     and EVERY :not() contributes its argument's specificity, so that chain
     scores (0,7,1) — it beats any reasonable selector here. It sets
     `border: 1px solid var(--border-color)`, which painted the field
     rgba(36,36,36,0.25) instead of the frame's #F2EAD8. `background` is not in
     that rule, so it wins normally and is left un-flagged. */
  background: var(--gw-pdp-accent-50);
  border: 1px solid var(--gw-pdp-accent-100) !important;
  border-radius: 0 !important;
  font-family: var(--gw-pdp-font);
  font-size: 16px;
  font-weight: 400;
  color: var(--gw-pdp-neutral-600);
}

[data-wetheme-section-type='template--product'] .product-block-text-field input.width-full::placeholder {
  color: var(--gw-pdp-neutral-700);
  opacity: 1;
}

[data-wetheme-section-type='template--product'] quantity-input label.quantity-selector {
  font-family: var(--gw-pdp-font);
  font-size: 18px;
  font-weight: 400;
  line-height: normal;
  color: var(--gw-pdp-label-ink);
}

/* The frame writes both form labels with a trailing colon — "Recipient Name *:"
   (30:10922) and "Quantity:" (30:10738). Neither is reachable from a setting:
   the theme appends its own " *" AFTER the text_field title, and the quantity
   label comes from a locale string. Generated content is the only place left
   that does not mean editing all 31 locales/*.schema.json. */
[data-wetheme-section-type='template--product'] .product-block-text-field > label::after,
[data-wetheme-section-type='template--product'] quantity-input label.quantity-selector::after {
  content: ':';
}

[data-wetheme-section-type='template--product'] quantity-input .js-qty {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 9px 39px;
}

[data-wetheme-section-type='template--product'] quantity-input .js-qty__adjust {
  width: 20px;
  height: 20px;
  padding: 0;
  background: none;
  border: 0;
  color: var(--gw-pdp-neutral-700);
}

[data-wetheme-section-type='template--product'] quantity-input .js-qty__num {
  width: auto;
  min-width: 0;
  padding: 0;
  background: none;
  border: 0;
  text-align: center;
  font-family: 'Inter', var(--body-font-stack, sans-serif);
  font-size: 16px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--gw-pdp-neutral-700);
}

/* ATC — look only. The class list is Bold's contract and is untouched. */
[data-wetheme-section-type='template--product'] .product--add-to-cart-button {
  width: 100%;
  height: 56px;
  padding-block: 8px;
  background: var(--gw-pdp-accent-800);
  border: 0;
  border-radius: 0;
  font-family: var(--gw-pdp-font);
  font-size: 18px;
  font-weight: 700;
  line-height: normal;
  letter-spacing: 0;
  text-transform: uppercase;
  color: #ffffff;
}

/* The button wrapper is a 12px-gap flex row and the theme leaves an EMPTY
   dynamic-checkout slot in it (show_smart_checkout is off), so the gap was
   counted anyway and the block measured 68 against the frame's 56. */
[data-wetheme-section-type='template--product'] .paymentButtonsWrapper > *:empty {
  display: none;
}

/* The reassurance line and the 48/12 bottom padding are one group with the
   button in Figma (30:10746), closed by a #F1F3F5 bottom border. */
[data-wetheme-section-type='template--product'] .product-form-block:not(.product-block-text-with-icon-group) > .text-with-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding-bottom: 48px;
  border-bottom: 1px solid var(--gw-pdp-neutral-100);
}

[data-wetheme-section-type='template--product'] .product-form-block:not(.product-block-text-with-icon-group) > .text-with-icon .text-with-icon--text {
  font-family: var(--gw-pdp-font);
  font-size: 16px;
  font-weight: 500;
  line-height: normal;
  text-transform: uppercase;
  color: var(--gw-pdp-neutral-800);
}

[data-wetheme-section-type='template--product'] .product-form-block:not(.product-block-text-with-icon-group) > .text-with-icon .text-with-icon--icon svg {
  display: none;
}

[data-wetheme-section-type='template--product'] .product-form-block:not(.product-block-text-with-icon-group) > .text-with-icon .text-with-icon--icon {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
}

[data-wetheme-section-type='template--product'] .product-form-block:not(.product-block-text-with-icon-group) > .text-with-icon .text-with-icon--icon::after {
  content: '';
  display: block;
  width: 100%;
  height: 100%;
  background-color: var(--gw-pdp-neutral-800);
  -webkit-mask-image: var(--gw-pdp-prayer-url);
  mask-image: var(--gw-pdp-prayer-url);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

@media (max-width: 1024px) {
  [data-wetheme-section-type='template--product'] .product-form-block:not(.product-block-text-with-icon-group) > .text-with-icon {
    padding-bottom: 12px;
  }
}

/* ==========================================================================
   8 — ACCORDIONS  (Figma 30:10750)
   The theme's plus_minus glyph is already a 20 x 20 stroke plus, so only the
   box, the type and the rhythm change.
   ========================================================================== */

/* The theme puts a 1px rgba(36,36,36,0.25) rule on the TOP AND BOTTOM of every
   collapsible-tab-container. The frame draws no rule between accordion rows at
   all — they are three separate cards with a 12px gap — and those rules were
   also what put a stray line above "AS SEEN IN". */
[data-wetheme-section-type='template--product'] .collapsible-tab-container {
  border-top: 0;
  border-bottom: 0;
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .collapsible-tab {
  background: var(--gw-pdp-accent-50);
  border: 1px solid var(--gw-pdp-accent-100);
  border-radius: 0;
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* 24 / 23 — stroke inside the frame; 24 + 23.5 + 24 + 2 = 73.5 row height. */
  padding: 24px 23px;
  min-height: 71px;
}

/* The theme gives .text-with-icon a 16px block margin, which was adding 32 to
   every row and putting it at 103.5 against the frame's 73. */
[data-wetheme-section-type='template--product'] .collapsible-tab-container .summary .text-with-icon {
  margin: 0;
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .summary .text-with-icon--text {
  font-family: var(--gw-pdp-font);
  font-size: 18px;
  font-weight: 400;
  line-height: normal;
  /* The theme's .label-font uppercases the summary; the frame is title case
     ("Product Details", not "PRODUCT DETAILS"). */
  text-transform: none;
  letter-spacing: 0;
  color: var(--gw-pdp-neutral-800);
  white-space: nowrap;
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .summary .icon--right svg {
  width: 20px;
  height: 20px;
}

/* Open panel (Figma 30:10949, "Shipping & Returns"): the heading keeps its
   24 / 23 inset, the body sits 10 below it at the same inset, and the frame
   closes 24 under the copy (25 / 24 in Figma includes the 1px stroke). The
   frame's glyph is a filled 1.75px-bar plus, not the theme's 1px stroke, so
   the Figma asset replaces it; the minus is the same bar without the stem. */
[data-wetheme-section-type='template--product'] .collapsible-tab-container .summary {
  transition: padding-bottom .35s cubic-bezier(.25,.46,.45,.94);
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .collapsible-tab.open .summary {
  padding-bottom: 0;
  min-height: 0;
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .summary .icon--right {
  display: block;
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  background: url('gw-icon-plus.svg') center / 20px 20px no-repeat;
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .collapsible-tab.open .summary .icon--right {
  background-image: url('gw-icon-minus.svg');
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .summary .icon--right svg {
  display: none !important;
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .collapsible-content .content {
  margin: 0;
  /* 9 + the 15 component-collapsible-button.js adds to the open height = 24. */
  padding: 10px 23px 9px;
}

/* Rich text body (Figma 30:10940) — one format for every accordion, whether
   the copy comes from the block's rich text or a rich_text metafield. Blocks
   stack flush; spacing comes from empty paragraphs, as in the frame. */
[data-wetheme-section-type='template--product'] .collapsible-tab-container .collapsible-content .richtext-block,
[data-wetheme-section-type='template--product'] .collapsible-tab-container .collapsible-content .richtext-block :is(p, h1, h2, h3, h4, h5, h6, ul, ol, li) {
  margin: 0;
  font-family: var(--gw-pdp-font);
  font-size: 18px;
  font-weight: 400;
  line-height: normal;
  letter-spacing: 0;
  color: var(--gw-pdp-neutral-800);
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .collapsible-content .richtext-block :is(ul, ol) {
  /* 27 = 1.5 x 18, the frame's marker indent. One blank line above and
     below the list, as in the frame — rich_text metafields cannot hold the
     empty paragraphs the frame uses for that gap. */
  margin: 1lh 0;
  padding: 0 0 0 27px;
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .collapsible-content .richtext-block ul {
  list-style: disc;
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .collapsible-content .richtext-block ol {
  list-style: decimal;
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .collapsible-content .richtext-block li {
  padding: 0;
  /* theme.min.css sets `ul li` inside, which pushed the text to 51. */
  list-style-position: outside;
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .collapsible-content .richtext-block li::before {
  content: none;
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .collapsible-content .richtext-block :is(strong, b) {
  font-weight: 700;
}

[data-wetheme-section-type='template--product'] .collapsible-tab-container .collapsible-content .richtext-block a {
  color: inherit;
  background: none;
  text-decoration: underline;
  text-decoration-thickness: from-font;
  text-underline-position: from-font;
}

/* ==========================================================================
   9 — GW PRESS LOGOS  (Figma 31:2 / 31:12)
   ========================================================================== */

.gw-pdp-press-logos {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 24px;
  width: 100%;
}

.gw-pdp-press-logos__heading {
  margin: 0;
  font-family: var(--gw-pdp-font);
  font-size: 18px;
  font-weight: 400;
  line-height: normal;
  text-align: center;
  text-transform: none;
  color: var(--gw-pl-heading-color, #191a1a);
}

.gw-pdp-press-logos__row {
  display: flex;
  align-items: stretch;
  gap: 8px;
  width: 100%;
}

.gw-pdp-press-logos__tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: 1 1 0;
  min-width: 0;
  /* 23 — stroke inside the frame. */
  padding: 23px;
  border: 1px solid var(--gw-pl-tile-border, #e9ded7);
  border-radius: 0;
}

/* Figma pins a BOX per logo and letterboxes the artwork inside it with
   object-contain — the boxes (141x48, 150x48, 140x40) are not the sources'
   own aspect ratios (6.02, 3.97, 3.78), so `height: auto` collapses the tile.
   The box is what makes the tile 96 tall: 48 + 23 + 23 + 2 border. */
.gw-pdp-press-logos__img {
  display: block;
  width: 141px;
  height: 48px;
  max-width: 100%;
  object-fit: contain;
}

.gw-pdp-press-logos__tile:nth-child(2) .gw-pdp-press-logos__img {
  width: 150px;
  height: 48px;
}

.gw-pdp-press-logos__tile:nth-child(3) .gw-pdp-press-logos__img {
  width: 140px;
  height: 40px;
}

/* brightness(0), not grayscale(1): the frame's logos are solid BLACK, and
   grayscale alone would leave CHARISMA's blue as mid-grey. Transparent pixels
   are unaffected, so the artwork keeps its shape. */
.gw-pdp-press-logos--mono .gw-pdp-press-logos__img {
  filter: brightness(0);
}

@media (max-width: 1024px) {
  .gw-pdp-press-logos__tile {
    /* 15 / 11 — stroke inside the frame. */
    padding: 15px 11px;
  }

  /* Mobile drops the fixed boxes: every logo is w-full on its own aspect
     ratio, all 79 wide inside a 103 tile. */
  .gw-pdp-press-logos__img,
  .gw-pdp-press-logos__tile:nth-child(2) .gw-pdp-press-logos__img,
  .gw-pdp-press-logos__tile:nth-child(3) .gw-pdp-press-logos__img {
    width: 100%;
    height: auto;
  }
}

/* ==========================================================================
   10 — GW COLLECTIVE PROMO  (Figma 32:2331 / 32:2572)
   Desktop is one row (icon | text | arrow); mobile regroups into two rows
   (icon + heading) then (body + arrow). Figma adds two wrapper frames on
   mobile that have no desktop counterpart — a grid whose template changes at
   the breakpoint serves both from ONE DOM.
   ========================================================================== */

.gw-pdp-collective-promo {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas:
    'icon heading arrow'
    'icon body    arrow';
  align-items: center;
  gap: 12px 16px;
  /* 15 — stroke inside the frame. */
  padding: 15px;
  background: var(--gw-cp-bg, #fdfaf4);
  border: 1px solid var(--gw-cp-border, #f2ead8);
  border-radius: 0;
  color: var(--gw-cp-text-color, #252626);
  text-decoration: none;
}

.gw-pdp-collective-promo__icon {
  grid-area: icon;
  display: block;
  width: 68px;
  height: 62px;
  color: var(--gw-cp-icon-color, #897244);
  /* The <img> sits at inset 0 / -3.07% / -3.18% / -3.16% and the node is NOT
     overflow-clip, so the bleed renders. Reproduced with a negative margin
     rather than by growing the box, which would move the 16px gap. */
  margin: 0 -2.09px -1.97px -2.15px;
}

.gw-pdp-collective-promo__icon svg,
.gw-pdp-collective-promo__icon-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.gw-pdp-collective-promo__heading {
  grid-area: heading;
  margin: 0;
  font-family: var(--gw-pdp-font);
  font-size: 20px;
  font-weight: 500;
  line-height: normal;
  text-transform: none;
  color: inherit;
}

.gw-pdp-collective-promo__body {
  grid-area: body;
  margin: 0;
  font-family: var(--gw-pdp-font);
  font-size: 16px;
  font-weight: 400;
  line-height: normal;
  color: inherit;
}

.gw-pdp-collective-promo__arrow {
  grid-area: arrow;
  font-family: var(--gw-pdp-font);
  font-size: 16px;
  font-weight: 800;
  line-height: normal;
  white-space: nowrap;
  color: var(--gw-pdp-neutral-900);
}

@media (max-width: 1024px) {
  .gw-pdp-collective-promo {
    grid-template-columns: auto 1fr auto;
    grid-template-areas:
      'icon heading heading'
      'body body    arrow';
    gap: 16px;
  }

  .gw-pdp-collective-promo__icon {
    width: 46px;
    height: 41.9412px;
  }
}

/* ==========================================================================
   11 — EDITOR PLACEHOLDERS
   Only ever rendered under request.design_mode; preview and live emit nothing.
   ========================================================================== */

.gw-pdp-placeholder {
  padding: 16px;
  border: 1px dashed var(--gw-pdp-accent-600);
  background: var(--gw-pdp-accent-50);
  font-family: var(--gw-pdp-font);
  font-size: 14px;
  line-height: 1.4;
  color: var(--gw-pdp-accent-900);
}

/* ==========================================================================
   12 — MOBILE TYPE STEPS
   The only type that changes between breakpoints.
   ========================================================================== */

@media (max-width: 1024px) {
  [data-wetheme-section-type='template--product'] h1.product-details-product-title {
    font-size: 40px;
    /* Present on mobile 30:11018 only. No visible effect on "Georgia
       Necklace"; reproduced because the frame carries it. */
    text-transform: capitalize;
  }
}
