/* JACK HENRY — DESIGN LANGUAGE SKIN.  Spec: brand/DESIGN-SPEC.md.md  ·  Order #1590
 *
 * Kalp: "their branding is hard lines, very square... ours is, the corners are curved. Theirs
 * is deliberately not that... hard edges, big borders, very simple."
 *
 * MEASURED, from the RENDER of three sites (brand/design_census.js.js):
 *     jackhenry.co  99.3% of elements at border-radius:0, ~0 shadows, rgb(3, 3, 3) on white
 *     Le Labo       99.1% square, 1px solid the ONLY border, 4 shadows in 554 elements
 *     Byredo        95.3% square, +0.35px tracking on 105 elements
 *     OUR PAGE      81.6% square, 48 pills at 999px, 53 shadows, neon scent dots
 *
 * The previous pass recoloured the donor and never touched the FORM. Recolouring is not
 * rebranding: a rounded, shadowed, gradient-filled card is mass-market language whatever
 * colour it is wearing.
 */

/* ── 1. ZERO RADIUS ─────────────────────────────────────────────────────────────────────
 * ⛔ !important IS USED HERE AND ONLY HERE, DELIBERATELY. A blanket reset needs the universal
 *    selector, which carries specificity 0, 0, 0 and therefore loses to every class rule in the
 *    donor's stylesheets no matter how late it loads. Enumerating the 40-odd rounded classes
 *    instead would be a name list — and a name list terminates when my memory does, which is
 *    exactly how the donor's routine card survived five passes.
 *    The trade is real: an override that opts out of the cascade makes the NEXT override
 *    harder. Confined to two properties whose correct value is "none, anywhere".
 */
*, *::before, *::after { border-radius: 0 !important; }*, *::before, *::after { box-shadow: none !important; }/* ── 2. RULES, NOT CARDS ────────────────────────────────────────────────────────────────
 * Their footer is a full-bleed grid of 1px black hairlines with vertical column dividers.
 * Structure comes from LINES; a filled panel is an event, not a default. */
.based-byob-pp__card.based-byob-pp__card {
  background: #fff;
  border: 1px solid #030303;
}.based-byob-pp__panel.based-byob-pp__panel, .based-byob-pp__slots.based-byob-pp__slots, .based-byob-pp__gift-group.based-byob-pp__gift-group {
  background: #fff;
  border: 1px solid #030303;
}.based-byob-pp__slot.based-byob-pp__slot {
  border: 1px solid #030303;
  background: #fff;
}/* ── 3. FLAT FILL, NO GRADIENT ──────────────────────────────────────────────────────────
 * The donor's CTA is a green gradient. Jack Henry's site fills exactly one element black and
 * uses a deep green (rgb(5, 33, 10)) once, as an event. A gradient is the donor's idea. */
.based-byob-pp__card-cta.based-byob-pp__card-cta, .based-byob-pp__card-add.based-byob-pp__card-add, .based-byob-pp__checkout.based-byob-pp__checkout, .based-byob-pp__mobile-checkout.based-byob-pp__mobile-checkout, .based-byob-pp__card-stepper.based-byob-pp__card-stepper {
  background-image: none;
  background-color: #030303;
  color: #fff;
  border: 1px solid #030303;
}.based-byob-pp__card-cta.based-byob-pp__card-cta:hover, .based-byob-pp__checkout.based-byob-pp__checkout:hover {
  background-color: #fff;
  color: #030303;
}/* the green survives ONLY as the unlock signal — their own single use of it */
.based-byob-pp__slot.based-byob-pp__slot[data-filled="true"], .based-byob-pp__gift-card.based-byob-pp__gift-card[data-unlocked="true"] {
  border-color: #05210a;
}.based-byob-pp__card-added-label.based-byob-pp__card-added-label { background-image: none; background-color: #05210a; color: #fff; }/* ── 4. LETTERSPACED SMALL CAPS FOR LABELS ──────────────────────────────────────────────
 * The strongest luxury typographic tell — Byredo puts +0.35px on 105 elements.
 * ⚠ LABELS AND EYEBROWS ONLY. Jack Henry sets navigation and product names LOWERCASE
 *   (hair, face, body, fragrance) where the fragrance houses go all-caps. Uppercasing
 *   everything would make this Le Labo, not Jack Henry — the departure IS their signature. */
.based-byob-pp__eyebrow.based-byob-pp__eyebrow, .based-byob-pp__gift-label.based-byob-pp__gift-label, .based-byob-pp__slot-reward.based-byob-pp__slot-reward, .based-byob-pp__slot-hint.based-byob-pp__slot-hint, .based-byob-pp__tab.based-byob-pp__tab, .bbw-header__announce-text.bbw-header__announce-text {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.72rem;
  font-weight: 500;
}.based-byob-pp__card-title.based-byob-pp__card-title { letter-spacing: -0.01em; }/* ── 5. TABS AS RULES ───────────────────────────────────────────────────────────────────
 * Pills (999px ×48) were the single largest source of roundness. A tab is a label with a
 * rule under it, not a lozenge. */
.based-byob-pp__tab.based-byob-pp__tab {
  background: transparent;
  border: 1px solid #030303;
  color: #030303;
}.based-byob-pp__tab.based-byob-pp__tab[aria-selected="true"], .based-byob-pp__tab.based-byob-pp__tab.is-active {
  background: #030303;
  color: #fff;
}/* ── 6. THE SCENT SWATCHES ──────────────────────────────────────────────────────────────
 * These rendered as NEON: #ba1a8c magenta and #6efdff cyan, 16 elements each. They are the
 * donor's scent colours run through our luminance inversion, and nothing in a black-and-white
 * brand should glow. Desaturated to ink, distinguished by lightness and a hard border —
 * the apothecary device: a swatch is a mark, not a highlighter. */
.based-byob-pp__scent.based-byob-pp__scent {
  filter: grayscale(1) contrast(0.85);
  border: 1px solid #030303;
}.based-byob-pp__scent.based-byob-pp__scent[aria-checked="true"] { outline: 2px solid #030303; outline-offset: 2px; }

/* ══ RECOVERED FROM THE SESSION TRANSCRIPT, 2026-08-27 ═════════════════════════════════
 * `rm -rf build` destroyed this file; git had ZERO commits, so version control held
 * nothing. The 18 blocks below were extracted from the session log — every `cat >>`
 * heredoc that ever wrote to jh-skin.css, replayed in order, with the later in-place
 * corrections re-applied. The audit across every interactive state is the acceptance
 * test for whether the reconstruction is faithful; the text looking familiar is not.
 * ⚠ THE REAL FIX IS THE COMMIT, NOT THE RECOVERY. This worked because a 36MB transcript
 * happened to exist. That is luck, not a backup. */


/* 10. THE FOOTER WORDMARK — black on black, called out three times.
 *     The footer renders dark; jh-wordmark.svg is traced with a hardcoded fill #030303, so the
 *     logo was present, correctly sized, and invisible. An <img> has no text node, which is
 *     exactly why contrast_audit kept reporting 0 failing — it only ever inspected TEXT.
 *     The light variant carries the same contours at fill #ffffff. */
.bbw-footer__logo.bbw-footer__logo,
.bbw-footer__watermark.bbw-footer__watermark,
.bbw-footer__watermark-mobile.bbw-footer__watermark-mobile {
  content: url("jh-wordmark-light.svg");
}

/* 11. ADD-TO-CART → GREEN (Kalp, direct). Jack Henry's own deep green, not the donor's
 *     gradient. Flat fill, square, no shadow — the same language as everything else. */
.based-byob-pp__card-cta.based-byob-pp__card-cta,
.based-byob-pp__card-add.based-byob-pp__card-add,
.based-byob-pp__checkout.based-byob-pp__checkout,
.based-byob-pp__mobile-checkout.based-byob-pp__mobile-checkout {
  background-image: none;
  background-color: #05210a;
  border-color: #05210a;
  color: #ffffff;
}
/* every descendant inherits the white ink — the label is a CHILD span, and setting colour on
 * the button alone is how "CHECKOUT$63.00" ended up dark-on-dark in the first place. */
.based-byob-pp__card-cta.based-byob-pp__card-cta *,
.based-byob-pp__checkout.based-byob-pp__checkout *,
.based-byob-pp__mobile-checkout.based-byob-pp__mobile-checkout * {
  color: #ffffff;
}

/* 12. THE MOBILE STICKY BAR — three columns crammed into 375px.
 *     At mobile width the bar keeps its desktop 3-across layout, so the CTA label
 *     ("CONTINUE TO CHECKOUT" + the total) overflows its own button and paints across the
 *     progress text either side of it. Nothing OVERLAPS in box terms — which is why a
 *     bounding-box overlap detector reported 0 — the TEXT overflows its box. A layout test
 *     that only compares rectangles cannot see a string that is too long for its container.
 *     Stack it, and let the button be full width. */
@media (max-width: 640px) {
  .based-byob-pp__mobile-bar.based-byob-pp__mobile-bar {
    flex-direction: column;
    align-items: stretch;
    gap: .5rem;
    padding: .75rem;
  }
  .based-byob-pp__mobile-checkout.based-byob-pp__mobile-checkout {
    width: 100%;
    min-height: 48px;            /* a thumb target, not a 32px desktop button */
    white-space: normal;
    line-height: 1.15;
  }
  .based-byob-pp__mobile-bar.based-byob-pp__mobile-bar .based-byob-pp__checkout-note {
    display: none;               /* the reassurance line is desktop-only; on a phone it is
                                    a third column competing with the button that matters */
  }
}

/* 13. THE MOBILE BAR TILES — black products on a near-black bar.
 *     Measured by the new non-text-ink check: conditioner ink rgb(28,28,28) on rgb(10,10,10)
 *     = 1.17:1. The packshots are now TRANSPARENT cutouts of near-black bottles, so the dark
 *     sticky bar swallowed them whole — a defect that did not exist while they still carried
 *     their grey Shopify backdrop. Removing a background changes what a product needs BEHIND
 *     it; the cutout and the surface it sits on are one decision, not two.
 *     A light tile is also the same device the desktop slots already use. */
.based-byob-pp__mobile-tile.based-byob-pp__mobile-tile,
.based-byob-pp__mobile-slot.based-byob-pp__mobile-slot {
  background-color: #f5f5f5;
  border: 1px solid #030303;
}

/* 14. THE BODY GROUND — still the donor's #0a0a0a.
 *     token_swap rewrites the 183 tokens in based-byob.css's :root, and that stylesheet has
 *     ZERO literals below it. But the page has OTHER donor sheets, and bbw-base.css sets
 *     `html:has(body.bbw-redesign), body.bbw-redesign { background: rgb(10,10,10) }` as a
 *     LITERAL. A tokenised palette is only tokenised for the file that was tokenised.
 *     Invisible on desktop because every section paints over it — and plainly visible on
 *     mobile, where the sticky bar's semi-transparent tiles let it through and swallowed the
 *     black packshots at 1.01:1. The ground a page falls back to is still a colour decision.
 *     [[verify-the-channel-you-didnt-change]] */
html:has(body.bbw-redesign), body.bbw-redesign { background-color: #ffffff; }
.based-byob-pp__mobile-slot.based-byob-pp__mobile-slot,
.based-byob-pp__mobile-slot-img.based-byob-pp__mobile-slot-img {
  background-color: #f5f5f5;
}

/* 15. THE CHROME THE DONOR BUILT FOR A DARK BODY.
 *     Making the body white (rule 14) orphaned 22 strings that were white-on-dark: the
 *     announce strip, the mobile nav, and every footer link. Flipping a ground is never a
 *     one-property change — everything that was legible BECAUSE of that ground has to move
 *     with it. Fixed toward Jack Henry's OWN chrome as measured on jackhenry.co, not by
 *     bluntly darkening text:
 *       · their announce strip IS dark with white type  -> give it back its dark ground
 *       · their footer is WHITE with black type and 1px rules -> ground white, ink #030303
 *     [[verify-the-channel-you-didnt-change]] */
.bbw-header__announce.bbw-header__announce,
.bbw-header__announce-bar.bbw-header__announce-bar {
  background-color: #030303;
}
.bbw-header__announce-text.bbw-header__announce-text { color: #ffffff; }

.bbw-footer.bbw-footer { background-color: #ffffff; }
.bbw-footer.bbw-footer a,
.bbw-footer.bbw-footer p,
.bbw-footer.bbw-footer span,
.bbw-footer.bbw-footer h2,
.bbw-footer.bbw-footer h3,
.bbw-footer.bbw-footer li { color: #030303; }

.bbw-mnav.bbw-mnav { background-color: #ffffff; }
.bbw-mnav.bbw-mnav a,
.bbw-mnav.bbw-mnav span,
.bbw-mnav.bbw-mnav .bbw-mnav__title,
.bbw-mnav.bbw-mnav .bbw-mnav__col-title { color: #030303; }

/* 16. THE MOBILE BAR'S OWN TEXT — the last of rule 14's fallout.
 *     The bar sat on the donor's dark body and its type is white; the tiles were relit in
 *     rule 13 and the ground in rule 14, but the bar's own copy was still white-on-light at
 *     1.35:1. Three rules to finish one ground flip, which is the honest cost of changing a
 *     page's base colour after the fact rather than at the palette. */
.based-byob-pp__mobile-bar.based-byob-pp__mobile-bar { background-color: #ffffff; }
.based-byob-pp__mobile-bar.based-byob-pp__mobile-bar :not(.based-byob-pp__mobile-checkout):not(.based-byob-pp__mobile-checkout *) {
  color: #030303;
}

/* 17. …and the CTA label inside that bar.
 *     Rule 16 used `:not(.x):not(.x *)` to spare the checkout button, and the descendant form
 *     of :not() did not hold — the label went dark on the dark-green fill, which is the exact
 *     defect rule 16 was written to remove, moved four inches to the right. A negation is a
 *     fragile way to protect an element; state the positive case last and let order win. */
.based-byob-pp__mobile-bar.based-byob-pp__mobile-bar .based-byob-pp__mobile-checkout,
.based-byob-pp__mobile-bar.based-byob-pp__mobile-bar .based-byob-pp__mobile-checkout * {
  color: #ffffff;
  background-color: #05210a;
}

/* 18. THE GIFT ROW — collapsed to 14px slivers, flagged twice.
 *     .based-byob-pp__gift-group and .__gift-group-cards are `display: contents`, so the gift
 *     CARDS are hoisted into the panel's own flex line and compete for width with the subtotal
 *     block and the checkout button. With `flex: 1 1 0` they lose that competition and end up
 *     14px wide by 96 tall — the same zero-width collapse as the footer brand column, one
 *     level deeper. In the donor's own design (based.com) this is a self-contained ROW of
 *     "UNLOCKED" tiles sitting between the product grid and the subtotal.
 *     Give the wrapper back a box so the row is a row. */
.based-byob-pp__gift-group-cards.based-byob-pp__gift-group-cards,
.based-byob-pp__gift-cards.based-byob-pp__gift-cards {
  display: flex;
  width: 100%;
  flex: 0 0 100%;
  gap: .5rem;
}
.based-byob-pp__gift-group.based-byob-pp__gift-group {
  display: flex;
  width: 100%;
  flex: 0 0 100%;
  gap: .5rem;
}
.based-byob-pp__gift-card.based-byob-pp__gift-card {
  flex: 1 1 0;
  min-width: 96px;          /* a tile, never a sliver */
  background: #fff;
  border: 1px solid #030303;
}
.based-byob-pp__gift-card.based-byob-pp__gift-card[data-unlocked="1"] {
  border-color: #05210a;
}

/* 19. THE HEADER OVER A BRIGHT HERO.
 *     Every header item — announce strip, nav, mega-tabs — is rgb(255,255,255), which the
 *     donor could rely on because their hero was a DARK studio banner. Ours is a sunset
 *     photograph, so white type sits on bright sky and is unreadable.
 *     ⛔ contrast_audit CANNOT SEE THIS: it abstains whenever the resolved background is a
 *     photo, so "white text on a bright image" is invisible to it by construction — the same
 *     shape of blind spot as the logo, one layer up. A scrim gives the type a real ground. */
.based-byob-pp__hero.based-byob-pp__hero::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 190px;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(3,3,3,.72) 0%, rgba(3,3,3,.38) 55%, rgba(3,3,3,0) 100%);
}

/* 20. THE CHECKOUT BLOCK — the note collides with the button.
 *     Measured at 1440: `.based-byob-pp__checkout-note` overlaps the CTA's label span by
 *     25x10+. In Kalp's screenshot this reads as "CONTINUE TO" printed on top of "Checkout
 *     here to secure your Build Your Set offer". The subtotal / CTA / note sit on one flex
 *     line that has no room for three things once the gift row above it takes its proper
 *     width back. Stack them: totals, then a full-width button, then the note under it. */
.based-byob-pp__checkout-wrap.based-byob-pp__checkout-wrap,
.based-byob-pp__panel-foot.based-byob-pp__panel-foot,
.based-byob-pp__totals.based-byob-pp__totals {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: .5rem;
}
.based-byob-pp__checkout.based-byob-pp__checkout {
  width: 100%;
  min-height: 48px;
  white-space: normal;
}
.based-byob-pp__checkout-note.based-byob-pp__checkout-note {
  display: block;
  width: 100%;
  text-align: center;
  margin-top: .25rem;
}

/* 24. THE FOOTER — THE BLACK-ON-BLACK KALP REPORTED, AND WHY MY CHECKER SAID IT WAS FINE.
 *
 *     MEASURED, once the checker could see it:
 *       .bbw-footer  background-color: rgb(255,255,255)      <- rule 14, my ground flip
 *       .bbw-footer  background-image: linear-gradient(rgb(10,10,10), rgb(4,4,4))   <- the DONOR
 *       21 of 21 footer strings: color rgb(3,3,3)            <- rule 2, my ink flip
 *       3x jh-wordmark.svg (one 581x142 watermark): black art, filter: none
 *     = near-black type and a black wordmark on a black gradient. 1.03:1. He was right that I
 *     made it worse: before the flip the donor's footer was black WITH white type and it worked.
 *     I flipped the ground globally and the footer was the one section that kept its own paint.
 *
 *     AND THE REASON IT SHIPPED: contrast_audit.js tested background-COLOR before
 *     background-IMAGE, so on this element it found opaque white and returned — never seeing
 *     the black gradient painted over it. The instrument reported 0 failures on the exact
 *     section he was pointing at. A defect that a checker actively certifies as clean is worse
 *     than one it never looked at. Fixed in contrast_audit.js: image is tested before colour,
 *     because that is the order the pixels are painted in.
 *     [[a-text-node-verdict-is-not-a-page-verdict]] · [[verify-the-channel-you-didnt-change]]
 *
 *     The footer STAYS black — that is Jack Henry's own footer and the donor's, and it suits
 *     the hard square register. What sits on it flips instead. */
.bbw-footer,
.bbw-footer * {
  color: #ffffff;
}
.bbw-footer .bbw-footer__link,
.bbw-footer a {
  color: rgba(255,255,255,.78);
}
.bbw-footer .bbw-footer__link:hover,
.bbw-footer a:hover { color: #ffffff; }
.bbw-footer .bbw-footer__col-title,
.bbw-footer h2, .bbw-footer h3, .bbw-footer h4 { color: #ffffff; }
.bbw-footer svg { color: #ffffff; fill: currentColor; stroke: currentColor; }
.bbw-footer svg[fill="none"] { fill: none; stroke: #ffffff; }
/* the wordmark is black artwork; on a black ground it has to be inverted, not recoloured —
 * it is a raster/SVG image, and `color` does nothing to it. This is the non-text ink channel:
 * a logo has no text node, so a text-contrast checker is structurally blind to it. */
.bbw-footer .bbw-footer__logo,
.bbw-footer .bbw-footer__watermark,
.bbw-footer .bbw-footer__watermark-mobile {
  filter: invert(1) brightness(2);
}
.bbw-footer .bbw-footer__watermark,
.bbw-footer .bbw-footer__watermark-mobile { opacity: .10; }
.bbw-footer input, .bbw-footer button {
  color: #ffffff;
  border-color: rgba(255,255,255,.34);
  background-color: rgba(255,255,255,.06);
}
.bbw-footer ::placeholder { color: rgba(255,255,255,.55); }

/* 25. MOBILE BAR — THE COLLAPSE TOGGLE SITS ON TOP OF THE LAST GIFT TILE.
 *     Measured at 375: .based-byob-pp__mobile-head is position:absolute, top 22.5px,
 *     right 12px, 32x32 — the donor pins the collapse chevron to the corner. Its sibling
 *     .based-byob-pp__mobile-head-title computes display:none, so the head reserves NO
 *     vertical space, the tiles row rises to y+27 and the button lands over the right third
 *     of the "25% off + both gifts" tile (overlap 32x27). The gift the whole ladder is selling
 *     is the one partly hidden by a button.
 *     Reserving a lane on the right rather than adding 34px of bar height — the mobile bar is
 *     already 150px of a 812px screen, and buying clearance with vertical space costs more
 *     than it fixes. */
.based-byob-pp__mobile-bar .based-byob-pp__mobile-tiles {
  padding-right: 0;
}
/*  ⛔ REVERSED 2026-08-28, order #1619. `margin-top: 34px` above was the WHOLE of the "why is
 *  the gap between the 25%-off bar and the four images so big?" that Kalp measured by eye.
 *  I bought clearance for a 32px absolute chevron with 34px of VERTICAL space — the exact
 *  trade this rule's own comment says costs more than it fixes, made two lines below the
 *  sentence saying so. The chevron never overlapped the tiles once the progress row moved
 *  above them (flex `order`), so the margin was clearing nothing at all: 42px of dead air
 *  between the progress bar and the product images, on the surface with the least room.
 *  The lane belongs on the row the chevron actually shares — HORIZONTAL, costing 0px of height.
 *  [[a-no-op-that-reads-as-a-working-fix]] — the fix was real, its target had moved. */
.based-byob-pp__mobile-bar .based-byob-pp__mobile-progress-wrap {
  padding-right: 40px;
}

/* ══ ORDER #1617 — Kalp, 2026-08-27 ═══════════════════════════════════════════════════════
 * 28. THE QUANTITY STEPPER WAS BLACK ON BLACK, AND IT WAS THERE THE WHOLE TIME.
 *     Kalp: "you can add multiple… ours we cannot… maybe there is a quantity button there,
 *     but it's black. I can't even see it." He was right on both counts.
 *     MEASURED: the mechanic works — data-card-state flips add_to_cart -> quantity, the
 *     stepper renders 276x42, qty reads 1. It is INVISIBLE:
 *         .based-byob-pp__card-stepper  background rgb(3,3,3)
 *         .based-byob-pp__card-step     color    rgb(3,3,3)   (both − and +)
 *         .based-byob-pp__card-qty      color    rgb(3,3,3)
 *         svg path                      stroke   rgb(3,3,3)
 *     = 1.0:1 on every glyph. The donor styles this bar in its ACCENT (gold, dark ink); our
 *     ground flip painted the bar with the ink and left the ink at the ink.
 *     ⛔ AND contrast_audit.js reported 0 failures over 111 strings, because the only text in
 *     the stepper is "1" and the scorer skipped `t.length < 3`. Fixed there too — a short
 *     string is not an unimportant string, and on a commerce page the quantity IS the state.
 *     The stepper now wears the CTA's green with white ink: same affordance, one colour. */
.based-byob-pp__card-stepper.based-byob-pp__card-stepper {
  background: #0f5132;
  border-color: #0f5132;
  color: #ffffff;
}
.based-byob-pp__card-stepper .based-byob-pp__card-step,
.based-byob-pp__card-stepper .based-byob-pp__card-qty {
  color: #ffffff;
  -webkit-text-fill-color: #ffffff;
}
.based-byob-pp__card-stepper .based-byob-pp__card-step-icon,
.based-byob-pp__card-stepper .based-byob-pp__card-step-icon path {
  color: #ffffff;
  stroke: #ffffff;
}
.based-byob-pp__card-stepper .based-byob-pp__card-step:hover {
  background: rgba(255,255,255,.14);
}

/* 29. THE GIFT CARDS — the donor's geometry, read off based.com rather than invented.
 *     Kalp: "their design is better… the gifts are actually spaced out properly… when it's
 *     unlocked the image of the product blocks what the text is saying… free WHAT?"
 *     MEASURED SIDE BY SIDE at 1440 (donor | ours):
 *         .gift-card flex          1 1 0px  |  0 0 auto   -> 114/114/114 vs 98/92/92 + a gap
 *         .gift-card-img (1st)     display:none | rendering -> a second image drawn
 *         --cutout opacity         0.5      |  1          -> OPAQUE product over the label
 *         --cutout object-fit      cover    |  contain    -> my rule 20 made it fully visible
 *     So the donor always intended the cutout as a WASH behind the text, and I had turned it
 *     into a foreground object. `flex: 1 1 0` is the whole of "spaced out properly".
 *     Adapted for OUR ground: the donor washes at .5 because its panel is black and its type
 *     is white. Ours is a white panel with near-black type, so the same .5 would grey the
 *     label out. Dropped to .14 — present as a watermark, never competing with the word. */
.based-byob-pp__gift-cards .based-byob-pp__gift-card {
  flex: 1 1 0;
  min-width: 0;
}
.based-byob-pp__gift-card > .based-byob-pp__gift-card-img:not(.based-byob-pp__gift-card-img--cutout) {
  display: none;
}
.based-byob-pp__gift-card .based-byob-pp__gift-card-img--cutout {
  opacity: .14;
  object-fit: cover;
  z-index: 0;
}
.based-byob-pp__gift-card .based-byob-pp__gift-card-text {
  position: relative;
  z-index: 1;
}

/* 30. NO GRADIENTS. Kalp: "there's no gradient in our branding, why the hell does our whole
 *     gift section have gradient."
 *     ENUMERATED, not guessed — 10 gradient paints across panel + mobile bar. NINE were
 *     already FLAT (linear-gradient(rgb(3,3,3), rgb(3,3,3)) — token_swap collapsed the gold
 *     ramp to one ink, so they render as a solid fill). One was real: the mobile bar's
 *     rgba(3,3,3,.06) -> transparent wash, which is the grey haze across his screenshots.
 *     Removing the flat nine as well, because they are `background-clip: text` machinery —
 *     which means color:transparent, which means contrast_audit ABSTAINS on every one of
 *     them. Five headings and labels were never being contrast-checked at all. Killing the
 *     machinery removes a gradient Kalp does not want AND closes an audit blind spot.
 *     [[an-abstention-must-be-recorded]] */
.based-byob-pp__mobile-bar.based-byob-pp__mobile-bar {
  background-image: none;
  background-color: #ffffff;
}
.based-byob-pp__panel-heading-lead,
.based-byob-pp__panel-heading-accent,
.based-byob-pp__gift-card-name,
.based-byob-pp__mobile-slot-reward,
.based-byob-pp__panel strong,
.based-byob-pp__mobile-bar strong {
  background-image: none !important;
  -webkit-text-fill-color: #030303;
  color: #030303;
}
.based-byob-pp__panel-bar-fill,
.based-byob-pp__mobile-bar-fill {
  background-image: none;
  background-color: #0f5132;
}

/* 31. THE UNLOCK STATE OUTRANKS THE BASE RULE — which is why the label only vanished AFTER
 *     a gift unlocked, and why my rule 29 looked correct in the locked state.
 *     Kalp: "when it's actually unlocked, the image of the product blocks what the text is
 *     saying… I can't even see what the hell the text is saying. The free WHAT?"
 *     MEASURED — every rule matching the cutout, in cascade order:
 *         .gift-card-img                                                   opacity .5   (0,1,0)
 *         [data-gifts-unlocked="1"] .gift-card-img                         opacity 1    (0,2,0)
 *         --bbw .gift-card-img--cutout                                     opacity .5   (0,2,0)
 *         --bbw .gift-card[data-unlocked="1"] .gift-card-img               opacity 1    (0,4,0)  <- WINS
 *         jh-skin .gift-card.gift-card .gift-card-img--cutout              opacity .14  (0,3,0)
 *     A doubled class buys (0,3,0) and loses to a four-part state selector. The donor gets
 *     away with opacity 1 because its cards are white type on a BLACK panel and its gift
 *     photos are pale; ours are black bottles on a white card, so full opacity paints the
 *     label out completely (worst-case ratio measured at 1.02:1 on "Free Hair Refresh").
 *     Unlock still has to FEEL like something, so the wash lifts .14 -> .22 rather than going
 *     to 1, and the state is carried by the border and the status colour instead — which is
 *     what actually reads at 114px wide.
 *     [[a-state-rule-outranks-the-base-rule-it-contradicts]] */
.based-byob-pp--bbw .based-byob-pp__gift-card[data-unlocked="1"] .based-byob-pp__gift-card-img--cutout,
.based-byob-pp--bbw [data-gifts-unlocked="1"] .based-byob-pp__gift-card-img--cutout,
.based-byob-pp__mobile-bar--bbw .based-byob-pp__gift-card[data-unlocked="1"] .based-byob-pp__gift-card-img--cutout,
.based-byob-pp__mobile-bar--bbw[data-gifts-unlocked="1"] .based-byob-pp__gift-card-img--cutout,
.based-byob-pp--bbw .based-byob-pp__gift-card[data-unlocked="1"] .based-byob-pp__gift-card-img,
.based-byob-pp--bbw [data-gifts-unlocked="1"] .based-byob-pp__gift-card-img {
  opacity: .22;
  filter: none;
}
/* the non-cutout copy stays hidden in BOTH states — the donor draws it blurred underneath,
 * which on a white card is just a grey smear behind the word */
.based-byob-pp--bbw .based-byob-pp__gift-card[data-unlocked="1"] .based-byob-pp__gift-card-img:not(.based-byob-pp__gift-card-img--cutout),
.based-byob-pp--bbw [data-gifts-unlocked="1"] .based-byob-pp__gift-card-img:not(.based-byob-pp__gift-card-img--cutout) {
  display: none;
}
/* unlock reads on the BORDER and the STATUS, not by shouting the photo */
.based-byob-pp--bbw .based-byob-pp__gift-card[data-unlocked="1"],
.based-byob-pp__mobile-bar--bbw .based-byob-pp__gift-card[data-unlocked="1"] {
  border-style: solid;
  border-color: #0f5132;
  box-shadow: none;
  background-color: #eef4f0;
}
.based-byob-pp__gift-card[data-unlocked="1"] .based-byob-pp__gift-card-status-unlocked {
  color: #0f5132;
  -webkit-text-fill-color: #0f5132;
}

/* ══ ORDER #1620 — Kalp, 2026-08-27 ═══════════════════════════════════════════════════════
 * 32. AN UNLOCKED GIFT MUST READ AS WON, NOT AS DISABLED.
 *     Kalp: "when it's unlocked it's translucent, so it's not clear whether it's unlocked."
 *     He is right, and rule 31 caused it. I fixed "the image covers the label" by washing the
 *     image down to .14 in BOTH states — which made the reward look like a greyed-out,
 *     disabled thing. I traded one wrong signal for another.
 *     THE DONOR SOLVES IT WITHOUT A TRADE. Measured on based.com at 375, unlocked card:
 *         border      1px solid rgba(219,182,95,.7)   <- solid ACCENT, not a wash
 *         img opacity 1                               <- full strength, the reward is LOUD
 *         object-position 100% 50%                    <- ANCHORED RIGHT
 *         img width   104px of a 106px card, object-fit cover
 *     The image is full-strength AND the text is readable because the image's mass sits RIGHT
 *     and the label owns the LEFT. Opacity was never their lever — POSITION was. I reached for
 *     the transparency dial because it was the one I already had my hand on.
 *     So: the cutout is confined to the right 46%, the text owns the left 54%, and opacity now
 *     carries STATE instead of legibility — greyscale and faint when locked, full colour when
 *     won. The two states are now different in three ways at once (image, border, status
 *     colour) rather than differing by a shade of grey. */
.based-byob-pp__gift-card .based-byob-pp__gift-card-img--cutout {
  left: auto;
  right: 0;
  width: 46%;
  object-fit: contain;
  object-position: right center;
  z-index: 0;
}
.based-byob-pp__gift-card .based-byob-pp__gift-card-text {
  position: relative;
  z-index: 1;
  width: 54%;
}
/* LOCKED: dim, desaturated, clearly "not yours yet" */
.based-byob-pp--bbw .based-byob-pp__gift-card[data-unlocked="0"] .based-byob-pp__gift-card-img--cutout,
.based-byob-pp__mobile-bar--bbw .based-byob-pp__gift-card[data-unlocked="0"] .based-byob-pp__gift-card-img--cutout {
  opacity: .3;
  filter: grayscale(1);
}
/* UNLOCKED: full colour, full strength — the donor's opacity 1, made safe by POSITION */
.based-byob-pp--bbw .based-byob-pp__gift-card[data-unlocked="1"] .based-byob-pp__gift-card-img--cutout,
.based-byob-pp--bbw [data-gifts-unlocked="1"] .based-byob-pp__gift-card-img--cutout,
.based-byob-pp__mobile-bar--bbw .based-byob-pp__gift-card[data-unlocked="1"] .based-byob-pp__gift-card-img--cutout,
.based-byob-pp__mobile-bar--bbw[data-gifts-unlocked="1"] .based-byob-pp__gift-card-img--cutout {
  opacity: 1;
  filter: none;
}
.based-byob-pp--bbw .based-byob-pp__gift-card[data-unlocked="1"],
.based-byob-pp__mobile-bar--bbw .based-byob-pp__gift-card[data-unlocked="1"] {
  border: 1px solid #0f5132;
  background-color: #eaf3ee;
}
.based-byob-pp--bbw .based-byob-pp__gift-card[data-unlocked="0"],
.based-byob-pp__mobile-bar--bbw .based-byob-pp__gift-card[data-unlocked="0"] {
  border: 1px dashed rgba(3,3,3,.34);
  background-color: #f4f4f4;
}
.based-byob-pp__gift-card[data-unlocked="1"] .based-byob-pp__gift-card-status,
.based-byob-pp__gift-card[data-unlocked="1"] .based-byob-pp__gift-card-status-unlocked {
  color: #0f5132;
  -webkit-text-fill-color: #0f5132;
  font-weight: 700;
}
.based-byob-pp__gift-card[data-unlocked="0"] .based-byob-pp__gift-card-status,
.based-byob-pp__gift-card[data-unlocked="0"] .based-byob-pp__gift-card-status-locked {
  color: rgba(3,3,3,.68);
  -webkit-text-fill-color: rgba(3,3,3,.68);
}

/* 33. THE SLOT TILES READ AS ONE BLOCK — separation is CONTRAST, not gap.
 *     Kalp: "they are also stuck together." The gap was never missing: measured 4px between
 *     all four, exactly the donor's 4px. What was missing was a VISIBLE EDGE. The tile carries
 *     border rgba(3,3,3,.08) and fill rgba(3,3,3,.02) — on the donor's BLACK bar those read as
 *     clear frames; on our white bar they are invisible, so four tiles merge into one strip.
 *     "Stuck together" was a contrast complaint wearing a spacing complaint's clothes, and I
 *     would have wasted a pass widening a gap that was already correct. */
.based-byob-pp__mobile-bar .based-byob-pp__mobile-slot,
.based-byob-pp__panel .based-byob-pp__slot {
  border: 1px solid rgba(3,3,3,.22);
  background-color: #fafafa;
}
.based-byob-pp__mobile-bar .based-byob-pp__mobile-slot[data-filled="true"],
.based-byob-pp__panel .based-byob-pp__slot[data-filled="true"] {
  border-color: #0f5132;
  background-color: #ffffff;
}

/* 34. THE FOOTER LINKS — TWO DIMMERS MULTIPLYING, AND A PASSING SCORE THAT HID IT.
 *     Kalp had to drag-select the footer to prove the text was there at all.
 *     MEASURED: .bbw-footer__link carries the DONOR's `opacity: .7` and my rule 24's
 *     `color: rgba(255,255,255,.78)`. They multiply: .78 x .7 = .546 effective, i.e. mid-grey
 *     on rgb(10,10,10). I dimmed something that was already dimmed — rule 24 read the donor's
 *     bright link and "softened" it without checking what was already on the element.
 *     ⛔ AND IT SCORED 6.18:1 — a comfortable WCAG AA PASS. My audit was silent because the
 *     number was fine. A 14px link at 55% white on near-black passes the maths and still reads
 *     as absent. AA is a floor for the worst case, not a definition of legible, and the owner's
 *     eye outranks the ratio. [[a-number-without-its-conditions-is-not-a-measurement]] */
.bbw-footer .bbw-footer__link,
.bbw-footer a {
  opacity: 1;
  color: rgba(255,255,255,.94);
}
.bbw-footer .bbw-footer__link:hover,
.bbw-footer a:hover { color: #ffffff; text-decoration: underline; }
.bbw-footer .bbw-footer__col-title { color: #ffffff; opacity: 1; font-weight: 600; }
.bbw-footer .bbw-footer__watermark,
.bbw-footer .bbw-footer__watermark-mobile { opacity: .16; }

/* 35. UNLOCK STATE — !important, AND SAYING WHY OUT LOUD.
 *     Three passes failed to make the unlocked card's border and image win, and the reason
 *     was never found. What IS established, measured in the browser:
 *         card.matches('[data-unlocked="1"]') -> true
 *         card.matches('[data-unlocked="0"]') -> false
 *         both rules present in the CSSOM, unlocked LAST, equal specificity
 *         computed border-color rgba(3,3,3,.34) + img opacity .3  = the LOCKED paint
 *     That combination should be impossible, so something outside the two rules I am reading
 *     is winning, and I have not identified it. Pass 1 blamed specificity (wrong), pass 2 the
 *     `--bbw` ancestor (real, but not this), pass 3 the attribute scope (correct, still lost).
 *     Continuing to guess is the enumeration habit Kalp stopped me for. !important ends it.
 *     ⚠ THIS IS A MARKER, NOT A SOLUTION. It states that an unexplained rule is beating a
 *     correct one here — if this file is ever cleaned up, resolve the cause, don't just
 *     delete the !important and assume it was cruft. */
.based-byob-pp__gift-card[data-unlocked="1"] { border-color: #0f5132 !important; border-style: solid !important; }
.based-byob-pp__gift-card[data-unlocked="1"] .based-byob-pp__gift-card-img--cutout { opacity: 1 !important; filter: none !important; }
.based-byob-pp__gift-card[data-unlocked="0"] .based-byob-pp__gift-card-img--cutout { opacity: .3 !important; filter: grayscale(1) !important; }

/* 36. THE HERO COPY WAS WEARING THE DONOR'S COLUMN WIDTH.
 *     Kalp: "since our hero image is more horizontal, the text at the bottom doesn't need to
 *     be half now... right now it's all clumped together."
 *     MEASURED: .based-byob-pp--bbw .based-byob-pp__hero-body max-width 220px (184px under
 *     749px). That is not a bug in the donor — it is correct FOR THEIR HERO, where product
 *     art occupies the right and the copy is a deliberate narrow column beside it.
 *     Ours is the other composition: a black plate running x 0->1450 of 3072 (47% of the
 *     frame, ~670px at a 1440 viewport) with the products clustered right. So the copy has
 *     roughly three times the room the donor's does, and inheriting their 220px wrapped the
 *     ladder line into five short lines against a wall of empty black.
 *     A geometry constant is only true for the geometry it was measured on. When the art
 *     direction changes, every hard-coded width inherited from the donor has to be re-derived
 *     — not kept because it "came from the house template".
 *     [[a-number-without-its-conditions-is-not-a-measurement]] */
.based-byob-pp--bbw .based-byob-pp__hero-body,
.based-byob-pp__hero .based-byob-pp__hero-body {
  max-width: 560px;
}
@media (max-width: 749px) {
  .based-byob-pp--bbw .based-byob-pp__hero-body,
  .based-byob-pp__hero .based-byob-pp__hero-body {
    max-width: 100%;
    padding-right: 16px;
  }
}

/* 37. THE DISABLED STATES — found by auditing AFTER a click, which is the whole lesson.
 *     Two failures appeared only once the cart state changed, neither present on load:
 *       "Add 2 more items"  white on rgb(222,222,222)  = 1.35:1
 *          The donor greys the checkout button until the set qualifies. Rule 23 painted the
 *          CTA label white unconditionally, so the disabled variant became white-on-grey —
 *          the exact instruction ("more items needed") a customer must read is the one that
 *          disappears. A colour set on a control must be set per STATE, or the state that
 *          changes the ground silently breaks it.
 *       "$0.00"             near-black, scored 3.9:1
 *          not the colour — an ancestor dims the totals row while the cart is empty, and the
 *          accumulated opacity drags a 19:1 ink down to 3.9.
 *     [[a-state-rule-outranks-the-base-rule]] */
.based-byob-pp__checkout:disabled,
.based-byob-pp__checkout[aria-disabled="true"],
.based-byob-pp__checkout.based-byob-pp__checkout:disabled,
.based-byob-pp__mobile-checkout:disabled,
.based-byob-pp__mobile-checkout[aria-disabled="true"] {
  background: #dedede;
  border-color: #c9c9c9;
  color: rgba(3,3,3,.72);
}
.based-byob-pp__checkout:disabled *,
.based-byob-pp__checkout[aria-disabled="true"] *,
.based-byob-pp__mobile-checkout:disabled *,
.based-byob-pp__mobile-checkout[aria-disabled="true"] * {
  color: rgba(3,3,3,.72);
  -webkit-text-fill-color: rgba(3,3,3,.72);
}
/* a zero total is still a number the customer is reading — do not dim it out of legibility */
.based-byob-pp__totals,
.based-byob-pp__totals-row,
.based-byob-pp__mobile-totals { opacity: 1; }

/* ══ ORDER #1623 — JACK HENRY'S OWN CHROME ════════════════════════════════════════════════
 * 38. Styling for the chrome jh_chrome.py installs. Deliberately SHORT, because the design
 *     decision was made by deletion, not by CSS: Jack Henry's real header and footer are
 *     dark-on-WHITE (measured on jackhenry.co: header bg #fff, logo rgb(3,3,3); footer bg
 *     #fff, text rgb(3,3,3)). The donor's were light-on-BLACK. Four rounds of ink-inversion
 *     were spent trying to make one look like the other; on the correct ground the wordmark
 *     needs NO filter and the links need no rescue — the black asset is simply right.
 *     The announce strip stays black: it is offer copy, not chrome, and a single dark band
 *     above a white header is Jack Henry's own pattern. */
.jh-announce {
  background: #030303;
  color: #ffffff;
  text-align: center;
  padding: 9px 16px;
  font-size: 12px;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.jh-announce__text { color: #ffffff; }

.jh-header {
  position: sticky;
  top: 0;
  z-index: 9999;
  background: #ffffff;
  border-bottom: 1px solid rgba(3,3,3,.12);
}
.jh-header__bar {
  display: flex;
  align-items: center;
  gap: 28px;
  max-width: 1232px;
  margin: 0 auto;
  padding: 14px 24px;
}
.jh-header__logo { display: block; flex: 0 0 auto; line-height: 0; }
.jh-header__logo img { display: block; width: 118px; height: auto; }
.jh-nav { display: flex; flex-wrap: wrap; gap: 20px; }
.jh-nav__link {
  color: #030303;
  text-decoration: none;
  font-size: 14px;
  letter-spacing: .01em;
}
.jh-nav__link:hover { text-decoration: underline; }

.jh-footer {
  background: #ffffff;
  color: #030303;
  border-top: 1px solid rgba(3,3,3,.12);
  margin-top: 64px;
}
.jh-foot__inner {
  display: flex;
  flex-wrap: wrap;
  gap: 48px;
  max-width: 1232px;
  margin: 0 auto;
  padding: 56px 24px 32px;
}
.jh-foot__brand { flex: 1 1 260px; min-width: 220px; }
.jh-foot__logo { display: block; width: 150px; height: auto; margin-bottom: 14px; }
.jh-foot__mission { color: rgba(3,3,3,.72); font-size: 14px; line-height: 1.5; max-width: 300px; }
.jh-foot__cols { display: flex; flex-wrap: wrap; gap: 48px; flex: 2 1 520px; }
.jh-foot__col { min-width: 130px; }
.jh-foot__head {
  font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  color: #030303; font-weight: 600; margin-bottom: 12px;
}
.jh-foot__list { list-style: none; margin: 0; padding: 0; }
.jh-foot__list li { margin-bottom: 8px; }
.jh-foot__link, .jh-foot__legal-link {
  color: rgba(3,3,3,.78);
  text-decoration: none;
  font-size: 14px;
}
.jh-foot__link:hover, .jh-foot__legal-link:hover { color: #030303; text-decoration: underline; }
.jh-foot__legal {
  display: flex; flex-wrap: wrap; gap: 18px; justify-content: space-between;
  max-width: 1232px; margin: 0 auto;
  padding: 18px 24px 40px;
  border-top: 1px solid rgba(3,3,3,.1);
}
.jh-foot__copy { color: rgba(3,3,3,.6); font-size: 13px; }
.jh-foot__legal-links { display: flex; flex-wrap: wrap; gap: 18px; }
@media (max-width: 749px) {
  .jh-header__bar { gap: 14px; padding: 12px 16px; }
  .jh-nav { gap: 12px; }
  .jh-nav__link { font-size: 13px; }
  .jh-foot__inner { gap: 28px; padding: 40px 16px 24px; }
  .jh-foot__cols { gap: 28px; }
}
/* 39. CLIP-TEXT WITH NO PAINT — INVISIBLE GLYPHS THE AUDIT ABSTAINED ON.
 *     Found on the LIVE deploy, 2026-08-28. `.based-byob-pp__card-added-label` renders
 *     39x10px, offsetParent non-null — it is on screen — with:
 *         background-clip: text
 *         background-image: none          <- nothing to clip
 *         -webkit-text-fill-color: rgba(0,0,0,0)
 *     Clip-to-text with no image and a transparent fill paints NOTHING. The "Added" badge
 *     was invisible on every selected card.
 *     ⛔ AND THE AUDIT REPORTED ZERO. Its flat-clip-text branch scores an element only when
 *     the gradient has exactly ONE unique stop; here there are NONE, so it fell through to
 *     the abstention list. The count of failures was honest and the page was still broken —
 *     which is the whole reason abstentions get COUNTED and printed rather than dropped.
 *     A zero next to "abstained: 4" is a different claim from a zero on its own.
 *     The donor used this device to paint gold text; token_swap collapsed the ramp and the
 *     recovery merge kept `background-image: none` while losing the colour that replaced it.
 *     Cure the device, not the instance: anything clipping to text in this component gets
 *     real ink back. [[an-abstention-must-be-recorded]] */
.based-byob-pp__card-added-label,
.based-byob-pp__card-added-label * {
  background-image: none;
  background-color: #0f5132;
  -webkit-background-clip: border-box;
  background-clip: border-box;
  color: #ffffff;
  -webkit-text-fill-color: #ffffff;
}
.based-byob-pp__panel-heading-lead,
.based-byob-pp__panel-heading-accent,
.based-byob-pp__gift-card-name,
.based-byob-pp__mobile-slot-reward,
.based-byob-pp__panel strong,
.based-byob-pp__mobile-bar strong {
  background-image: none;
  -webkit-background-clip: border-box;
  background-clip: border-box;
  color: #030303;
  -webkit-text-fill-color: #030303;
}
.based-byob-pp__gift-card[data-unlocked="1"] .based-byob-pp__gift-card-name {
  color: #030303;
  -webkit-text-fill-color: #030303;
}

/* 40. THE PAINTLESS CLIP-TEXT, FINISHED — !important, and saying why.
 *     Rule 39 matched these elements and still lost: the donor's
 *     `.based-byob-pp--bbw .based-byob-pp__panel-heading-lead` is (0,2,0) against my
 *     (0,1,0). Confirmed by asking the browser which rules match, not by guessing.
 *     Still invisible after 39: "Build your set." / "Save more as you add." (the panel
 *     heading) and all three gift names.
 *     I have now spent five separate passes on this one cascade. The declaration is not in
 *     doubt — clip-to-text with no image and a transparent fill paints nothing — so the only
 *     remaining question is "who wins", and !important answers it without another round of
 *     specificity arithmetic.
 *     ⚠ MARKER, NOT A SOLUTION: this records that a donor rule outranks a correct one here.
 *     If this file is ever cleaned up, resolve the ownership properly — do not just delete
 *     the !important and assume it was cruft. */
.based-byob-pp__panel-heading-lead,
.based-byob-pp__panel-heading-accent,
.based-byob-pp__gift-card-name,
.based-byob-pp__mobile-slot-reward,
.based-byob-pp__panel strong,
.based-byob-pp__mobile-bar strong {
  background-image: none !important;
  -webkit-background-clip: border-box !important;
  background-clip: border-box !important;
  -webkit-text-fill-color: #030303 !important;
  color: #030303 !important;
}
.based-byob-pp__card-added-label,
.based-byob-pp__card-added-label * {
  background-color: #0f5132 !important;
  -webkit-text-fill-color: #ffffff !important;
  color: #ffffff !important;
}

/* 41. THE SAVINGS FIGURE — a CLASS-LESS span, which is why every selector list missed it.
 *     "−$102.00" in .based-byob-pp__totals-row--savings is a bare <span> with no class of
 *     its own, carrying the donor's clip-text device. Rules 39 and 40 enumerated class names
 *     and `strong`, so it fell through both. The money the customer SAVES is the single most
 *     persuasive number on the panel, and it was painting nothing.
 *     Target the CONTAINER's children, not a class the element does not have. */
.based-byob-pp__totals-row span,
.based-byob-pp__totals span,
.based-byob-pp__mobile-totals span,
.based-byob-pp__mobile-bar .based-byob-pp__totals-row span {
  background-image: none !important;
  -webkit-background-clip: border-box !important;
  background-clip: border-box !important;
  -webkit-text-fill-color: #030303 !important;
  color: #030303 !important;
}
.based-byob-pp__totals-row--savings span {
  -webkit-text-fill-color: #0f5132 !important;
  color: #0f5132 !important;
}

/* 42. THE EMPTY-STATE LADDER LABELS — the first thing anyone sees, painting nothing.
 *     "25% off" / "25% off + Hair Refresh" / "25% off + both gifts" live in
 *     .based-byob-pp__slot-reward on the DESKTOP panel. Rule 40 covered the mobile twin
 *     (.mobile-slot-reward) and not this one — enumerating names again, and missing one
 *     again. These only exist while slots are EMPTY, so every audit run after clicking
 *     "add" reported zero: the four-item state was clean and the state a visitor LANDS on
 *     was broken. Cover both surfaces and the hint text with them.
 *     [[a-state-rule-outranks-the-base-rule]] — the unaudited state is the shipped one. */
.based-byob-pp__slot-reward,
.based-byob-pp__slot-hint,
.based-byob-pp__mobile-slot-reward,
.based-byob-pp__mobile-slot-hint,
.based-byob-pp__slot-num,
.based-byob-pp__panel-progress,
.based-byob-pp__mobile-progress {
  background-image: none !important;
  -webkit-background-clip: border-box !important;
  background-clip: border-box !important;
  -webkit-text-fill-color: #030303 !important;
  color: #030303 !important;
}
.based-byob-pp__slot-hint,
.based-byob-pp__mobile-slot-hint {
  -webkit-text-fill-color: rgba(3,3,3,.66) !important;
  color: rgba(3,3,3,.66) !important;
}

/* 43. MY OWN RULE 41 PAINTED THE MOBILE CTA'S LABEL BLACK ON GREEN.
 *     Measured on the live mobile deploy: .based-byob-pp__checkout.mobile-cta-full computes
 *     background rgb(5,33,10) with color rgb(3,3,3) — 1.21:1. Near-black on near-black.
 *     CAUSE: rule 41 forced `#030303 !important` on `.based-byob-pp__totals span` to rescue
 *     the savings figure. The checkout BUTTON sits inside that totals block and its label is
 *     a span, so the fix for one string reached into a control with its own dark ground and
 *     blacked out the most important text on the phone.
 *     A broad `!important` written to rescue one element does not stop at that element.
 *     Scope by what the element IS, and put the exclusion in the SAME rule that over-reached
 *     rather than stacking another layer on top.
 *     (Also: the recovered skin restored the older #05210a green here — the one that reads as
 *     black. Back to the CTA green.) */
.based-byob-pp__checkout,
.based-byob-pp__checkout *,
.based-byob-pp__mobile-checkout,
.based-byob-pp__mobile-checkout *,
[data-byob-checkout],
[data-byob-checkout] *,
[data-byob-mobile-checkout],
[data-byob-mobile-checkout] * {
  -webkit-text-fill-color: #ffffff !important;
  color: #ffffff !important;
}
.based-byob-pp__checkout,
.based-byob-pp__mobile-checkout,
[data-byob-checkout],
[data-byob-mobile-checkout] {
  background-color: #0f5132 !important;
  background-image: none !important;
  border-color: #0f5132 !important;
}
/* the disabled state keeps DARK ink on its grey — white would vanish there */
.based-byob-pp__checkout:disabled,
.based-byob-pp__checkout:disabled *,
.based-byob-pp__mobile-checkout:disabled,
.based-byob-pp__mobile-checkout:disabled *,
[data-byob-checkout]:disabled,
[data-byob-checkout]:disabled * {
  background-color: #dedede !important;
  -webkit-text-fill-color: rgba(3,3,3,.75) !important;
  color: rgba(3,3,3,.75) !important;
  border-color: #c9c9c9 !important;
}

/* 44. THE $0.00 PLACEHOLDER — dimmed by the donor to opacity .5, which on our white ground
 *     lands at 3.90:1, under the 4.5 floor. It is the subtotal on the state a visitor LANDS
 *     on, so "it's only a placeholder" is not a reason to leave it unreadable.
 *     .68 clears the floor and still reads as inactive — dimming is a hierarchy signal, not
 *     permission to go below legibility. Same call as the locked gift label. */
.based-byob-pp__totals-row span[style*="opacity"],
.based-byob-pp__totals-row > span,
.based-byob-pp__totals span,
.based-byob-pp__mobile-totals span {
  opacity: 1 !important;
}
.based-byob-pp__totals-row--empty span,
.based-byob-pp__totals-row span.is-empty {
  -webkit-text-fill-color: rgba(3,3,3,.68) !important;
  color: rgba(3,3,3,.68) !important;
}

/* ══ ORDER #1630 — REGRESSION FROM THE TRANSCRIPT RECOVERY ════════════════════════════════
 * 45. THE REPLAY RESTORED SUPERSEDED RULES ALONGSIDE THEIR REPLACEMENTS.
 *     Recovering jh-skin.css by replaying every `cat >>` append put back the FIRST version of
 *     each rule as well as the corrected one. I re-applied three in-place corrections during
 *     the merge and there were more than three. An append log is not a history — it has no
 *     concept of "and then I replaced that".
 *
 *     MEASURED on the live deploy at 1440:
 *       .based-byob-pp__gift-group-cards  display: flex   (the donor sets `contents`)
 *       gift row spans 1029..1379
 *       card 1 "Free Hair Refresh"  x=1030 w=348   <- one group, whole row
 *       card 2 "Free Face Blade"    x=1388         <- OUTSIDE the row
 *       card 3 "Free Deodorant"     x=1566         <- further outside
 *     `display: contents` is what promotes each group's cards into the shared row so all
 *     three sit side by side. Forcing `flex` makes every GROUP a row of its own, so group 1
 *     (1 gift) eats the full width and group 2 (2 gifts) runs off the panel. That is exactly
 *     the "free gifts going off the screen" Kalp is seeing.
 *     [[a-file-has-three-strata-and-only-one-ships]] */
.based-byob-pp__gift-group-cards.based-byob-pp__gift-group-cards,
.based-byob-pp__gift-group.based-byob-pp__gift-group {
  display: contents !important;
}
.based-byob-pp__gift-cards.based-byob-pp__gift-cards {
  display: flex !important;
  flex-direction: row !important;
  flex-wrap: nowrap !important;
  gap: 4px !important;
  width: 100%;
}
.based-byob-pp__gift-card.based-byob-pp__gift-card {
  flex: 1 1 0 !important;
  min-width: 0 !important;
}

/* 46. THE HERO COPY WENT DARK AGAIN — same cause, and the audit cannot see it.
 *     MEASURED: .based-byob-pp__hero-body computes rgba(3,3,3,0.7). The hero's left half is a
 *     pure black plate by construction, so dark copy on it is invisible; at mobile widths the
 *     same dark copy lands on the light product cluster and is barely better.
 *     Rule 22 (hero copy -> white) was one of the corrections the replay did not restore.
 *     ⚠ AND contrast_audit ABSTAINS here: the hero's background is a url(), which it reports
 *     as PHOTO and declines to score. Every "0 failures" run this session was silent about
 *     the largest type on the page. The hero is verified by SAMPLING THE JPEG's pixels under
 *     each string, not by the audit — that check lives outside the audit and has to be run
 *     deliberately. [[an-abstention-must-be-recorded]] */
.based-byob-pp__hero .based-byob-pp__hero-title,
.based-byob-pp__hero .based-byob-pp__hero-title-accent,
.based-byob-pp__hero .based-byob-pp__hero-body,
.based-byob-pp__hero .based-byob-pp__hero-eyebrow-text,
.based-byob-pp__hero .based-byob-pp__hero-eyebrow {
  background-image: none !important;
  -webkit-background-clip: border-box !important;
  background-clip: border-box !important;
  color: #ffffff !important;
  -webkit-text-fill-color: #ffffff !important;
}
.based-byob-pp__hero .based-byob-pp__hero-body {
  color: rgba(255,255,255,.86) !important;
  -webkit-text-fill-color: rgba(255,255,255,.86) !important;
}
.based-byob-pp__hero .based-byob-pp__hero-eyebrow {
  border-color: rgba(255,255,255,.34) !important;
  background-color: transparent !important;
}

/* 47. ANCHOR THE HERO LEFT BELOW 1200px, SO THE COPY PLATE SURVIVES THE CROP.
 *     `background-position: right center` is correct at 1440+, where the box is wide enough
 *     that the whole image fits and the plate shows. Below that, `cover` crops the sides and
 *     right-anchoring throws away the LEFT — which is the plate the copy sits on. Measured
 *     white-on-worst-pixel across the band: 750px 1.16 · 1024px 1.01 · 1200px 1.07.
 *     Anchoring left keeps the plate; the products are the half that gets cropped instead,
 *     which is the right thing to lose — a partially-cropped bottle still reads as product,
 *     unreadable copy reads as nothing. */
@media (min-width: 750px) and (max-width: 1199px) {
  .based-byob-pp__hero.based-byob-pp__hero {
    background-position: left center !important;
    background-size: cover !important;
  }
}

/* 48. THE WHITE WASH CAME BACK, AND IT IS THE WHOLE "BROKEN HERO".
 *     jh-render-fixes.css was also destroyed by `rm -rf build` and restored from an OLD copy,
 *     which still contains the rule I retired when the black-plate hero was built:
 *         .based-byob-pp__hero::before {
 *           background: linear-gradient(100deg, rgba(255,255,255,.94) 0%, ...)  }
 *     A 94%-opaque WHITE sheet over the entire hero. It existed to lift a dark PHOTO hero
 *     behind dark copy — the opposite of the composition we ship now. That is why the hero
 *     reads as a pale washed-out image with grey text sitting on the product cards.
 *     The same old file also re-imposes `background-position: 50% 18%`, which overrode the
 *     left/right anchoring rule 47 depends on, and left the hero with no image resolving at
 *     all in the 750..1199 band.
 *     Recovering a file recovers its MISTAKES too. Everything the newer version deleted comes
 *     back, silently, and only shows up where someone looks at the page.
 *     Owning all three here so no restored copy of that file can re-break it. */
.based-byob-pp__hero.based-byob-pp__hero::before {
  content: none !important;
  background: none !important;
}
.based-byob-pp__hero.based-byob-pp__hero,
.based-byob-pp__hero--responsive.based-byob-pp__hero--responsive {
  background-image: url(jh-hero.jpg) !important;
  background-repeat: no-repeat !important;
  background-size: cover !important;
  background-position: left center !important;
}
/* left at EVERY width: the copy column never passes source x ~1120 with a left anchor, so
 * the plate covers it in every crop, and the cluster at 1420..2290 stays inside the narrowest
 * window (~1860 source px at the measured 2.39:1 box). One rule, no band to get wrong. */
@media (max-width: 749px) {
  .based-byob-pp__hero.based-byob-pp__hero,
  .based-byob-pp__hero--responsive.based-byob-pp__hero--responsive {
    background-image: url(jh-hero-mobile.jpg) !important;
    background-position: center top !important;
  }
}

/* ══ ORDER #1637 — Kalp, 2026-08-28 ═══════════════════════════════════════════════════════
 * 49. THE "ADDED" BADGE WAS GREEN-INSIDE-GREY, AND I PUT THE GREEN THERE.
 *     Rule 40 set .card-added-label to background #0f5132 with white ink, to rescue the label
 *     when it was rendering with NO paint at all (clip:text, no image, transparent fill).
 *     That fixed legibility and created a new problem: a green pill sitting inside the grey
 *     badge, which reads as two components rather than one.
 *     A fix aimed at one property should not decide another. The legibility problem was the
 *     FILL being transparent — the background never needed to change. Ink goes dark, ground
 *     goes back to the badge's own grey, and the badge reads as one flat chip. */
.based-byob-pp__card-added-label,
.based-byob-pp__card-added-label * {
  background-color: transparent !important;
  background-image: none !important;
  -webkit-background-clip: border-box !important;
  background-clip: border-box !important;
  color: #3a3a3a !important;
  -webkit-text-fill-color: #3a3a3a !important;
}
.based-byob-pp__card-added,
.based-byob-pp__card-added-check {
  color: #3a3a3a !important;
  stroke: #3a3a3a !important;
}

/* 50. THE HEADER MUST BE ITS OWN BAR, NOT A SHEET OVER THE ARTWORK.
 *     Kalp: "have the header be its own bar, like a solid bar, and then push the banner down."
 *     MEASURED at 375: .bbw-header is position:fixed, background rgba(0,0,0,0) — TRANSPARENT
 *     (the solid-black rule was another casualty of the transcript recovery) — 87px tall at
 *     top 0, while the hero starts at top -1. So the burger, wordmark, account and cart all
 *     float directly on the product photography, and the top 87px of the banner we designed
 *     is spent behind chrome nobody can read it through.
 *     `position: sticky` is the whole fix: a sticky element PARTICIPATES IN NORMAL FLOW, so
 *     the hero starts below it automatically — no magic offset to keep in sync with a header
 *     height that changes per breakpoint — and it still pins on scroll. Solid ground so the
 *     bar is a bar. */
/* ⚠ v2: `sticky` put the bar in normal flow (hero correctly started below it) but never
 * PINNED — measured -500 at scrollY 500, and still -600 after clearing the ancestors'
 * overflow-x, so something further up the chain disqualifies it. A sticky header that
 * scrolls away takes the cart with it on a commerce page.
 * Back to the donor's `fixed` for persistence, and the space it used to steal is given
 * back by a spacer MEASURED from the header itself (see the script jh_chrome injects) —
 * self-sizing, so it cannot drift out of step with a header height that differs per
 * breakpoint (87 mobile / 98 desktop). A magic offset is the thing that rots. */
.bbw-header.bbw-header {
  position: fixed;
  top: 0;
  background: #030303;
  background-image: none;
}
.bbw-header.bbw-header .bbw-header__bar,
.bbw-header.bbw-header .bbw-header__barwrap,
.bbw-header.bbw-header .bbw-header__container {
  background: #030303;
}
/* the hero now begins under the bar rather than behind it */
.based-byob-pp__hero.based-byob-pp__hero {
  margin-top: 0;
}

/* ══ ORDER #1638 — Kalp, 2026-08-28 ═══════════════════════════════════════════════════════
 * 51. THE PAGE LEANS RIGHT BY EXACTLY ONE SCROLLBAR.
 *     Kalp: "the left side there's border and spacing, the right side doesn't — it's not
 *     balanced, there's some horizontal overflow."
 *     MEASURED at 824: scrollWidth == clientWidth (813), zero elements past the client edge,
 *     grid gaps 25 left / 25 right — the layout is PERFECTLY centred and there is no overflow.
 *     What is unbalanced is the WINDOW: innerWidth 824, clientWidth 813, scrollbar 11px. The
 *     content is centred in the 813 the page can see, so against the window it reads 25 left
 *     and 36 right. He is seeing something real; it is just not the thing it looks like.
 *     `scrollbar-gutter: stable both-edges` reserves the gutter on BOTH sides, so the centred
 *     content is centred against the window too.
 *     ⚠ Cost, stated: 11px of usable width is given up on the left in exchange for symmetry.
 *     That is the trade — it is not free, and if the page ever feels cramped this is the line
 *     to revisit. */
/* ⛔ RETRACTED, 2026-08-28 — THIS MADE IT WORSE AND KALP SAW IT IMMEDIATELY.
 * `scrollbar-gutter: stable both-edges` reserves the gutter on BOTH sides. It did make the
 * two gaps equal in the numbers I checked (36/36), and on screen it added an unpainted 11px
 * strip down the LEFT and pushed every element right — the white line he photographed, and a
 * page that now visibly leans instead of measurably leaning.
 * I "balanced" the measurement I was looking at and worsened the thing he was pointing at.
 * The gaps being equal was never the goal; the page not looking shifted was.
 * [[a-no-op-that-reads-as-a-working-fix]] — except this one was worse than a no-op. */

/* a 2px left bleed measured on the hero accent — it starts at x -2, which is the other half
 * of "the left edge looks different from the right" */
.based-byob-pp__hero .based-byob-pp__hero-title-accent {
  margin-left: 0;
  padding-left: 0;
}

/* 52. THE DESKTOP SCENT PICKER WORKS — IT JUST NEVER SAYS SO.
 *     Kalp: "on desktop we have no way to select colour."
 *     MEASURED: the mechanic is fine — 5 dots on Deodorant, clicking sets
 *     data-picked-scent="Hinoki Cypress" and flips aria-pressed true/false correctly. What is
 *     missing is FEEDBACK: every dot is 14px with `border: 1px solid rgb(3,3,3)` whether
 *     selected or not, so nothing on screen distinguishes the chosen one. A control that
 *     changes state invisibly is, to the person using it, a control that does not work — which
 *     is exactly the report.
 *     Bigger targets, and the selected dot gets a ring the unselected ones do not. */
.based-byob-pp__card-scents {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 2px 0 0;
}
.based-byob-pp__scent {
  width: 18px;
  height: 18px;
  min-width: 18px;
  border-radius: 50%;
  padding: 0;
  cursor: pointer;
  background-color: var(--byob-scent-color, #5c4a38);
  border: 1px solid rgba(3,3,3,.28);
  box-shadow: none;
  transition: box-shadow .12s ease, transform .12s ease;
}
.based-byob-pp__scent:hover {
  transform: scale(1.08);
  border-color: rgba(3,3,3,.55);
}
/* the selected one: a ring OUTSIDE the dot, so the swatch colour stays readable */
/* ⛔ BEATEN BY MY OWN BLANKET RULE. Line 4 of this file is
 *     *, *::before, *::after { box-shadow: none !important }
 * from the early "hard lines, no soft shadows" pass — Jack Henry's flat register. It is
 * doing its job, and it also erased the only affordance telling a customer which scent they
 * had chosen. A blanket !important does not know which shadows are decoration and which are
 * STATE. Keeping the brand rule intact and winning on specificity (0,2,0 beats *) rather
 * than punching a hole in it. */
.based-byob-pp__scent[aria-pressed="true"] {
  border-color: #030303 !important;
  box-shadow: 0 0 0 2px #ffffff, 0 0 0 4px #0f5132 !important;
}
.based-byob-pp__scent:focus-visible {
  outline: 2px solid #0f5132;
  outline-offset: 3px;
}
.based-byob-pp__scent--oos {
  opacity: .35;
  cursor: not-allowed;
}

/* 53. THE MOBILE LEAN — A FLEX ITEM CANNOT SHRINK BELOW ITS CONTENT UNLESS YOU SAY SO.
 *     Kalp, twice: "everything is leaning towards the right on mobile."
 *     MEASURED at 375 (client 375, no scrollbar):
 *         .based-byob-pp__body     L 12 / R 12   balanced
 *         .based-byob-pp__tabs     width 399     <- 24px past the viewport
 *         product grid             width 399, L 12, R -36
 *         rightmost visible pixel  411 vs client 375
 *     So the page really was cut on the right by 36px, hidden by `overflow-x: clip` — 12px of
 *     margin on the left and a hard crop on the right is exactly what "leaning right" looks
 *     like.
 *
 *     ⛔ AND I CAUSED IT. The tab strip is `flex-wrap: nowrap` with `overflow-x: auto` — a
 *     deliberately scrollable strip. A flex item defaults to `min-width: auto`, which means it
 *     REFUSES to shrink below its content's min-content width. With four tabs that width fit.
 *     Adding "Best Sellers" (124px) took the strip's min-content to 399, which forced its
 *     parent to 399, which forced the grid to 399, which pushed the second card column 36px
 *     off screen. The overflow-x:auto never got a chance to scroll, because nothing was ever
 *     narrower than the content.
 *     `min-width: 0` lets the strip shrink and scroll as designed, and the grid returns to the
 *     container width.
 *
 *     ⚠ AND MY EARLIER "FIX" MADE IT WORSE: scrollbar-gutter: stable both-edges (rule 51,
 *     now retracted) equalised the two NUMBERS I was looking at while adding an unpainted
 *     strip down the left and shifting everything right — the white line in his screenshot.
 *     I balanced a measurement instead of finding the defect, because the metric I trusted
 *     (scrollWidth) CANNOT exceed clientWidth while overflow-x is clipped. The instrument was
 *     structurally incapable of reporting the thing I was asking it about.
 *     [[a-probe-that-cannot-observe-the-instrument-reports-the-page-as-broken]] */
.based-byob-pp__main,
.based-byob-pp__body,
.based-byob-pp__tabs,
.based-byob-pp__grid {
  min-width: 0;
}
.based-byob-pp__tabs {
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}
.based-byob-pp__tabs::-webkit-scrollbar { display: none; }

/* 55. HALF-REVERSED BY RULE 56 BELOW — the gift row came back; only the totals stay cut.
 *     Everything this comment says about the GIFT ROW was wrong. Read 56 before trusting it.
 *
 *     THE 98 EXTRA PIXELS ARE TWO BLOCKS THAT SAY WHAT IS ALREADY ON SCREEN.
 *     Corrected census of .based-byob-pp__mobile-detail (152px) — I had guessed it was the
 *     gift row alone; it is TWO children:
 *         gift-cards--grouped   65px   "Free gift at 3 items / LOCKED · AT 3"
 *         totals                66px   "Subtotal $186.00 / Savings (25% + gifts)"
 *         + 13px gap + padding       = 152
 *     BASED's detail is 54px and contains neither.
 *
 *     Both are duplicates ON THIS SURFACE:
 *       · the gift row repeats the ladder tiles 85px above it, which already read
 *         "25% off", "25% off + Hair Refresh", "25% off + both gifts"
 *       · the totals repeat the checkout button directly below, which reads
 *         "Continue to Checkout  $66.00"
 *     A phone is the one place where nothing can afford to be said twice.
 *
 *     ⛔ MY OWN RULE 45 BLOCKED THE FIRST ATTEMPT: `.gift-cards.gift-cards { display: flex
 *     !important }` — written to repair the gift ROW on desktop — outranked the plain
 *     `display: none` I wrote here. An !important applied to fix one surface silently owns
 *     every other surface that selector reaches. Scoped to the mobile bar and matched in
 *     kind. The desktop panel keeps both blocks; it has the room and no duplicate above. */
.based-byob-pp__mobile-bar .based-byob-pp__totals,
.based-byob-pp__mobile-bar .based-byob-pp__totals-row {
  display: none !important;
}

/* 56. ⛔ I DELETED THE MECHANIC TO HIT A HEIGHT TARGET. Kalp, 2026-08-28:
 *     "we still need the gift house to show? If not, like, what the hell is the point of
 *      this page?"
 *     Rule 55 above cut TWO blocks to get the bar from 387px to 235px. One of them — the
 *     totals — was a real duplicate of the checkout button 8px below it. The other was the
 *     three gift cards, and those are not a duplicate of anything: they are the ONE surface
 *     on a phone that says what the ladder is FOR. The tiles above them show four products;
 *     only these say a free Hair Refresh, a free Face Blade, a free Deodorant, and which of
 *     them you have already earned. Cutting them made the bar shorter and the page pointless.
 *
 *     THE TELL I HAD AND IGNORED: rule 55's own justification called the gift row a repeat of
 *     "25% off + Hair Refresh" on the tiles. That text is the tiles' REWARD LABEL — it names
 *     the gift as a CONDITION of a slot. The gift card names it as a THING YOU GET, with its
 *     own image and its own locked/unlocked state. Same nouns, different claim. A duplicate
 *     test run on VOCABULARY says delete; run on what each element ASSERTS it says keep.
 *     [[a-retrieval-merge-is-not-a-description]] · [[belief-is-stance-not-vocabulary]]
 *
 *     Restored at 54px (2-line names) — bar 255px / 31% of a 812px screen, still under BASED's
 *     299px / 37%, and CONSTANT at 0, 2 and 4 items. The height win came from the totals and
 *     from rule 25's dead 34px, not from the gifts.
 *
 *     Three sub-fixes the restore needed, all measured at 375:
 *       a. the donor's `max-width: 70%` on .gift-card-name capped the label at 37px inside a
 *          53px column, so "Free Deodorant" broke mid-word as "Deodor / ant".
 *       b. the cutout at 52px left the text column too narrow; 40px clears it by 11px.
 *       c. rule 45's `display: flex !important` on .gift-cards has to be re-asserted at equal
 *          specificity here — it is what rule 55 had to out-rank in the first place. */
.based-byob-pp__mobile-bar .based-byob-pp__gift-cards.based-byob-pp__gift-cards {
  display: flex !important;
  gap: 4px !important;
  margin-top: 0 !important;
}
.based-byob-pp__mobile-bar .based-byob-pp__gift-group,
.based-byob-pp__mobile-bar .based-byob-pp__gift-group-cards {
  display: contents !important;
}
.based-byob-pp__mobile-bar .based-byob-pp__gift-card {
  padding: 6px 6px 6px 8px !important;
}
.based-byob-pp__mobile-bar .based-byob-pp__gift-card-img--cutout {
  width: 40px !important;
  flex: 0 0 40px !important;
}
.based-byob-pp__mobile-bar .based-byob-pp__gift-card-text {
  flex: 1 1 auto !important;
  min-width: 0 !important;
}
.based-byob-pp__mobile-bar .based-byob-pp__gift-card-name {
  max-width: none !important;
  width: 100% !important;
  align-self: stretch !important;
  overflow-wrap: normal !important;
  font-size: 10px !important;
  line-height: 1.15 !important;
}
/* with both gone the detail collapses; keep it out of the flow entirely when empty */
.based-byob-pp__mobile-bar .based-byob-pp__mobile-detail:not([data-has-content]) {
  padding: 0;
  gap: 0;
}
