
:root,
.shopify-section {
  /* `--RADIUS-BTN` was here and is GONE: nothing in theme.css, od-custom.css, od-pdp.css or
   * any liquid consumes it. It was a mis-recollection of Broadcast's real second variable,
   * `--RADIUS-SELECT`. Dead CSS that looks load-bearing is worse than no CSS. */
  --btn-radius: 100px;
}

.btn,
.od-btn,
.sliderow__back-button,
.product__submit__add,
.cart-bar .btn,
.shopify-payment-button__button,
button[type="submit"],
input[type="submit"],
.chip,
.filterbar__clear,
/* the quick-size pills revealed on a product card (S / M / L / XL) - real buttons */
.od.pcard__size, .od .pcard__size,
.od.news button, .od .news button,
.od.news input[type="submit"], .od .news input[type="submit"],

.jdgm-paginate__page,
/* ---- found by the Fable review, missed by my own sweep ----------------------------------
 * A1, the important one: the PDP size picker (XS / S / M / L) is a <label> over a hidden
 * input, not an <a> or <button>, so a sweep that queried a/button never classified it. It
 * rendered 42x40 with 0px radius while the quick-size pills on a product CARD were already
 * round - the same control, two shapes, on the same site.
 * The :not() is load-bearing: `.radio__fieldset--swatches` is the COLOUR SWATCH, which brief
 * section 5 lists as already correct and must stay square. */
.radio__fieldset:not(.radio__fieldset--swatches) .radio__button label,
/* A2: quick-view dialog chrome - all painted white squares over the product photo */
.product-quick-add__close,
.slider__button,
.product-upsell__btn,
/* A4: the active-filter chips on a filtered collection */
.active__filters__remove,
.active__filters__clear {
  border-radius: 100px;
}

.badge-box,
.product__price--off {
  border-radius: 0;
}

.quick-add__button {
  border-radius: 3px;
}
@media only screen and (max-width: 749px) {
  /* double class beats the coarse-pointer `.btn { min-height: 44px }` floor further down,
   * which shares specificity with a single class and would otherwise win on order. */
  .quick-add__button.quick-add__button--mini {
    position: relative;
    --btn-size: 36px;
    min-height: 36px;
    height: 36px;
    max-width: 36px;
    padding: 0;
  }
}
@media (pointer: coarse) {
  .quick-add__button--mini::after {
    content: "";
    position: absolute;
    inset: -4px;
  }
}

.jdgm-btn,
.jdgm-write-rev-link,
.jdgm-submit-rev,
.jdgm-widget .jdgm-btn {
  border-radius: 100px !important;
}

/* The newsletter field sits directly beside its button; a pill button against a hard-edged
 * input reads as a mistake rather than a choice, so the pair is rounded together.
 *
 * BOTH selector forms on purpose: `.news` sits on the SAME element as `.od` (the section tag
 * carries both), so the descendant form alone silently matches nothing. Same trap that made
 * the guides mobile flatten a no-op earlier. */
.od.news input[type="email"], .od .news input[type="email"] {
  border-radius: 100px;
}

@media (pointer: coarse) {
  .btn,
  .od-btn,
  .product-upsell__btn,
  .radio__fieldset:not(.radio__fieldset--swatches) .radio__button label,
  .active__filters__remove,
  .active__filters__clear {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* Circular icon buttons: grow the box, keep the circle.
   * BOTH selector forms, and not the bare class: od-custom.css sets `.od .pcard__wish` at
   * (0,2,0), so a (0,1,0) rule here loses no matter that it loads later. */
  .od.pcard__wish, .od .pcard__wish {
    width: 44px;
    height: 44px;
  }

  /* the price filter fields were 13-15px tall, effectively untappable */
  .filter__price__input,
  .filter-group input[type="number"],
  .filter-group input[type="text"] {
    min-height: 44px;
  }

  
  .jdgm-btn,
  .jdgm-write-rev-link {
    min-height: 44px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
  }
}

.btn:not(.btn--text),
/* both forms at (0,2,0): the generated od-custom.css sets `.od .od-btn { transition: all }`
 * at (0,2,0), which beat a bare .od-btn at (0,1,0) - the 5-property list below silently
 * never applied to od buttons. Tied specificity + later file = this wins. */
.od.od-btn, .od .od-btn,
.quick-add__button,
.product__submit__add {
  transition: transform .18s ease, box-shadow .18s ease, background-color .18s ease,
              color .18s ease, border-color .18s ease;
}

@media (hover: hover) {
  /* :not(.product__submit__add) is load-bearing, not style: the sticky cart-bar button is
   * `class="btn ... product__submit__add"`, so excluding it only from a PARALLEL selector
   * list did nothing - it still matched `.btn:not(.btn--text)` and lifted, and its 18px-blur
   * shadow clipped against the bar's overflow:hidden into a flat grey band. Exclusion must
   * live on the same selector that matches. (Gate finding, 2026-08-11.) */
  .btn:not(.btn--text):not(.product__submit__add):hover,
  .od-btn:hover,
  .quick-add__button:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .14);
  }
}

.btn:not(.btn--text):active,
.od-btn:active,
.quick-add__button:active,
.product__submit__add:active {
  transform: translateY(0) scale(.97);
  box-shadow: none;
}

.btn:focus-visible,
.od-btn:focus-visible,
.quick-add__button:focus-visible,
.product__submit__add:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .btn:not(.btn--text),
  .od-btn,
  .quick-add__button,
  .product__submit__add {
    transition: none;
  }
  .btn:not(.btn--text):hover,
  .od-btn:hover,
  .quick-add__button:hover,
  .btn:not(.btn--text):active,
  .od-btn:active,
  .quick-add__button:active,
  .product__submit__add:active {
    transform: none;
    box-shadow: none;
  }
}

/* --- TRUST AFFORDANCES (task 39, 2026-08-11) ---------------------------------------------
 * 1. PDP service line: one-time gentle fade-in. Measured first: the host block
 *    (.product__block.product__text) carries NO data-aos, so this is additive, not a
 *    duplicate of vendor motion. TEXT only - the ijFadeIn image trap does not apply because
 *    this animation ENDS at opacity 1, which is also the resting state; a fill:both animation
 *    is only dangerous when the cascade needs a different resting value.
 * 2. Review-count link: a persistent underline so its clickability is VISIBLE (it looked
 *    like plain text), thickening on hover. Affordance, not decoration.
 * 3. Wishlist heart: a small scale pop on press. Physical feedback, no loops.
 * All three die under prefers-reduced-motion.
 * ---------------------------------------------------------------------------------------- */
@keyframes ijTextIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.product__block.product__text {
  animation: ijTextIn .7s ease .15s both;
}

.reviews__count-link,
.od .reviews__count-link {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: text-decoration-thickness .15s ease, text-underline-offset .15s ease;
}
@media (hover: hover) {
  .reviews__count-link:hover,
  .od .reviews__count-link:hover {
    text-decoration-thickness: 2px;
    text-underline-offset: 4px;
  }
}

.od.pcard__wish svg, .od .pcard__wish svg {
  transition: transform .15s ease;
}
.od.pcard__wish:active svg, .od .pcard__wish:active svg {
  transform: scale(1.2);
}

@media (prefers-reduced-motion: reduce) {
  .product__block.product__text { animation: none; }
  .reviews__count-link, .od .reviews__count-link { transition: none; }
  .od.pcard__wish svg, .od .pcard__wish svg { transition: none; }
  .od.pcard__wish:active svg, .od .pcard__wish:active svg { transform: none; }
}

/* --- Breadcrumbs + koopgids dropdown (PDP, 2026-08-11) --- */
.od-crumbs { font-size: 12px; color: #1c1c1c; display: flex; gap: 8px; flex-wrap: wrap; }
.od-crumbs a { color: inherit; }
.od-crumbs a:hover { text-decoration: underline; }
.od-crumbs [aria-current] { opacity: .65; }
.od-buying-guide { border-top: 1px solid var(--od-line, #e7e7e3); }
.od-buying-guide summary { cursor: pointer; padding: 16px 0; font-weight: 600; font-size: 14px; list-style: none; display: flex; justify-content: space-between; align-items: center; }
.od-buying-guide summary::after { content: "+"; font-weight: 400; }
.od-buying-guide[open] summary::after { content: "\2212"; }
.od-buying-guide__body { padding: 0 0 18px; font-size: 13.5px; line-height: 1.75; }

:root { --od-muted: #1c1c1c; }

.od.footer, .od .footer { background: #141414; border-top-color: #141414; }

.od.footer .od-footer__logo, .od .footer .od-footer__logo { filter: invert(1); }
.od.footer h4, .od .footer h4 { color: #fff; }
.od.footer a, .od .footer a, .od.footer p, .od .footer p { color: rgba(255,255,255,.78); }
.od.footer a:hover, .od .footer a:hover { color: #fff; }
.od .footer__social a { color: #fff; }
.od .footer__social a:hover { color: #fff; opacity: .7; }
.od .footer__bottom { border-top-color: rgba(255,255,255,.16); }
.od .footer__copy, .od .footer__copy a { color: rgba(255,255,255,.6); }

@keyframes ijBounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
.od .footer__social a { animation: ijBounce 2.4s ease-in-out infinite; }
/* 44px touch floor for the 20px social icons; negative margin keeps the visual gap */
@media (pointer: coarse) { .od .footer__social a { min-width: 44px; min-height: 44px; align-items: center; justify-content: center; margin: -12px -6px; } }
.od .footer__social a:nth-child(2) { animation-delay: -.8s; }
.od .footer__social a:nth-child(3) { animation-delay: -1.6s; }
@media (prefers-reduced-motion: reduce) { .od .footer__social a { animation: none; } }

@media (hover: hover) {
  .od .splitfeature__cta {
    opacity: 0;
    transform: translateY(6px);
    transition: opacity .25s ease, transform .25s ease;
    background: #111;
    color: #fff;
    padding: 11px 24px;
    border-radius: 100px;
    border-bottom: 0;
  }
  .od .splitfeature__col:hover .splitfeature__cta,
  .od .splitfeature__col:focus-visible .splitfeature__cta {
    opacity: 1;
    transform: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .od .splitfeature__cta { transition: none; transform: none; }
}

/* The flow space belongs to the GROUP wrapper (.header-sections, 77px), not the header
 * wrapper (0-tall, its header is already absolute inside). :has() lifts the whole group out
 * of flow so the hero tucks underneath; browsers without :has() keep the current in-flow
 * look, which is a graceful fallback, not breakage. */
.header-sections:has([data-header-transparent]) {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: 90;
}
.header__wrapper[data-header-transparent] .theme__header {
  background: transparent;
  transition: background-color .25s ease;
}
.header__wrapper[data-header-transparent]:hover .theme__header,
.header__wrapper[data-header-transparent].js__header__stuck .theme__header {
  background: #fff;
}

.header__wrapper[data-header-transparent]:not(.js__header__stuck):not(:hover) .theme__header,
.header__wrapper[data-header-transparent]:not(.js__header__stuck):not(:hover) .theme__header .navlink,
.header__wrapper[data-header-transparent]:not(.js__header__stuck):not(:hover) .theme__header .navtext,
.header__wrapper[data-header-transparent]:not(.js__header__stuck):not(:hover) .theme__header a {
  color: #fff;
}
.header__wrapper[data-header-transparent]:not(.js__header__stuck):not(:hover) .theme__header .logo__img--color:not(.logo__img--transparent) {
  filter: invert(1);
}
.theme__header .navlink, .theme__header a, .theme__header .logo__img--color {
  transition: color .25s ease, filter .25s ease;
}
@media (prefers-reduced-motion: reduce) {
  .header__wrapper[data-header-transparent] .theme__header { transition: none; }
}

/* --- Site-wide breadcrumb band (top-left below the header) --- */
.od-crumbs-band { padding: 14px 0 0; }

.od .feature5050__media--fit { display: flex; align-items: center; justify-content: center; align-self: stretch; background: transparent; padding: clamp(24px, 4vw, 56px); }
.od .feature5050__media--fit img { width: min(100%, 440px); height: auto; aspect-ratio: 4 / 5; max-height: 550px; object-fit: cover; object-position: 50% 0; min-height: 0; }
@media (max-width: 800px) { .od .feature5050__media--fit { padding: 24px 20px 8px; } .od .feature5050__media--fit img { width: min(100%, 400px); } }

.od.imgbanner--contain { background: linear-gradient(to right, #ddd9cc, #eae6da); color: #1c1c1c; }
.od.imgbanner--contain .imgbanner__img { left: auto; right: clamp(16px, 7vw, 140px); width: auto; height: 100%; object-fit: contain; object-position: bottom; -webkit-mask-image: linear-gradient(to right, transparent, #000 14%, #000 86%, transparent); mask-image: linear-gradient(to right, transparent, #000 14%, #000 86%, transparent); }
.od.imgbanner--contain .imgbanner__overlay { display: none; }
.od.imgbanner--contain .imgbanner__inner h2 { color: #1c1c1c; text-shadow: none; }
.od.imgbanner--contain .eyebrow { color: #1c1c1c !important; opacity: .6 !important; }
.od.imgbanner--contain .od-btn--light { background: #1c1c1c; color: #fff; }

@media (max-width: 800px) {
  .od.imgbanner--contain .imgbanner__inner {
    padding-bottom: clamp(36px, 9vw, 56px);
  }
}

@media (max-width: 800px) {
  .od.imgbanner--contain { display: block; min-height: 0; padding-top: 0; }
  .od.imgbanner--contain .imgbanner__img {
    position: static;
    display: block;
    width: 100%;
    height: auto;
    margin: 0 0 clamp(18px, 5vw, 28px);
    -webkit-mask-image: linear-gradient(to bottom, #000 92%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 92%, transparent 100%);
  }
}
.od-crumbs-band .wrap { max-width: var(--od-maxw, 1440px); margin: 0 auto; padding: 0 var(--od-gutter, 18px); }

.swatch__button--square .sibling__link,
.swatch__button--square .swatch__link,
.swatch__button--square input ~ label {
  aspect-ratio: 1 / 1;
  height: auto;
}
@media (pointer: coarse) {
  .swatch__button--square .sibling__link,
  .swatch__button--square .swatch__link,
  .swatch__button--square input ~ label {
    width: 44px;
    min-height: 44px;
  }
}

/* Drawer price was 13px body size while the PDP price renders 18.7px (body-x-large):
 * the drawer's price div carries price--large but not the sizing class. Mirror the PDP. */
.product-quick-add .product__price__wrap .price {
  font-size: 1.44rem;
}

.od .pcard__badge--new {
  background: #4a4c4c;
}
.od .pcard__badge--stack {
  top: 40px;
}

.od.imgbanner, .od .imgbanner { min-height: 66vh; }
.od.videoband, .od .videoband { min-height: 66vh; }

.od.feature5050__media:not(.feature5050__media--fit) img,
.od .feature5050__media:not(.feature5050__media--fit) img { min-height: 560px; }
@media (max-width: 800px) {
  .od.feature5050__media:not(.feature5050__media--fit) img,
  .od .feature5050__media:not(.feature5050__media--fit) img { min-height: 420px; }
}

.od.usp.usp--static {
  border-top: none;
  border-bottom: none;
  background: #fff;
  margin: 0;
  padding: clamp(56px, 7vw, 88px) 0;
}
.od.usp--static .usp__row {
  max-width: var(--od-maxw, 1440px);
  margin: 0 auto;
  padding: 0 var(--od-gutter, 20px);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(28px, 3vw, 56px);
  text-align: center;
}
.od.usp--static .usp__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 0;
  font-size: 15px;
  line-height: 1.5;
  white-space: normal;
  color: var(--od-text);
}
.od.usp--static .usp__item svg {
  width: 40px;
  height: 40px;
  flex: none;
  color: var(--od-cta-2);
}
.od.usp--static .usp__item strong {
  display: block;
  font-size: 18px;
  font-weight: 600;
  color: var(--od-text);
  margin-bottom: 2px;
}
@media (max-width: 760px) {
  .od.usp--static .usp__row {
    grid-template-columns: repeat(2, 1fr);
    gap: 36px 20px;
  }
}

@media (max-width: 760px) {
  .od .pgrid > *,
  .od .tiles--4 > * {
    width: 100%;
  }
}

@media (max-width: 700px) {
  .od .hero__overlay {
    background: linear-gradient(to top, rgba(0,0,0,.82), rgba(0,0,0,.5) 50%, rgba(0,0,0,.6));
  }
  .od .hero p {
    text-shadow: 0 2px 16px rgba(0,0,0,.7), 0 1px 4px rgba(0,0,0,.9);
  }
}

@media (max-width: 700px) {
  .od .section__head h2 {
    font-size: 1.85rem;
  }
}

/* Same undersized-heading fix, extended to the newsletter section (2026-08-20): `.news h2`
 * shares the identical `clamp(1.5rem, 3vw, 2.2rem)` floor (od-custom.css), same 13px root
 * cause, flagged but out of scope on 08-18 since it's a different class. Both selector forms
 * required - `.news` sits on the same element as `.od`, same trap noted elsewhere in this
 * file for the guides mobile flatten. */
@media (max-width: 700px) {
  .od.news h2, .od .news h2 {
    font-size: 1.85rem;
  }
}

@media (max-width: 760px) {
  .od .guides-section .guide {
    width: 100%;
  }
}

/* Named once so the rails, the crumbs and any future full-bleed block cannot
   drift apart again. Value is the collection page's own .grid-outer padding. */
:root { --od-rail-gutter: 50px; }

@media (min-width: 761px) {
  .od.toggle-section > .wrap,
  .od .toggle-section > .wrap {
    max-width: none;
    padding-inline: var(--od-rail-gutter);
  }
}

/* [2] Breadcrumbs: "on mobile and laptop they seem good but on bigger screen it
 * is not being responsive." Same cause as [1] seen from the other side - the
 * band was capped at 1440 and centred while the content beneath it ran full
 * width, so the two left edges separated as the viewport grew. Now one frame at
 * every width, directly under the header, with the air asked for between the
 * trail and the first H1 or image. Supersedes the earlier .od-crumbs-band .wrap
 * rule above, which stays put so the PDP/koopgids block reads in one place. */
.od-crumbs-band .wrap {
  max-width: none;
  margin: 0;
  padding-inline: var(--od-rail-gutter);
}
.od-crumbs-band { padding: 14px 0 24px; }
@media (max-width: 760px) {
  .od-crumbs-band .wrap { padding-inline: var(--od-gutter, 18px); }
  .od-crumbs-band { padding: 12px 0 16px; }
}

@media (max-width: 760px) {
  .od.guides-section .guide,
  .od .guides-section .guide { width: 100%; }
}

/* [4] "all carousels should have arrows on the right bottom so it is also clear
 * it can be swiped. but those should also work of course."
 * The markup is injected by od-site.js and ONLY for a rail that actually
 * overflows, so a grid whose cards already fit never grows a control it cannot
 * use. Everything here is presentation; the behaviour lives in the JS. */
.od-railnav {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 18px;
}
.od-railnav__btn {
  width: 44px;
  height: 44px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--od-line, #e7e7e3);
  border-radius: 100px;
  background: #fff;
  color: var(--od-text, #1c1c1c);
  cursor: pointer;
  transition: background .18s ease, color .18s ease, border-color .18s ease, opacity .18s ease;
}
.od-railnav__btn svg { width: 18px; height: 18px; display: block; }
.od-railnav__btn:hover:not(:disabled) {
  background: var(--od-text, #1c1c1c);
  border-color: var(--od-text, #1c1c1c);
  color: #fff;
}
.od-railnav__btn:focus-visible {
  outline: 2px solid var(--od-text, #1c1c1c);
  outline-offset: 2px;
}
/* Disabled at an end: dimmed but still in the layout, so the pair never jumps. */
.od-railnav__btn:disabled { opacity: .3; cursor: default; }
/* The rails carry a bottom padding for their scrollbar; the arrows sit under
   that, so pull them back up rather than leaving a gap that reads as a break. */
.od .pgrid + .od-railnav,
.od .tiles--4 + .od-railnav,
.od .setsrow + .od-railnav,
.od .subtiles + .od-railnav { margin-top: 2px; }

.od .footer__legal,
.od .footer__meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  font-size: 12px;
}
.od .footer__legal { gap: 8px 18px; }
.od .footer__meta { gap: 6px 28px; }
.od .footer__bottom .footer__legal + .footer__meta { margin-top: -6px; }
/* The old markup was ONE `.footer__copy` span, and the rule above at line ~333
 * (`.od .footer__copy, .od .footer__copy a`) was what made every word in the bar
 * legible on the #141414 footer. Splitting the span into two rows moved the plain
 * text OUT of that span's reach: "Site built by" is not a link, so it fell back to
 * the body colour and rendered #1c1c1c on #141414 - a contrast ratio of 1.06,
 * invisible. The links either side of it stayed light (`.od .footer a`), which is
 * exactly what makes this the kind of bug that passes a glance. Colour is now
 * stated on the rows themselves rather than inherited from a wrapper that no
 * longer contains everything. */
.od .footer__legal,
.od .footer__legal a,
.od .footer__meta,
.od .footer__meta a { color: rgba(255, 255, 255, .6); }
.od .footer__legal a:hover,
.od .footer__meta a:hover { color: #fff; }

/* [6] Collection hero heading. Broadcast hardcodes `<h1 class="hero__title h3">`
 * in collection-image-with-title.liquid, and `.h3` (0,1,0) beats the `h1` element
 * selector (0,0,1), so the page's ONLY h1 rendered at --font-heading-medium =
 * 20px while --font-heading-x-large sat unused at 50px. The h3 class is replaced
 * in that section with this hook rather than swapped for `h2`, so the size is the
 * site's own H1 scale instead of another borrowed step on Broadcast's ladder.
 * Root font-size on this theme is 13px, so this clamp resolves to 23.4px on
 * mobile and 39px on desktop - the same range as `.col-hero h1`. */
.od-hero-h1 { font-size: clamp(1.8rem, 4vw, 3rem); line-height: 1.12; }

/* [7] "the cta block is to big ... All cta buttons should be consistently the same
 * size." Measured at 1785, every .od-btn on the homepage is content width (125,
 * 152, 155, 160, 208px) EXCEPT the two inside feature5050, which are both 717px.
 * Cause: `.od-btn` is `inline-flex`, but an inline-level box used as a FLEX ITEM
 * is blockified to `flex`, and `.feature5050__body` is a COLUMN flex container
 * whose default `align-items: stretch` then pulls the item across the full cross
 * axis. Every other CTA sits in a block parent or a ROW flex container, where
 * stretch does nothing horizontally - which is exactly why only these two grew.
 * Scoped rather than applied to `.od-btn` globally on purpose: the newsletter
 * button is a row-flex sibling of its input and RELIES on stretch to match that
 * input's height, so a blanket align-self would break an alignment that is
 * currently correct. Mobile inherits this and gets the same content width, which
 * is what "consistent everywhere" asks for. */
.od .feature5050__body .od-btn { align-self: flex-start; }

/* [8] "this image should be slightly bigger". The fit variant was capped at
 * 440px wide / 550px tall inside an 893px media column, so it filled under half
 * of its own half of the section. Raised about 18%. Mobile is untouched: the
 * 800px rule below still pins width to min(100%, 400px), and at 390 that is a
 * 354x442 box, nowhere near this max-height, so the cap cannot reach it. */
@media (min-width: 801px) {
  .od .feature5050__media--fit img { width: min(100%, 520px); max-height: 650px; }
}

.od.pcard__media,
.od .pcard__media { aspect-ratio: 4 / 5; }

/* The vendor card sizes its image with the padding-top ratio trick driven by a theme
 * variable, not by aspect-ratio, so it has to be set in its own currency: for 4:5 the
 * padding is height/width = 5/4 = 125%. Measured before: 0.669 (about 2:3, ~149.5%). */
.product-item__image { --PRODUCT-GRID-ASPECT-RATIO: 125%; }

.quick-add__holder {
  display: flex;
  justify-content: center;
}

.quick-add__holder {
  top: var(--btn-offset);
  bottom: auto;
  justify-content: flex-start;
}

/* Pinned back: "You may also like" keeps the centred, bottom placement he asked for. The
 * section is `.tabs__recommendation`; the collection grid is `.collection__products`, so
 * the two surfaces are cleanly separable without touching the card markup. */
.tabs__recommendation .quick-add__holder {
  top: auto;
  bottom: var(--btn-offset);
  justify-content: center;
}

.quick-add__holder .quick-add__button {
  margin-left: 0;
  margin-right: 0;
}

.od-gendernav {
  /* The vendor drawer gives its blocks a side gutter; our nav replaces the
   * block's inner list, so it has to carry the gutter itself or every row sits
   * flush against the viewport edge (measured x=0 on the first deploy). */
  padding: 4px var(--od-gutter, 16px) 8px;
}

/* The tab row. Scrolls horizontally rather than wrapping, so a fourth or fifth
 * top-level item can never push the row into two lines inside a 390 drawer. */
/* Specificity note: od-custom.css ships `.od .favtoggle` (0,2,0), which beats a
 * bare `.od-gendernav__tabs` (0,1,0). Measured after the first deploy: display
 * computed to inline-flex and width:100% never applied, so the row could not
 * scroll and would clip a fourth tab on a 360 or 320 phone. Match the vendor's
 * specificity instead of fighting it with !important. */
.od .favtoggle.od-gendernav__tabs {
  display: flex;
  width: 100%;
  box-sizing: border-box;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.od-gendernav__tabs::-webkit-scrollbar { display: none; }
.od-gendernav__tabs .favtoggle__btn {
  flex: 1 0 auto;
  white-space: nowrap;
}

/* The panel. .favgrid already handles display none/block + the fade, so this
 * only owns the list inside it. */
.od-gendernav__list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.od-gendernav__list li { margin: 0; }
.od-gendernav__list a {
  display: block;
  padding: 14px 0;
  text-decoration: none;
  color: var(--od-text);
  border-bottom: 1px solid var(--od-line);
}
.od-gendernav__list a:hover,
.od-gendernav__list a:focus-visible { text-decoration: underline; }
.od-gendernav__list a[aria-current="page"] { font-weight: 600; }

.od-gendernav__all a {
  font-weight: 600;
  border-bottom: 0;
}

/* Sale / New Arrivals have no children, so they are not tabs. They sit under
 * the panels as direct rows, and SALE keeps the highlight colour the vendor
 * drawer gave it. */
.od-gendernav__list--flat {
  margin-top: 4px;
  border-top: 1px solid var(--od-line);
}
/* Measured: the class WAS applied and --highlight DID resolve to #d02e2e, but
 * the colour still computed black, because `.od-gendernav__list a` (0,1,1) beats
 * `.od-gendernav__highlight` (0,1,0). Own the element, not just the modifier. */
.od-gendernav__list a.od-gendernav__highlight { color: var(--highlight, #d02e2e); }

@media (min-width: 1024px) {
  .od-gendernav__list a { padding: 12px 0; }
}

.od-collection-count {
  margin: 10px 0 0;
  font-size: 13px;
  letter-spacing: .04em;
  color: var(--od-muted);
}

.od-nav-count {
  display: none;
  font-size: 12px;
  letter-spacing: .04em;
  color: var(--od-muted);
  white-space: nowrap;
}
@media (max-width: 767px) {
  .collection__nav { justify-content: space-between; }
  .od-nav-count { display: inline-block; order: 0; }
}

.od-relcol { padding-top: 8px; }
.od-relcol__desc {
  margin: 4px 0 0;
  font-size: 12px;
  line-height: 1.4;
  opacity: .85;
}
@media (max-width: 700px) {
  .od-relcol .tiles,
  .od-relcol.tiles { grid-template-columns: 1fr 1fr; }
}

/* Card colour swatches. Colour is a separate PRODUCT here, so each swatch is a
 * sibling product's own photo rather than a colour chip - we hold no hex values,
 * and inventing them would be guessing at the garment. */
.pcard__swatches {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-top: 7px;
  min-height: 24px;
}
.pcard__swatch {
  width: 24px;
  height: 24px;
  border-radius: 100px;          /* the pill system reaches here too */
  overflow: hidden;
  cursor: pointer;
  border: 1px solid var(--od-line);
  background: var(--od-grey);
  flex: 0 0 auto;
  transition: border-color .15s ease, transform .15s ease;
}
.pcard__swatch img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.pcard__swatch:hover { transform: scale(1.08); }
.pcard__swatch.is-current { border-color: var(--od-text); border-width: 2px; }
.pcard__swatch--more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  color: var(--od-muted);
  cursor: default;
  background: none;
}
.pcard__swatch--more:hover { transform: none; }

/* Phones: the grid is 2-up, so cap the row rather than let six thumbs wrap and
 * push the price line around. */
@media (max-width: 480px) {
  .pcard__swatch { width: 20px; height: 20px; }
  .pcard__swatches { gap: 4px; }
}

.product-item .badge-box-container.align--top-left {
  left: auto;
  right: 0;
  text-align: right;
}
.product-item .badge-box-container.align--top-left .badge-box {
  margin-left: auto;
}

/* Demo preview: the demonstration notice sits above the site container. The transparent
 * header group is absolutely positioned, so anchor it to the container rather than the page,
 * otherwise it paints over the notice. No effect when nothing precedes the container. */
.container[data-site-container] { position: relative; }

/* Announcement bar: a solid black strip, so its copy stays legible when the header group
 * overlays the homepage hero. */
.announcement__wrapper { background: #141414; color: #fff; }
.announcement__wrapper a, .announcement__wrapper p { color: #fff; }

/* The mobile menu icon ships with a hard-coded black stroke; follow the header's white
 * chrome while the header is transparent over the hero. */
.header__wrapper[data-header-transparent]:not(.js__header__stuck):not(:hover) .header__mobile__hamburger .icon-menu path { stroke: #fff; }

/* Sticky collection bar on mobile: keep the product count off the screen edge. */
@media (max-width: 767px) {
  .od-nav-count { padding-left: 16px; }
}

/* Plain content pages (size guide, delivery, returns, legal) render page.content through the
 * size chart section. Store-written h2s inherited the display heading size, so they were
 * larger than the page title and sat on the text with no space. */
.od-sizechart .rte h2 { font-size: clamp(1.1rem, 1.6vw, 1.35rem); font-weight: 600; letter-spacing: -0.005em; margin: 36px 0 10px; }
.od-sizechart .rte p { margin: 0 0 14px; line-height: 1.7; }
.od-sizechart .rte > p:first-child { text-align: center; color: var(--od-muted); margin-bottom: 8px; }
.od-sizechart .rte table { margin: 8px 0 12px; }
