/* bm-overrides.css: hand-written, site-wide.
 *
 * Loaded on EVERY template, after bm-custom.css, for rules that must reach Broadcast's own
 * chrome as well as our ported sections. bm-pdp.css stays product-only; bm-custom.css is
 * GENERATED and scoped under .ij, so neither can do this job.
 *
 * --------------------------------------------------------------------------------------
 * PILL BUTTONS (client via the client, 2026-08-11): "keep all buttons round / oval, no square or
 * rectangle."
 *
 * SETTLED 2026-09-07 (the client): "keep it round if that is the site's consistency." The pill
 * is the site's system and it wins. This closes the conflict that stood open since 08-11,
 * where the brand brief dated 2026-08-10 said the opposite in section 3 ("Sharp
 * rectangular buttons, 0px radius") under a heading reading KEEP WHAT THE DRAFT THEME
 * DOES. The brief loses; the pill stays.
 *
 * Consequence, so nobody re-litigates it: a later request for rectangular buy buttons
 * was shipped as a radius-0 override on the buy actions and then REVERTED the same day.
 * Do not re-add it. One inconsistent control is worse
 * than one control the client would have styled differently.
 *
 * CORRECTION (Fable review, 2026-08-11): Broadcast DOES have a radius setting - Buttons >
 * `btn_border_style` (Square / Rounded / Pill), mapped in snippets/head.liquid, currently
 * "square". My first pass claimed there was none; the grep missed it because it is not named
 * "radius". The override is STILL the right lever, for a better reason than I gave: flipping
 * that setting to Pill rewrites `--RADIUS` for ~29 consumers including
 * `.radio__fieldset .radio__button label`, which is the PROTECTED colour swatch. So we round
 * buttons deliberately instead of flipping a global.
 *
 * Circular icon buttons already at 50% are left alone - they are round.
 *
 * NOT ROUNDED, and deliberately: .tile, .splitfeature__col and .product__thumb__link. Those
 * are image cards and gallery thumbnails wrapped in an <a>, not buttons. Rounding product
 * imagery is a visual-system change the brief did not ask for, and section 5 lists the
 * surrounding pieces as already correct.
 * -------------------------------------------------------------------------------------- */
:root,
.shopify-section {
  /* `--RADIUS-BTN` was here and is GONE: nothing in theme.css, bm-custom.css, bm-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,
.bm-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 */
.ij.pcard__size, .ij .pcard__size,
.ij.news button, .ij .news button,
.ij.news input[type="submit"], .ij .news input[type="submit"],
/* Judge.me injects its own buttons into the PDP after our CSS loads. They are real buttons,
 * so they follow the rule; the widget is app-rendered but plain DOM, so a rule reaches it. */
.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;
}

/* ---- COLLATERAL, PINNED BACK (Fable B) --------------------------------------------------
 * `--btn-radius` is read by two NON-buttons as well as the buttons: `.badge-box` (the "new"
 * badge) and `.product__price--off` (the "50% OFF" badge). Rounding the variable silently
 * turned both into pills, which nobody asked for. A badge is not a button, and the brief is
 * explicit about not adding discount surfaces - making the sale badge softer and friendlier
 * pushes the wrong way. Pinned back to square; one line to remove if the client wants them
 * rounded too. */
.badge-box,
.product__price--off {
  border-radius: 0;
}

/* --- QUICK-ADD BUTTON: square + smaller (client 2026-08-11) ------------------------------
 * The round pill quick-add did not look right; the approved look is live's square
 * mini, square but smaller. So: 3px corners (live's square
 * btn_border_style) instead of the pill, and on touch layouts a 36px box instead of the
 * padded pill. The 44px coarse-pointer tap floor is kept INVISIBLY - ::after extends the
 * hit area 4px per side, so the target stays WCAG-sized while the visual shrinks. */
.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;
  }
}

/* Judge.me. My first explanation was wrong: it is not load order, it is SPECIFICITY. Their
 * base.css carries `.jdgm-widget .jdgm-btn.jdgm-btn` at (0,3,0), which outranks any plain
 * one- or two-class rule regardless of order. !important is kept because it is measured
 * working; the tidier alternatives are a (0,4,0) selector or their own theming variable
 * (`html:root { --jdgm-border-radius: 40 }`), and tidiest of all is the corner-radius setting
 * in the Judge.me admin. */
.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 `.ij` (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. */
.ij.news input[type="email"], .ij .news input[type="email"] {
  border-radius: 100px;
}

/* --- MOBILE TAP TARGETS (CRO pass, 2026-08-11) -------------------------------------------
 * the client's stated priority is mobile, properly CRO optimised. Measured at 320 and 390 with a
 * coarse pointer, these interactive controls all painted a surface UNDER the 44px minimum:
 *   .pcard__wish 34 · .sibling__link 34 · .quick-add__button 36 · .jdgm-btn 33
 *   .filter__price__input 15 · a bare filter input 13 · .btn 39-41 · a size label 40
 *
 * Scoped to `pointer: coarse` on purpose. These sizes are fine under a mouse, and inflating
 * them on desktop would loosen a layout the brief calls already correct; the 44px floor is a
 * touch requirement, not a visual preference.
 *
 * min-height rather than height, so nothing that already exceeds it gets squashed, and
 * inline-flex centring so the label does not sit at the top of a taller box.
 * ---------------------------------------------------------------------------------------- */
@media (pointer: coarse) {
  .btn,
  .bm-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: bm-custom.css sets `.ij .pcard__wish` at
   * (0,2,0), so a (0,1,0) rule here loses no matter that it loads later. */
  .ij.pcard__wish, .ij .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;
  }

  /* Judge.me again needs the specificity, same reason as its radius */
  .jdgm-btn,
  .jdgm-write-rev-link {
    min-height: 44px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
  }
}

/* --- CTA MICRO-INTERACTIONS (the client 2026-08-11) --------------------------------------------
 * "Interactive animations that visualize the site better and highlight things like CTAs."
 * Register per the brief: calm and premium. So: a small lift with a soft shadow on hover, a
 * pressed scale on tap, a visible focus ring. NO pulsing, NO shimmer, NO attention loops -
 * those are urgency devices the brief bans.
 *
 * Hover is gated behind (hover: hover) so touch devices never get a stuck hover state; they
 * get the :active press feedback instead, which reads as physical response. .btn--text is
 * excluded - lifting a text link looks broken, not premium.
 * ---------------------------------------------------------------------------------------- */
.btn:not(.btn--text),
/* both forms at (0,2,0): the generated bm-custom.css sets `.ij .bm-btn { transition: all }`
 * at (0,2,0), which beat a bare .bm-btn at (0,1,0) - the 5-property list below silently
 * never applied to ij buttons. Tied specificity + later file = this wins. */
.ij.bm-btn, .ij .bm-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,
  .bm-btn:hover,
  .quick-add__button:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .14);
  }
}

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

.btn:focus-visible,
.bm-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),
  .bm-btn,
  .quick-add__button,
  .product__submit__add {
    transition: none;
  }
  .btn:not(.btn--text):hover,
  .bm-btn:hover,
  .quick-add__button:hover,
  .btn:not(.btn--text):active,
  .bm-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,
.ij .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,
  .ij .reviews__count-link:hover {
    text-decoration-thickness: 2px;
    text-underline-offset: 4px;
  }
}

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

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

/* --- Breadcrumbs + buying guide dropdown (PDP, 2026-08-11) --- */
.bm-crumbs { font-size: 12px; color: #1c1c1c; display: flex; gap: 8px; flex-wrap: wrap; }
.bm-crumbs a { color: inherit; }
.bm-crumbs a:hover { text-decoration: underline; }
.bm-crumbs [aria-current] { opacity: .65; }
.bm-buying-guide { border-top: 1px solid var(--bm-line, #e7e7e3); }
.bm-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; }
.bm-buying-guide summary::after { content: "+"; font-weight: 400; }
.bm-buying-guide[open] summary::after { content: "\2212"; }
.bm-buying-guide__body { padding: 0 0 18px; font-size: 13.5px; line-height: 1.75; }

/* --- Clear black text (the client 2026-08-11): the grey muted tone reads washed on white --- */
:root { --bm-muted: #1c1c1c; }

/* --- Black footer (the client 2026-08-11) --- */
.ij.footer, .ij .footer { background: #141414; border-top-color: #141414; }
/* the client 2026-08-12: the logo lockup is black-on-transparent - invisible on the dark footer.
   Invert flips the monochrome mark to white (same stopgap as the transparent header). */
.ij.footer .bm-footer__logo, .ij .footer .bm-footer__logo { filter: invert(1); }
.ij.footer h4, .ij .footer h4 { color: #fff; }
.ij.footer a, .ij .footer a, .ij.footer p, .ij .footer p { color: rgba(255,255,255,.78); }
.ij.footer a:hover, .ij .footer a:hover { color: #fff; }
.ij .footer__social a { color: #fff; }
.ij .footer__social a:hover { color: #fff; opacity: .7; }
.ij .footer__bottom { border-top-color: rgba(255,255,255,.16); }
.ij .footer__copy, .ij .footer__copy a { color: rgba(255,255,255,.6); }

/* --- Bouncing social icons (the client asked explicitly). Soft, slow, staggered; killed under
 * reduced motion. Flagged once: a continuous loop sits at the edge of the brief's
 * no-attention-devices rule - same precedent as the marquees, the client's call. --- */
@keyframes ijBounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
.ij .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) { .ij .footer__social a { min-width: 44px; min-height: 44px; align-items: center; justify-content: center; margin: -12px -6px; } }
.ij .footer__social a:nth-child(2) { animation-delay: -.8s; }
.ij .footer__social a:nth-child(3) { animation-delay: -1.6s; }
@media (prefers-reduced-motion: reduce) { .ij .footer__social a { animation: none; } }

/* --- Split feature (two columns): SHOP NOW appears as a black pill only on image hover ---
 * Desktop only - on touch there is no hover, so the underline CTA stays always visible. */
@media (hover: hover) {
  .ij .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;
  }
  .ij .splitfeature__col:hover .splitfeature__cta,
  .ij .splitfeature__col:focus-visible .splitfeature__cta {
    opacity: 1;
    transform: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .ij .splitfeature__cta { transition: none; transform: none; }
}

/* --- Transparent header (the client 2026-08-11): white only on hover / when stuck --------------
 * Broadcast's transparent_home flag sets data-header-transparent but on this build left the
 * header in flow (white gap above the hero) and painted nothing when stuck. Three rules
 * finish it, scoped to the attribute so only transparent-enabled templates are touched:
 * at rest the header overlays the hero, transparent; hovering or sticking paints it white. */
/* 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;
}

/* While genuinely transparent (not hovered, not stuck) the chrome goes WHITE - the measured
 * alternative was near-invisible dark nav over the dark hero video. The logo is a black PNG,
 * inverted here as a stopgap: the CLEAN fix is the client uploading the white logo into the
 * header's own "transparent logo" setting, which then wins (Broadcast swaps the image and
 * the invert below stops matching). Everything reverts the moment white paints. */
.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) --- */
.bm-crumbs-band { padding: 14px 0 0; }

/* the client 2026-08-11 (#45): feature5050 "fit" mode = a COMPACT image box. The image IS the
   box: fixed 4/5 aspect, size-capped, centered in its half - not a photo floating on a
   full-height grey slab, and never taller than the section. Overrides the generated 3/2
   landscape assumption, which decapitated the portrait shoot images. */
.ij .feature5050__media--fit { display: flex; align-items: center; justify-content: center; align-self: stretch; background: transparent; padding: clamp(24px, 4vw, 56px); }
.ij .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) { .ij .feature5050__media--fit { padding: 24px 20px 8px; } .ij .feature5050__media--fit img { width: min(100%, 400px); } }

/* the client 2026-08-11 (#50): banner "contain" variant - the ENTIRE portrait photo, right of
   the copy on a band matched to the shoot backdrop, soft-blended at its left edge. Dark
   copy, no scrim, dark CTA. Mobile stacks: copy on top, full photo under it. */
.ij.imgbanner--contain { background: linear-gradient(to right, #ddd9cc, #eae6da); color: #1c1c1c; }
.ij.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); }
.ij.imgbanner--contain .imgbanner__overlay { display: none; }
.ij.imgbanner--contain .imgbanner__inner h2 { color: #1c1c1c; text-shadow: none; }
.ij.imgbanner--contain .eyebrow { color: #1c1c1c !important; opacity: .6 !important; }
.ij.imgbanner--contain .bm-btn--light { background: #1c1c1c; color: #fff; }

/* Client 08-11, first item of the mobile list: the banner button needed space below it. At
 * 393 the banner button's bottom edge sat at the section's EXACT last pixel, flush
 * against the Bestsellers rail. Mobile-only air under the CTA; desktop keeps the
 * flex-centred composition. */
@media (max-width: 800px) {
  .ij.imgbanner--contain .imgbanner__inner {
    padding-bottom: clamp(36px, 9vw, 56px);
  }
}
/* the client 2026-09-06: on mobile this band read as "2 different backgrounds in one image".
 * MEASURED CAUSE, not guessed. The band is a hand-picked LEFT-TO-RIGHT gradient
 * (#ddd9cc -> #eae6da) chosen to sit under one particular shoot. That photo's own studio
 * backdrop runs DIAGONALLY: sampled corners are 221,218,206 (TL) -> 231,226,212 (TR) ->
 * 233,230,217 (BL) -> 239,232,219 (BR), i.e. it also brightens downward, which a
 * to-right gradient cannot follow. Desktop hides the mismatch behind an edge mask; the
 * mobile rule above deliberately removed that mask (mask-image:none) while keeping the
 * band, so the photo ended as a hard-edged rectangle 47px in from each side, on a band
 * that was ~14 RGB points darker than the photo by its lower half. Hence two backgrounds.
 * Fix is structural rather than another hand-matched colour: the photo goes FULL BLEED,
 * so no band is visible beside or above it and there is nothing left to mismatch. Only
 * the bottom edge still meets the band, and that one seam is dissolved with the same mask
 * technique desktop already uses. Starts at 92% so the fade sits in the empty floor
 * BELOW the model's shoes (measured: feet end at ~94% of the frame), never across her.
 * Works for any future image because nothing here is tuned to this photo's colours. */
@media (max-width: 800px) {
  .ij.imgbanner--contain { display: block; min-height: 0; padding-top: 0; }
  .ij.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%);
  }
}
.bm-crumbs-band .wrap { max-width: var(--bm-maxw, 1440px); margin: 0 auto; padding: 0 var(--bm-gutter, 18px); }

/* --- SIBLING COLOUR SWATCHES: square photo chips (client 08-11: price too small and
 * photos looked wrong, quick-add drawer). ROOT CAUSE WAS OURS: the coarse-pointer 44px tap floor
 * on .sibling__link stretched the 29px-wide swatch into a 29x44 box, exposing a 15px slab
 * of the fallback swatch COLOUR under the photo - the "broken photos". The floor is kept,
 * but as a SQUARE: on touch the box is 44x44 and the photo fills it; on fine pointers the
 * vendor's --swatch-size square renders untouched. .sibling__link is out of the generic
 * 44px min-height list for the same reason (its inline-flex centring also fought the
 * figure). Reaches the PDP sibling row and the quick-add drawer alike. */
.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;
}

/* NEW badge on the home rail cards, which were missing it. Same source and same colour
 * as Broadcast's collection-grid badge (badge_bg_color
 * #4a4c4c), so grid and rails read identically. --stack drops it below the Sale badge on
 * the rare card that carries both. */
.ij .pcard__badge--new {
  background: #4a4c4c;
}
.ij .pcard__badge--stack {
  top: 40px;
}

/* Client feedback 08-17, item 1: several homepage full-bleed bands read "big, small, big" -
 * inconsistently sized next to each other - and the client wants them bigger, filling more
 * of the screen, like a larger-block homepage. imgbanner (54vh) and
 * videoband (60vh) were two different heights for the same visual role (full-bleed emotive
 * banner); feature5050's image column (460px desktop / 340px mobile) read comparatively
 * thin next to them. Unify and grow all three rather than touch section order/count here -
 * that is items 2-4. Overrides bm-custom.css (GENERATED by port-home.py - see
 * the client build.md guardrail 5 - never hand-edited
 * directly); same selectors, later in the cascade. */
.ij.imgbanner, .ij .imgbanner { min-height: 66vh; }
.ij.videoband, .ij .videoband { min-height: 66vh; }
/* :not(--fit) so this never fights the deliberate compact "fit" box mode (the client 08-11, same
 * file above) - that mode already pins its own min-height:0 at equal (0,2,1) specificity,
 * and this rule sits later in the cascade so it would otherwise win and blow the box open. */
.ij.feature5050__media:not(.feature5050__media--fit) img,
.ij .feature5050__media:not(.feature5050__media--fit) img { min-height: 560px; }
@media (max-width: 800px) {
  .ij.feature5050__media:not(.feature5050__media--fit) img,
  .ij .feature5050__media:not(.feature5050__media--fit) img { min-height: 420px; }
}

/* Client feedback 08-17, item 3: trust/USP band rebuilt static in bm-trust-marquee.liquid
 * (no more `.usp__marquee`/`.usp__track` in the markup, so those generated animation rules
 * simply no longer match anything). `.usp--static` lays the same items out as a bigger,
 * non-scrolling row: icon above text, generous padding, full page width. Relocated in
 * templates/index.json to sit directly under the first video band (see item 4 for reviews
 * moving to sit directly under this). */
.ij.usp.usp--static {
  border-top: none;
  border-bottom: none;
  background: #fff;
  margin: 0;
  padding: clamp(56px, 7vw, 88px) 0;
}
.ij.usp--static .usp__row {
  max-width: var(--bm-maxw, 1440px);
  margin: 0 auto;
  padding: 0 var(--bm-gutter, 20px);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(28px, 3vw, 56px);
  text-align: center;
}
.ij.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(--bm-text);
}
.ij.usp--static .usp__item svg {
  width: 40px;
  height: 40px;
  flex: none;
  color: var(--bm-cta-2);
}
.ij.usp--static .usp__item strong {
  display: block;
  font-size: 18px;
  font-weight: 600;
  color: var(--bm-text);
  margin-bottom: 2px;
}
@media (max-width: 760px) {
  .ij.usp--static .usp__row {
    grid-template-columns: repeat(2, 1fr);
    gap: 36px 20px;
  }
}
/* Client feedback 08-17, item 6: on a phone the next product/tile card already peeked into
 * view before swiping, reading as a broken carousel instead of one card per screen. The
 * 62% snap width in generated bm-custom.css (same media query, same selector) was a
 * deliberate earlier call documented in that file - "62% is right on a phone" - which this
 * client round explicitly overrides: exactly one block per viewport, no peek. Overrides
 * bm-custom.css (GENERATED by port-home.py, never hand-edited - LOOP-BRIEF.md guardrail 5);
 * identical selector/media-query, later in the cascade, so no !important needed. Reaches the
 * two homepage product rails (.pgrid) and the collection
 * tiles (.tiles--4) - the two card carousels sharing this rule. The tabbed guides scroller
 * (.guides-section .guide, separate rule, 76% width) is a different component and is left
 * alone here; flag if the client meant that one specifically. */
@media (max-width: 760px) {
  .ij .pgrid > *,
  .ij .tiles--4 > * {
    width: 100%;
  }
}

/* Client feedback 08-18, item 2: the hero subtext read as
 * barely legible on mobile. The heading already carries a text-shadow (bm-custom.css
 * `.ij .hero h1`), but the subtext (`.ij .hero p`) never did - it leans entirely on
 * `.hero__overlay`'s gradient, which is weakest right where the copy sits: flex-end anchors
 * the text block near the bottom, but the gradient's own bottom stop is only rgba(0,0,0,.5),
 * lighter than its .72 peak higher up. A bright frame of the looping video can wash the text
 * out at any given moment, and it is worse on phones because the hero collapses to 74vh there
 * (existing `@media (max-width:700px)` rule in bm-custom.css), pulling the text block
 * proportionally further from the darkest part of the gradient. Fix: deepen the overlay and
 * add a real text-shadow to the subtext, scoped to that same 700px breakpoint so desktop
 * (where this was not reported, and the gradient already reads fine against a large frame)
 * is untouched. Client's separate "totally broken" comment on the hero is addressed mostly by
 * item 1 (dropping the cramped two-button row); no layout defect found here on code review -
 * see item 5 notes. */
@media (max-width: 700px) {
  .ij .hero__overlay {
    background: linear-gradient(to top, rgba(0,0,0,.82), rgba(0,0,0,.5) 50%, rgba(0,0,0,.6));
  }
  .ij .hero p {
    text-shadow: 0 2px 16px rgba(0,0,0,.7), 0 1px 4px rgba(0,0,0,.9);
  }
}

/* Client feedback 08-18, item 3: the first product rail's section heading read too small on
 * mobile relative to the section beneath it. `.section__head h2` clamps to
 * `clamp(1.5rem, 3vw, 2.2rem)` (bm-custom.css) - on a phone, 3vw never reaches the 1.5rem
 * floor until ~650px viewport width, so every phone renders the flat minimum. Root
 * font-size on this theme is 13px (Theme settings > Typography > base_font_size, current
 * value 13 - NOT the usual 16px browser default), so that 1.5rem floor is ~19.5px on screen:
 * visibly smaller than this SAME page's other section headings on mobile (videoband/imgbanner
 * both floor at 1.8rem, ~23.4px) for no content reason - this class was the outlier.
 * Overriding the shared `.section__head h2` class (not a single-instance fix) reaches every
 * section that uses it on this page: new-in/bestsellers (product rails), fav-collections
 * (tiles toggle), guides. */
@media (max-width: 700px) {
  .ij .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 (bm-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 `.ij`, same trap noted elsewhere in this
 * file for the guides mobile flatten. */
@media (max-width: 700px) {
  .ij.news h2, .ij .news h2 {
    font-size: 1.85rem;
  }
}

/* Client feedback 08-18, item 4: client explicitly confirmed the Gidsen & Advies mobile
 * carousel needs the SAME one-card-per-viewport fix as item 6/08-17 (5d6c862, the
 * .pgrid/.tiles--4 rule above) - that commit deliberately left `.guides-section .guide`
 * (76% width, bm-custom.css, same 760px media query) untouched pending confirmation the
 * client meant that carousel too: "this not fixed yet for mobile, only one card per frame
 * like you did with the collection sections." Confirmed now. Identical technique: override
 * the generated 76% snap width to 100% at the same breakpoint the generated rule already
 * uses, later in the cascade, no !important needed. scroll-snap itself stays in the
 * generated file, untouched, so snapping behaviour is unaffected. */
@media (max-width: 760px) {
  .ij .guides-section .guide {
    width: 100%;
  }
}

/* ==========================================================================
   the client feedback 2026-09-06. Five items; three of them share ONE root cause.
   The collection page is the frame the client named as correct: its `.grid-outer`
   runs the FULL viewport width with a flat 50px gutter and no max-width. The
   homepage `.wrap` and the breadcrumb band instead cap at --bm-maxw (1400px)
   and centre. Measured at 1785: the collection grid sits 50px from each edge,
   every homepage rail sits 249px in. That is 398px of screen discarded, and it
   is also why the crumbs land on a different left edge than the content under
   them. All of it below adopts the collection page's frame as the one answer.
   ========================================================================== */

/* 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 { --bm-rail-gutter: 50px; }

/* [1] The tabbed homepage blocks were not taking the full width of the screen,
 * while the collection page already did.
 * `.toggle-section` is precisely the four blocks pointed at and nothing else:
 * the two product rails, the collection tiles and the tabbed guides.
 * Mobile is deliberately NOT touched: there the gutter is already 18px, so
 * forcing 50px would make these blocks narrower, the opposite of the ask. */
@media (min-width: 761px) {
  .ij.toggle-section > .wrap,
  .ij .toggle-section > .wrap {
    max-width: none;
    padding-inline: var(--bm-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 .bm-crumbs-band .wrap
 * rule above, which stays put so the PDP/buying guide block reads in one place. */
.bm-crumbs-band .wrap {
  max-width: none;
  margin: 0;
  padding-inline: var(--bm-rail-gutter);
}
.bm-crumbs-band { padding: 14px 0 24px; }
@media (max-width: 760px) {
  .bm-crumbs-band .wrap { padding-inline: var(--bm-gutter, 18px); }
  .bm-crumbs-band { padding: 12px 0 16px; }
}

/* [3] "Gidsen & advies ... should be a proper carousel, with one per frame, now
 * the next one is already visible."
 * The 08-19 commit (b89d6dd) already tried exactly this and SILENTLY DID
 * NOTHING. It wrote `.ij .guides-section .guide` - a DESCENDANT selector - but
 * `ij` and `guides-section` sit on the SAME element (<section class="ij section
 * toggle-section guides-section">), so it matched zero nodes. The generated rule
 * it meant to beat is the COMPOUND `.ij.guides-section .guide`. That is why the
 * card was still min(76%, 340px) = 269px inside a 354px track, leaving the next
 * card's edge on screen. Both selector shapes below, so this survives whichever
 * way that wrapper is rebuilt. The dead rule above is kept only as the record of
 * what was tried; this block is the one that actually lands. */
@media (max-width: 760px) {
  .ij.guides-section .guide,
  .ij .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 bm-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. */
.bm-railnav {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 18px;
}
.bm-railnav__btn {
  width: 44px;
  height: 44px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--bm-line, #e7e7e3);
  border-radius: 100px;
  background: #fff;
  color: var(--bm-text, #1c1c1c);
  cursor: pointer;
  transition: background .18s ease, color .18s ease, border-color .18s ease, opacity .18s ease;
}
.bm-railnav__btn svg { width: 18px; height: 18px; display: block; }
.bm-railnav__btn:hover:not(:disabled) {
  background: var(--bm-text, #1c1c1c);
  border-color: var(--bm-text, #1c1c1c);
  color: #fff;
}
.bm-railnav__btn:focus-visible {
  outline: 2px solid var(--bm-text, #1c1c1c);
  outline-offset: 2px;
}
/* Disabled at an end: dimmed but still in the layout, so the pair never jumps. */
.bm-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. */
.ij .pgrid + .bm-railnav,
.ij .tiles--4 + .bm-railnav,
.ij .setsrow + .bm-railnav,
.ij .subtiles + .bm-railnav { margin-top: 2px; }

/* [5] Footer bottom bar: "Disclaimers and policy pages should be set up next to
 * each other and below comes: (c) 2026 Brackmoor Stoneworks, then with some space next
 * to it: Site built by Etari Digitals ... not all of it packed next to each
 * other like now." Two rows instead of one run-on line. The markup split lives
 * in sections/bm-footer.liquid. */
.ij .footer__legal,
.ij .footer__meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  font-size: 12px;
}
.ij .footer__legal { gap: 8px 18px; }
.ij .footer__meta { gap: 6px 28px; }
.ij .footer__bottom .footer__legal + .footer__meta { margin-top: -6px; }
/* The old markup was ONE `.footer__copy` span, and the rule above at line ~333
 * (`.ij .footer__copy, .ij .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 (`.ij .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. */
.ij .footer__legal,
.ij .footer__legal a,
.ij .footer__meta,
.ij .footer__meta a { color: rgba(255, 255, 255, .6); }
.ij .footer__legal a:hover,
.ij .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`. */
.bm-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 .bm-btn on the homepage is content width (125,
 * 152, 155, 160, 208px) EXCEPT the two inside feature5050, which are both 717px.
 * Cause: `.bm-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 `.bm-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. */
.ij .feature5050__body .bm-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) {
  .ij .feature5050__media--fit img { width: min(100%, 520px); max-height: 650px; }
}

/* ==========================================================================
   Client feedback, 2026-09-07. A reference store was named for three of these,
   so the target numbers below were MEASURED off that store at 390px rather than
   eyeballed from the screenshots:
     - product card image ratio 0.8 (4:5), ours was 0.75 (3:4)
     - quick add 48x48, sitting INSIDE the image
   The fourth item, a rectangular buy button, was SETTLED THE OTHER WAY on 2026-09-07
   and is not in this file. See the pill-button block at the top.
   ========================================================================== */

/* [1] Product card photos slightly smaller, as on the reference store.
 * Our card media was 3/4 = 0.75, taller than the reference's 4/5 = 0.8. A wider ratio
 * is a SHORTER card at the same column width, which is what reads as "smaller".
 * Both card systems are moved together, because the site runs two: `.pcard` on the
 * homepage rails, and Broadcast's `.product-item` on the PDP related grid and the
 * collection page. Leaving one behind would make the same product look like two
 * different products depending on the page it appears on. */
.ij.pcard__media,
.ij .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%; }

/* [2] Centre the quick add button in "You may also like".
 * The vendor pins its quick add holder to `bottom/left/right: 5px`, so the holder spans
 * the card but the button sits hard against the left edge, half over the photo's corner.
 * The card itself is `product-item--centered`, so a left-hugging control was the only
 * thing on the card not centred. Centre the BUTTON inside the holder rather than moving
 * the holder: the holder's full width is what gives the button its hover/focus target
 * area, and the vendor's own show/hide logic keys off the holder. */
.quick-add__holder {
  display: flex;
  justify-content: center;
}

/* [2c] REFERENCE POSITION ON THE GRID (client 09-07 03:47: the cart button placed as on
 * the reference store, with a screenshot circling the icon at the TOP-LEFT of the card).
 * The vendor pins the holder to the BOTTOM of the image; the reference sits at the top-left.
 * Moved there, and left-aligned rather than centred.
 *
 * THIS IS DELIBERATELY NOT GLOBAL. The same client asked, seven minutes earlier, for this
 * button to be CENTRED in "You may also like" (03:40). Two remarks, two surfaces, and
 * they pull opposite ways: centre-bottom in
 * the recommendation row, top-left everywhere else. So the move is scoped to the grid and
 * the recommendation row is pinned back below. Do not "simplify" these into one rule.
 *
 * `--btn-offset` is the vendor's own variable, declared on this element (5px, 10px at
 * >=750px), so reusing it keeps our inset identical to the one it already uses. */
.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;
}

/* [2b] THE ABOVE ALONE DID NOT WORK, found on re-measure 2026-09-07 (evening).
 * The button still sat 22px right of centre: holder 174px, button 131px, and the button's
 * USED margin-left measured 43.71px, which is exactly the 43px of free space. That is the
 * signature of an auto margin, and an auto margin absorbs all free space BEFORE
 * justify-content is ever applied, so `center` on the parent could never win.
 *
 * HONEST LIMIT: the declaration could not be located. A full CSSOM walk over every
 * same-origin sheet returned ZERO margin rules matching this button, and it carries no
 * inline style. Four app sheets are CORS-blocked from reading (Judge.me widget_v3_*,
 * webrex-faq). So this neutralises the USED value rather than overriding a rule we can
 * point at. Probed in the page first: setting both margins to 0 moved the offset from
 * 22px to 0px.
 *
 * Why the 09-07 commit claimed "measured 0px offset": the holder is hidden until hover.
 * Measured while hidden, holder and button share a collapsed box, so both centres land on
 * the same coordinate and the difference reads 0. A false pass. Measure this one hovered,
 * or measure against the CARD, never the holder. */
.quick-add__holder .quick-add__button {
  margin-left: 0;
  margin-right: 0;
}

/* ============================================================================
 * [3] CATEGORY-FIRST MOBILE DRAWER, client 09-07 item 1:
 * top-level categories shown apart, side by side.
 *
 * WHAT WAS ACTUALLY WRONG, measured on the draft at 390 before writing any code:
 * our drawer rendered the two main categories as two rows of a vertical accordion,
 * each with a chevron you drill into. So the two were never on screen "apart" at the
 * same time: you could only ever be inside one. The reference drawer puts them
 * SIDE BY SIDE as a tab row pinned at the top (active underlined) and swaps the list
 * beneath. That side-by-side row is the thing the client is pointing at.
 *
 * WHY A PILL AND NOT AN UNDERLINE: the same client message praised our homepage
 * collection toggle, which is the .favtoggle pill. The reference homepage uses the
 * identical two-tab pattern (verified 2026-09-12: tabbed carousel, aria-selected on
 * the first tab). So the pill IS the reference structure in the place it was
 * approved, and it keeps the settled pill system intact. Structure copied, control
 * kept.
 *
 * Markup reuses [data-toggle-section] / .favtoggle__btn / .favgrid, already
 * driven by bm-site.js, so there is no new JS and arrow-key tab nav comes free.
 * ========================================================================= */
.bm-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(--bm-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: bm-custom.css ships `.ij .favtoggle` (0,2,0), which beats a
 * bare `.bm-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. */
.ij .favtoggle.bm-gendernav__tabs {
  display: flex;
  width: 100%;
  box-sizing: border-box;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.bm-gendernav__tabs::-webkit-scrollbar { display: none; }
.bm-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. */
.bm-gendernav__list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.bm-gendernav__list li { margin: 0; }
.bm-gendernav__list a {
  display: block;
  padding: 14px 0;
  text-decoration: none;
  color: var(--bm-text);
  border-bottom: 1px solid var(--bm-line);
}
.bm-gendernav__list a:hover,
.bm-gendernav__list a:focus-visible { text-decoration: underline; }
.bm-gendernav__list a[aria-current="page"] { font-weight: 600; }

/* A "view all" row closes each panel, the way the reference ends a category
 * list. */
.bm-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. */
.bm-gendernav__list--flat {
  margin-top: 4px;
  border-top: 1px solid var(--bm-line);
}
/* Measured: the class WAS applied and --highlight DID resolve to #d02e2e, but
 * the colour still computed black, because `.bm-gendernav__list a` (0,1,1) beats
 * `.bm-gendernav__highlight` (0,1,0). Own the element, not just the modifier. */
.bm-gendernav__list a.bm-gendernav__highlight { color: var(--highlight, #d02e2e); }

/* Desktop keeps the existing mega-menu untouched: it is ALREADY the reference
 * model (categories at top level, logo centred). This drawer only exists below the
 * vendor's mobile-menu breakpoint anyway, but pin it so a wide drawer can never
 * inherit the mobile treatment. */
@media (min-width: 1024px) {
  .bm-gendernav__list a { padding: 12px 0; }
}

/* Transparent header over the homepage hero: Broadcast positions `.header-sections`
 * absolute at top 0 without a positioned ancestor, so it anchors to the page itself.
 * Anything placed above the theme's container (a site-wide notice bar, a cookie bar)
 * is then covered by the header. Anchor it to the container instead. With nothing
 * above the container, which is the normal case, nothing moves. */
body > .container { position: relative; }

/* Quick add sits top-RIGHT on the grid. Top-left collided with the sale badge, which
 * Broadcast pins top-left (badge_alignment), so a discounted card showed the button
 * sitting on top of its own "% OFF" label. The recommendation row keeps its centred,
 * bottom placement from the rule above. */
.quick-add__holder { justify-content: flex-end; }
.tabs__recommendation .quick-add__holder { justify-content: center; }
