/* BFCM landing — v8 (v7 + short lead, the hero bar sinks as one piece on hover, product photos on the receipt rows,
   screen 2 cart stage at a real drawer width ≤480px).
   Was v7: v6 + hero receipt with coins, screen 2 = one cart stage playing the two widgets in sequence, "safe to try" lead.
   Was v6: hero 2 columns, real widgets on screen 2. The prototype's "BFCM banners" popup (Free Gifts tab), page-sized.
   Source: aov-cd-prototype origin/main src/pages/bundle/bfcm/bfcm.css (.bfpop-fg--paper).
   Ink + white/paper, yellow only for emphasis (headline line 2, shadows, chip, fill at goal),
   red only for the goal marker (and the error mark, same red). 2px ink borders, square corners,
   offset yellow shadow with an ink rim. */

:root {
  --ink: #111111;
  --y: #FFD23F;
  --cut: #FF5A36;
  --paper: #F4F3EE;
  --muted: #6E6B66;
  --num: #4A4844;
  --track: #D3D1CB;
  --thumb: #F4EFE9;

  --display: "Space Grotesk", system-ui, sans-serif;
  --body: "DM Sans", system-ui, sans-serif;
  --mono: "DM Mono", ui-monospace, monospace;

  --shadow-lg: 8px 8px 0 var(--y), 8px 8px 0 2px var(--ink);
  --shadow-btn: 4px 4px 0 var(--y), 4px 4px 0 2px var(--ink);
  --shadow-btn-down: 2px 2px 0 var(--y), 2px 2px 0 2px var(--ink);

  --gutter: 40px;
  --shell: 1200px;
  --bars: 107.5px; /* ticker 39.5 + nav 68, desktop */
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: #fff;
  color: var(--ink);
  font: 400 16px/1.5 var(--body);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}
h1, h2, p { margin: 0; }
[hidden] { display: none !important; }
img { display: block; max-width: 100%; }
button, input { font: inherit; color: inherit; }
a { color: inherit; }

.shell { width: 100%; max-width: calc(var(--shell) + var(--gutter) * 2); margin-inline: auto; padding-inline: var(--gutter); }
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.glyph { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }

@keyframes bf-in { from { opacity: 0; transform: translateY(5px); } }
@keyframes bfm-pop { from { transform: scale(.6); opacity: 0; } }
@keyframes bf-scroll { to { transform: translateX(-50%); } }

/* ───────── ticker (.bf-ticker) ───────── */
.ticker { overflow: hidden; white-space: nowrap; background: var(--ink); border-top: 1.5px dashed rgba(255, 255, 255, .35); }
.ticker__track {
  display: inline-block; padding: 11px 0;
  font: 700 16px/1 var(--display); letter-spacing: -.01em; color: var(--y);
  animation: bf-scroll 42s linear infinite;
}
.ticker__track span { display: inline-flex; align-items: center; }
.ticker__track span::after { content: ""; width: 7px; height: 7px; margin: 0 26px; background: #fff; }
/* The band between the goal and the end block runs the other way. */
.ticker--rev { border-top: 2px solid var(--ink); }
.ticker--rev .ticker__track { animation-direction: reverse; }

/* ───────── nav ───────── */
.nav__in { display: flex; align-items: center; justify-content: space-between; gap: 16px; height: 68px; }
.nav__brand { display: block; color: var(--ink); }
.nav__logo { display: block; width: 100px; height: auto; }
.nav__install {
  padding: 7px 12px; border: 1.5px solid var(--ink); text-decoration: none;
  font: 500 14px/1.2 var(--body); transition: background .1s, color .1s;
}
.nav__install:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

/* The dealbar is gone, so the top ticker no longer needs the dashed seam above it. */
.ticker:not(.ticker--rev) { border-top: 0; }

/* ───────── hero: copy + form (left) | BFCM illustration (right) ───────── */
.hero__in {
  display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); column-gap: 40px; align-items: center;
  padding-top: 32px; padding-bottom: 48px;
}
/* The H1 is sized from its own column (container units): line 1 fits the column with ≥24px to spare
   in Space Grotesk and in the Arial fallback (widest of the two = 12.36 × font-size, measured). */
.hero__copy { min-width: 0; container-type: inline-size; }

/* chip pair (.bfp2-b, paper) */
.pair {
  display: inline-flex; align-items: stretch; font: 700 13px/1 var(--display); letter-spacing: .06em; text-transform: uppercase;
  transform-origin: 0 50%; animation: bfm-pop .35s cubic-bezier(.2, 1.6, .4, 1) .1s both;
}
.pair__a, .pair__b { display: inline-flex; align-items: center; gap: 8px; padding: 10px 14px; }
.pair__a { padding-right: 21px; border: 1.5px solid var(--ink); border-right: 0; }
.pair__b { padding-left: 21px; background: var(--y); border: 1.5px solid var(--ink); }
.pair__seam { position: relative; width: 0; }
.pair__seam b {
  position: absolute; top: 50%; left: 0; z-index: 1; display: grid; place-items: center;
  width: 26px; height: 26px; transform: translate(-50%, -50%); border-radius: 50%;
  background: var(--ink); border: 1.5px solid var(--y); color: var(--y); font: 500 16px/1 var(--mono);
}
.pair .glyph { width: 18px; height: 18px; }

/* title: 2 lines, line 2 on yellow. Line 1 = 12.36 × font-size wide → font = (column − 28px) / 12.6. No nowrap:
   if a fallback font is ever wider, it wraps instead of running into the illustration. */
.hero__title {
  margin-top: 22px;
  font: 700 clamp(30px, calc((100cqi - 28px) / 12.6), 64px)/1.18 var(--display); letter-spacing: -.03em;
  text-wrap: balance;
}
.hero__title .hero__l1 { padding-bottom: .08em; }
.hero__title > span, .goal-sec__title > span, .end__title > span { display: block; }
/* Line 2: yellow on the text run only (inline, cloned per wrapped line) — never a full-width bar. */
.hero__title em, .goal-sec__title em, .end__title em {
  font-style: normal; padding: 0 .1em; background: var(--y); color: var(--ink);
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.hero__lead { max-width: 580px; margin-top: 18px; font: 400 17px/1.55 var(--body); color: var(--num); text-wrap: pretty; }

/* form: field + button joined into one bar, carrying the offset yellow shadow (v5 run card) */
.run-form {
  display: flex; max-width: 560px; margin-top: 28px; margin-right: 8px;
  border: 2px solid var(--ink); background: #fff; box-shadow: var(--shadow-lg);
  animation: bf-in .25s ease both;
  transition: translate .12s ease, box-shadow .12s ease;
}
.field {
  flex: 1; width: 100%; min-width: 0; height: 56px; padding: 0 16px;
  background: #fff; border: 0; border-radius: 0;
  font: 500 16px/1 var(--body); color: var(--ink);
}
.field::placeholder { color: var(--muted); opacity: 1; }
.field:focus { outline: none; box-shadow: inset 0 -4px 0 var(--y); }
.run-form:has(.field[aria-invalid="true"]) { border-color: var(--cut); }

.cta {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; flex: none;
  height: 56px; padding: 0 22px; white-space: nowrap; text-decoration: none; cursor: pointer;
  background: var(--ink); color: #fff; border: 2px solid var(--ink); border-radius: 0;
  box-shadow: var(--shadow-btn);
  font: 700 16px/1 var(--body);
  transition: transform .1s, box-shadow .1s, background .1s, color .1s;
}
.cta:active { transform: translate(2px, 2px); box-shadow: var(--shadow-btn-down); }
.cta:focus-visible { outline: 2px solid var(--ink); outline-offset: 6px; }
/* inside the joined bar the button has no shadow of its own (the bar has it) */
.run-form .cta { height: 56px; border: 0; box-shadow: none; }
/* The button sits inside the bar, so the bar sinks, not the button: moved 2px → shadow 8px → 6px (the shadow's far edge
   stays put), pressed 4px → shadow 4px. The button keeps ink + white, only deepening to #000. */
.run-form .cta { transition: background .12s ease; }
.run-form:has(.cta:active) { translate: 4px 4px; box-shadow: 4px 4px 0 var(--y), 4px 4px 0 2px var(--ink); }
.run-form .cta:active { transform: none; box-shadow: none; background: #000; color: #fff; }
.run-form .cta:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
@media (hover: hover) {
  .cta:hover { transform: translate(2px, 2px); box-shadow: var(--shadow-btn-down); }
  .run-form:has(.cta:hover):not(:has(.cta:active)) { translate: 2px 2px; box-shadow: 6px 6px 0 var(--y), 6px 6px 0 2px var(--ink); }
  .run-form .cta:hover { transform: none; box-shadow: none; background: #000; color: #fff; }
  .nav__install:hover { background: var(--ink); color: #fff; }
}

/* error: ink text, one red mark, no second red */
.run-status { display: flex; gap: 9px; max-width: 560px; margin-top: 14px; font: 500 14px/1.45 var(--body); color: var(--ink); }
.run-status:empty { display: none; }
.run-status[data-tone="error"]::before { content: ""; flex: none; width: 8px; height: 8px; margin-top: 6px; background: var(--cut); }
.hero__fine { margin-top: 16px; font: 400 14px/1.4 var(--body); color: var(--num); }

/* countdown (.bf-count) — secondary: one small row under the form, flush left with it */
.count { display: flex; align-items: center; gap: 12px; margin-top: 18px; }
.count__label { font: 500 12px/1.2 var(--mono); color: var(--num); }
.count__cells { display: flex; gap: 4px; }
.count__cell {
  display: inline-flex; align-items: baseline; gap: 2px; padding: 6px 7px 5px;
  background: var(--ink); color: var(--y); font-family: var(--mono); font-weight: 500; font-variant-numeric: tabular-nums;
}
.count__cell b { font-weight: 500; font-size: 16px; line-height: 1; min-width: 2ch; text-align: right; }
.count__cell i { font-style: normal; font-size: 11px; line-height: 1; }

/* ── illustration: one focal point (the receipt) + 4 coins on two layers ──
   The paper is a white sheet with zig-zag top/bottom edges (mask on .bill__paper); the ink rim and the offset
   yellow shadow are drop-shadows on .bill (a filter on the masked element itself would be cut by the mask). */
.art { position: relative; justify-self: end; width: 100%; max-width: 480px; padding: 48px 56px 52px 64px; }
.bill { position: relative; z-index: 1; width: 100%; max-width: 360px; margin-inline: auto;
  filter: drop-shadow(2px 0 0 var(--ink)) drop-shadow(-2px 0 0 var(--ink)) drop-shadow(0 2px 0 var(--ink)) drop-shadow(0 -2px 0 var(--ink))
          drop-shadow(8px 8px 0 var(--y)); }
.bill__paper {
  --tooth: 14px; --edge: 7px;
  display: flex; flex-direction: column; padding: calc(var(--edge) + 20px) 26px calc(var(--edge) + 22px);
  background: #fff; color: var(--ink); font-variant-numeric: tabular-nums lining-nums;
  -webkit-mask: var(--zig); mask: var(--zig);
  --zig:
    conic-gradient(from 135deg at 50% 0, #000 90deg, #0000 0) top / var(--tooth) var(--edge) round no-repeat,
    linear-gradient(#000 0 0) center / 100% calc(100% - var(--edge) * 2 + 1px) no-repeat,
    conic-gradient(from -45deg at 50% 100%, #000 90deg, #0000 0) bottom / var(--tooth) var(--edge) round no-repeat;
}
.bill__title {
  padding-bottom: 14px; border-bottom: 2px solid var(--ink);
  font: 700 26px/1.05 var(--display); letter-spacing: -.035em;
}
.bill__rows { display: grid; gap: 11px; margin-top: 16px; margin-bottom: 20px; }
.bill__row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: 16px; font: 400 15px/1.35 var(--body); }
.bill__row > :last-child { text-align: right; white-space: nowrap; }
.bill__row b { font-weight: 700; }
/* item rows: the same product photo as the screen 2 cart, left of the name (v5 thumb: square, ink rim, warm ground) */
.bill__row:has(.bill__item) { align-items: center; }
.bill__item { display: flex; align-items: center; gap: 12px; min-width: 0; }
.bill__thumb { flex: none; width: 40px; height: 40px; overflow: hidden; border-radius: 4px; border: 1.5px solid var(--ink); background: var(--thumb); }
.bill__thumb img { width: 100%; height: 100%; object-fit: cover; }
/* the gift line's name is a tag, like the gift row in the screen 2 cart */
.bill__tag { padding: 3px 8px; border-radius: 4px; background: rgba(51, 51, 51, .08); font-size: 13px; font-weight: 600; line-height: 1.3; white-space: nowrap; }
.bill__gift { padding: 2px 6px; background: var(--y); font-weight: 700; }
.bill__gift small, .bill__free small { display: block; font-size: 12px; font-weight: 500; line-height: 1.25; }
/* free shipping: the same "$0.00 (costs you $6)" shape as the gift, without the yellow (yellow stays on the gift) */
.bill__free { padding: 2px 6px; font-weight: 700; }
/* the highlight pads out past the column so the amounts line up with $60.00 / +$30.00 above */
.bill__free, .bill__gift { margin-right: -6px; }
.bill__name { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.bill__at { font-size: 12px; line-height: 1.2; color: var(--muted); }
.bill__thumb--icon { display: flex; align-items: center; justify-content: center; color: var(--ink); background: #fff; }
.bill__rule { display: block; border-top: 2px dashed var(--ink); }
.bill__row--total { font-size: 18px; }
.bill__row--net { color: var(--muted); font-size: 14px; }
.bill__stamp {
  align-self: flex-end; padding: 4px 12px; border: 2px solid var(--ink); background: var(--y);
  font: 700 12.5px/1.4 var(--body); letter-spacing: .07em; text-transform: uppercase; rotate: 3deg;
}

/* the tilt sits on the img, the drop + float on the span: a translate inside a rotated box would push the coin sideways */
.art__coin { position: absolute; display: block; }
.art__coin img { width: 100%; height: auto; rotate: var(--r, 0deg); } /* real ratio of each coin file, never stretched */
/* front: one large coin over the paper's empty lower-left corner (labels sit above it), one beside (not over) the right edge */
.art__coin--1 { --r: -8deg; left: -1%; top: 77%; width: 22%; z-index: 2; }
.art__coin--2 { --r: 10deg; right: -5%; top: 13%; width: 14%; z-index: 2; }
/* behind: small and soft, peeking out from behind the paper */
.art__coin--3 { --r: 0deg; left: 6%; top: 6%; width: 10%; z-index: 0; opacity: .7; filter: blur(1.5px); }
.art__coin--4 { --r: 0deg; right: 1%; top: 62%; width: 10%; z-index: 0; opacity: .75; filter: blur(1px); }
.art.is-debug .art__coin { outline: 2px solid red; outline-offset: -1px; }

/* receipt print — runs once on load: paper slides down out of the printer (.55s) → rows one by one → the gift row
   lights up → the stamp lands (1.15 → 1) → coins drop into place, then float out of phase. */
@keyframes bill-print { from { clip-path: inset(0 0 100% 0); translate: 0 -28px; } to { clip-path: inset(0 0 -20px 0); translate: 0 0; } }
@keyframes bill-row { from { opacity: 0; translate: 0 6px; } }
@keyframes bill-lit { 0% { background-color: rgba(255, 210, 63, 0); box-shadow: 0 0 0 0 rgba(255, 210, 63, 0); }
  55% { background-color: var(--y); box-shadow: 0 0 0 6px rgba(255, 210, 63, .45); } 100% { background-color: var(--y); box-shadow: 0 0 0 0 rgba(255, 210, 63, 0); } }
@keyframes bill-stamp { 0% { opacity: 0; scale: 1.15; } 60% { opacity: 1; } 100% { opacity: 1; scale: 1; } }
@keyframes coin-drop { 0% { opacity: 0; transform: translateY(-70px); } 70% { opacity: 1; transform: translateY(5px); } 100% { opacity: 1; transform: none; } }
@keyframes coin-float { from { translate: 0 0; } to { translate: 0 -10px; } }

.bill__paper { animation: bill-print .55s cubic-bezier(.2, .8, .3, 1) .1s both; }
.bill__title, .bill__row, .bill__rule { animation: bill-row .22s ease both; }
.bill__title { animation-delay: .5s; }
.bill__row:nth-child(1) { animation-delay: .62s; }
.bill__row:nth-child(2) { animation-delay: .72s; }
.bill__row:nth-child(3) { animation-delay: .82s; }
.bill__row:nth-child(4) { animation-delay: .92s; }
.bill__rule { animation-delay: 1s; }
.bill__row:nth-child(6) { animation-delay: 1.08s; }
.bill__row:nth-child(7) { animation-delay: 1.16s; }
.bill__gift { animation: bill-lit .6s ease 1.2s both; }
.bill__stamp { animation: bill-stamp .28s cubic-bezier(.3, 1.6, .5, 1) 1.55s both; }
.art__coin--3 { animation: coin-drop .5s cubic-bezier(.3, .9, .4, 1) 1.75s both, coin-float 5.8s ease-in-out 2.6s infinite alternate; }
.art__coin--2 { animation: coin-drop .5s cubic-bezier(.3, .9, .4, 1) 1.85s both, coin-float 5.2s ease-in-out 2.9s infinite alternate; }
.art__coin--1 { animation: coin-drop .5s cubic-bezier(.3, .9, .4, 1) 1.95s both, coin-float 4.4s ease-in-out 2.5s infinite alternate; }
.art__coin--4 { animation: coin-drop .5s cubic-bezier(.3, .9, .4, 1) 2.05s both, coin-float 4.9s ease-in-out 3.2s infinite alternate; }

.hero { position: relative; }
.hero__in { position: relative; z-index: 1; }

/* ───────── screen 2 · one cart stage, the two widgets in sequence ───────── */
.goal-sec { background: var(--paper); border-top: 2px solid var(--ink); }
.goal-sec__in { padding-top: 72px; padding-bottom: 72px; }

/* narrow claim column | wide stage */
/* claim column (≤560px, the H2 at its 60px cap fills it) | cart column at a real drawer width: 480px frame + 8px for
   its shadow. The pair is centred in the shell, so the spare width splits evenly to both sides, not into one gap. */
.show { display: grid; grid-template-columns: minmax(0, 560px) 488px; column-gap: clamp(56px, 6vw, 96px); justify-content: center; align-items: center; }
.show__side { min-width: 0; container-type: inline-size; }
/* "$60 gets nothing." = 8.3 × font-size wide (Space Grotesk 700, −.03em) → sized from the column, one line each */
.goal-sec__title { font: 700 clamp(30px, calc((100cqi - 24px) / 8.6), 60px)/1.24 var(--display); letter-spacing: -.03em; }

/* the two steps: a label + one line each; the running step is ink + yellow bar, the other recedes */
.steps { display: grid; gap: 10px; margin: 36px 0 0; padding: 0; list-style: none; }
.step {
  display: grid; gap: 6px; width: 100%; padding: 14px 16px 15px 18px; text-align: left; cursor: pointer;
  background: transparent; border: 0; border-left: 4px solid var(--track); color: var(--muted);
  transition: color .25s, border-color .25s, background-color .25s;
}
.step__tag { font: 700 13px/1.2 var(--display); letter-spacing: .06em; text-transform: uppercase; }
.step__line { font: 400 16px/1.45 var(--body); }
.step.is-on { border-left-color: var(--ink); background: #fff; color: var(--ink); }
.step.is-on .step__tag { color: var(--ink); }
.step.is-on .step__tag::before { content: ""; display: inline-block; width: 9px; height: 9px; margin-right: 8px; background: var(--y); outline: 1.5px solid var(--ink); vertical-align: 1px; }
.step:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
@media (hover: hover) { .step:not(.is-on):hover { color: var(--ink); border-left-color: var(--ink); } }

/* the stage: a store cart in an ink frame with the offset yellow shadow (v6 frame) */
.stages { min-width: 0; width: 100%; max-width: 488px; }
.frame {
  position: relative; margin-right: 8px; /* room for the 8px shadow */
  background: #fff; border: 2px solid var(--ink); box-shadow: var(--shadow-lg); overflow: hidden;
}
.v11-js .frame { opacity: 0; }
.v11-js .frame.is-in { opacity: 1; animation: bf-in .25s ease; }

.stage { position: relative; padding: 20px 24px 28px; background: #fff; color: #1C1C1C; } /* a plain white store cart */
.cart { display: flex; flex-direction: column; transition: opacity .25s ease; }
.stage.is-reset .cart { opacity: 0; }

/* cart rows: the first is in the cart from the start; the added item and the gift line open their own row
   (grid-rows 0fr → 1fr, so the cart grows like a real one, no reserved gap) and slide in */
.cart__list { margin-top: 18px; border-top: 1px solid #E2E2DF; }
.cart__item { display: flex; align-items: center; gap: 14px; padding: 12px 0; border-bottom: 1px solid #E2E2DF; }
.cart__img { flex: none; width: 56px; height: 56px; border-radius: 4px; object-fit: cover; background: #E8E8E5; }
.cart__meta { flex: 1; min-width: 0; }
.cart__name { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font-size: 14px; font-weight: 600; line-height: 1.35; }
.cart__qty { margin-top: 2px; font-size: 13px; line-height: 1.35; color: #5F5F5F; }
.cart__price { display: flex; gap: 8px; font-size: 14px; font-weight: 600; white-space: nowrap; }
.cart__was { font-weight: 400; color: #33333380; }
.cart__tag { padding: 2px 6px; border-radius: 4px; background: rgba(51, 51, 51, .08); font-size: 12px; font-weight: 600; line-height: 1.3; }
.cart__foot { display: flex; flex-direction: column; gap: 14px; padding-top: 20px; }
.cart__row { display: flex; justify-content: space-between; font-size: 15px; }
.cart__sum { font-weight: 700; font-variant-numeric: tabular-nums; }
.cart__checkout {
  display: block; padding: 16px; border-radius: 8px; background: #1C1C1C; color: #fff;
  font-size: 16px; font-weight: 600; line-height: 1.2; text-align: center;
}
.cart__slot { display: grid; grid-template-rows: 1fr; }
.cart__slot-in { min-height: 0; overflow: hidden; }
.v11-js .cart__slot { grid-template-rows: 0fr; transition: grid-template-rows .35s cubic-bezier(.2, 1, .3, 1); }
.v11-js .cart__slot .cart__item { opacity: 0; transform: translateX(-18px); transition: opacity .2s ease, transform .2s ease; }
.v11-js .cart__slot.is-in { grid-template-rows: 1fr; }
.v11-js .cart__slot.is-in .cart__item { opacity: 1; transform: none; transition: opacity .3s ease .12s, transform .35s cubic-bezier(.2, 1, .3, 1) .12s; }
.cart__slot.is-in .cart__tag { animation: bfm-pop .3s cubic-bezier(.2, 1.6, .4, 1) .35s both; }
/* while JS measures the tallest state: no transitions */
.stage.is-measure .cart__slot, .stage.is-measure .cart__item { transition: none !important; }
/* the stage column keeps the height of the tallest state (set by JS), so the page below never moves while the cart grows */
.stages { align-self: start; }

/* --- AOV Milestone Bar, classic layout, basic colours ---
   Source: ProgressBar.scss:16-92 · LayoutProgress.js:66-118 · useLayoutProgress.js:99-117,276-305 ·
   progressCalculation.js:12-73 · getColors.js:716-731 · designSettingDetail.js:302-319 */
.mb { display: flex; flex-direction: column; align-items: center; width: 100%; margin: 0; padding: 8px 0; }
.mb__msg { margin-bottom: 24px; font-size: 16px; line-height: 1.4; text-align: center; color: #1C1C1C; }
.mb__msg b { font-weight: 700; }
.mb__stone { position: relative; display: flex; flex-direction: column; gap: 4px; width: 100%; }
.mb__track, .mb__fill { position: absolute; top: 0; left: 0; height: 6px; border-radius: 16px; background: #333333; }
.mb__track { opacity: .1; }
.mb__fill { width: 0; }
/* milestones sit on the full-width track: centred on their step, the last one flush right with its label right-aligned */
.mb__items { position: relative; width: 100%; height: 50px; transform: translateY(-11px); } /* barThickness/2 − iconSize */
.mb__item { position: absolute; top: 0; display: flex; flex-direction: column; align-items: center; gap: 4px; translate: -50% 0; }
.mb__item--end { align-items: flex-end; translate: -100% 0; }
.mb__icon {
  display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 32px; border: 2px solid rgba(28, 28, 28, .3);
  background: #fff; color: #1C1C1C;
}
.mb__icon svg { display: block; }
.mb__item.is-done .mb__icon { background: #333333; border-color: #333333; }
@keyframes mb-pop { 0% { scale: 1; } 45% { scale: 1.35; } 100% { scale: 1; } }
.mb__item.is-pop .mb__icon { animation: mb-pop .4s cubic-bezier(.3, 1.5, .5, 1); }
.mb__label { font-size: 13px; line-height: 1.4; white-space: nowrap; color: #1C1C1C; }

/* gift detail pill (ProgressBarGiftDetail.js:300-355; padding/radius = prototype, scss not in repo) */
.mb__detail {
  display: inline-flex; align-items: center; gap: 8px; margin-top: 14px; padding: 8px 14px;
  border-radius: 14px; background: rgba(51, 51, 51, .05); font-size: 13px; line-height: 1.35; color: #1C1C1C;
}
.mb__thumb { flex: none; width: 22px; height: 22px; overflow: hidden; border-radius: 50%; border: 1px solid #DDD; background: #fff; }
.mb__thumb img { width: 100%; height: 100%; object-fit: cover; }
.mb__dtitle b { font-weight: 700; }
.mb__see { flex: none; font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }


/* --- Gift popup, vertical list (GiftCampaignLayout.scss:200-364 · GiftCampaignItem.scss:29-296) --- */
/* step 2: the cart dims, the popup opens centred over the stage */
.dim { position: absolute; inset: 0; z-index: 3; background: rgba(17, 17, 17, .32); opacity: 0; pointer-events: none; transition: opacity .3s ease; }
.stage.is-pop .dim { opacity: 1; }
/* top is set by JS (--gp-top): centred on the stage, nudged so its edges never cut a line of text in half */
.gp {
  position: absolute; top: var(--gp-top, 50%); left: 50%; z-index: 4; width: calc(100% - 32px); max-width: 480px; overflow: hidden; border-radius: 8px;
  background: #fff; color: #1C1C1C;
  box-shadow:
    0 -2px 4px rgba(0, 0, 0, .08), 0 1.1px 1.1px rgba(0, 0, 0, .03), 0 2.8px 2.8px rgba(0, 0, 0, .04),
    0 5.7px 5.7px rgba(0, 0, 0, .05), 0 11.7px 11.7px rgba(0, 0, 0, .05), 0 32px 32px rgba(0, 0, 0, .08);
}
.gp__head { display: flex; flex-direction: column; gap: 6px; padding: 24px 24px 12px; }
.gp__top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.gp__title { font-size: 18px; font-weight: 600; line-height: 1.3; }
.gp__x { flex: none; }
.gp__desc { font-size: 14px; line-height: 1.45; color: #1C1C1CB3; }
.gp__body { display: flex; flex-direction: column; gap: 16px; padding: 12px 24px; }
.gp__card {
  display: flex; flex-direction: row-reverse; align-items: center; gap: 12px;
  padding: 10px 14px 10px 10px; border: 2px solid transparent; border-radius: 8px; background: #33333308;
}
.gp__card.is-on { border-color: #1C1C1C; background: #1C1C1C08; }
.gp__media { position: relative; flex: none; width: 64px; min-width: 64px; height: 64px; overflow: hidden; border-radius: 4px; background: #EDEDED; }
.gp__media img { width: 100%; height: 100%; object-fit: cover; }
.gp__qty {
  position: absolute; top: 0; right: 0; display: grid; place-items: center; width: 20px; height: 20px;
  border-radius: 4px; background: #1C1C1C; color: #fff; font-size: 12px; font-weight: 600; line-height: 1;
}
.gp__info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.gp__name { font-size: 14px; font-weight: 600; line-height: 1.35; }
.gp__price { display: flex; gap: 8px; max-width: 80%; font-size: 14px; }
.gp__now { font-weight: 600; color: #1C1C1C; }
.gp__was { color: #33333380; }
/* unticked: empty box, border #33333380 (AdvancedCheckbox.scss:1-9); ticked: solid + white check */
.gp__check {
  display: grid; place-items: center; flex: none; width: 16px; height: 16px;
  border-radius: 4px; border: 2px solid #33333380; background: transparent; transition: background-color .15s, border-color .15s;
}
.gp__check svg { opacity: 0; transition: opacity .15s; }
.gp__card { transition: border-color .15s, background-color .15s; }
.gp__card.is-on .gp__check { border-color: #1C1C1C; background: #1C1C1C; }
.gp__card.is-on .gp__check svg { opacity: 1; }
.gp__foot { display: flex; flex-direction: column; gap: 16px; padding: 12px 24px 24px; }
.gp__count { font-size: 14px; line-height: 20px; }
/* button: dim until the gift count is met (rgba(0,0,0,.08), opacity .4 — app behaviour), solid once ticked */
.gp__btn {
  display: block; padding: 16px; border-radius: 8px; background: rgba(0, 0, 0, .08); color: #1C1C1C; opacity: .4;
  font-size: 16px; font-weight: 600; line-height: 1.2; text-align: center;
  transition: background-color .2s, color .2s, opacity .2s, transform .1s;
}
.gp__btn.is-ready { background: #1C1C1C; color: #fff; opacity: 1; }
.gp__btn.is-press { transform: scale(.97); background: #000; }
.gp__cont { font-size: 13px; text-align: center; }

/* motion: the fill follows the cart value frame by frame (source: transition width .1s); popup pops in .3s */
.mb__fill { transition: width .1s linear; }
.gp { transform: translate(-50%, var(--gp-ty, -50%)); }
.v11-js .gp { opacity: 0; transform: translate(-50%, var(--gp-ty, -50%)) translateY(14px) scale(.9); visibility: hidden; }
.v11-js .stage.is-pop .gp { opacity: 1; transform: translate(-50%, var(--gp-ty, -50%)); visibility: visible;
  transition: opacity .2s ease, transform .3s cubic-bezier(.2, 1.4, .4, 1), visibility 0s; }
.v11-js .stage.is-close .gp { opacity: 0; transform: translate(-50%, var(--gp-ty, -50%)) scale(.94); visibility: visible; transition: opacity .22s ease, transform .22s ease; }

/* coins burst from the gift milestone at $75, then fade (decor layer over the stage) */
.burst { position: absolute; z-index: 2; width: 0; height: 0; pointer-events: none; }
.burst i { position: absolute; left: -9px; top: -9px; width: 18px; height: 18px; background: center / contain no-repeat; opacity: 0; }
@keyframes coin-burst { 0% { opacity: 0; transform: translate(0, 0) scale(.4); } 20% { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--x), var(--y)) scale(1) rotate(var(--rot)); } }
.burst.is-on i { animation: coin-burst .8s cubic-bezier(.2, .8, .3, 1) both; }

/* reduced motion: no sequence — the two moments as still frames, stacked (step 1 cart at $60 · step 2 popup) */
.stages.is-still { display: grid; gap: 28px; }
.frame__cap { display: none; }
.stages.is-still .frame__cap { display: block; padding: 10px 16px; border-bottom: 2px solid var(--ink); font: 700 13px/1.2 var(--display); letter-spacing: .06em; text-transform: uppercase; }

.goal-sec__note, .keep { max-width: calc(100% - 8px); } /* as wide as the cart frame, not its shadow */
/* what you keep: two bars on one scale — the gift cart keeps more than the discount cart */
.keep { margin-top: 24px; }
.keep__title { margin-bottom: 10px; font: 500 12px/1 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.keep__row { display: grid; grid-template-columns: 150px minmax(0, 1fr) 40px; align-items: center; gap: 12px; margin-top: 8px; font: 400 14px/1.3 var(--body); color: var(--ink); }
.keep__bar { height: 14px; }
.keep__bar i { display: block; height: 100%; background: #D3D1CB; }
.keep__row--gift .keep__bar i { background: var(--y); outline: 1.5px solid var(--ink); outline-offset: -1.5px; }
.keep__val { font-weight: 700; text-align: right; }
.goal-sec__note { margin-top: 12px; font: 400 13px/1.45 var(--body); color: var(--muted); }
.goal-sec__tally { margin-top: 4px; font: 400 13px/1.45 var(--body); color: var(--muted); text-wrap: pretty; }
/* the two outcomes sit one per line, never splitting "$6 gift" onto its own line */
.goal-sec__tally .nowrap-line { white-space: nowrap; }

/* ───────── screen 3 · end ───────── */
.end { background: var(--ink); color: #fff; border-top: 1.5px dashed rgba(255, 255, 255, .35); }
.end__in {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 40px 56px; flex-wrap: wrap;
  padding-top: 88px; padding-bottom: 88px;
}
.end__title { font: 700 clamp(32px, 4.6vw, 64px)/1.24 var(--display); letter-spacing: -.03em; }
.cta--onink { background: var(--y); color: var(--ink); border-color: var(--y); box-shadow: 4px 4px 0 #fff; }
.cta--onink:active { box-shadow: 2px 2px 0 #fff; }
@media (hover: hover) { .cta--onink:hover { box-shadow: 2px 2px 0 #fff; } }
.cta--onink:focus-visible { outline-color: var(--y); }

.foot { border-top: 1.5px dashed rgba(255, 255, 255, .35); }
.foot__in { padding-top: 22px; padding-bottom: 26px; font: 400 13px/1.5 var(--body); color: rgba(255, 255, 255, .72); }

/* ───────── mobile dock ───────── */
.dock { display: none; }

/* ───────── responsive ───────── */
/* Desktop: the hero runs exactly to the fold (no strip of the next section), content centred in it. */
@media (min-width: 1024px) {
  .hero { display: grid; align-items: center; min-height: min(calc(100svh - var(--bars)), 1000px); }
}

@media (min-width: 1600px) {
  /* v11 · layout eases out on wide screens (layout, not decor): shell 1320 → 1440 by 1920, the receipt 360 → 420
     and its box 480 → 560 with it; the coins are % of that box, so they grow by the same clamp. */
  :root { --shell: clamp(1320px, 75vw, 1440px); }
  .art { max-width: clamp(480px, 30vw, 560px); }
  .bill { max-width: clamp(360px, 22vw, 420px); }
}

/* Below 1024: one column — copy and form first, the illustration under the form. */
@media (max-width: 1023px) {
  .hero__in { grid-template-columns: minmax(0, 1fr); }
  .hero__title { font-size: clamp(30px, 6.4vw, 52px); }
  .hero__title .hero__l1 { padding-bottom: 0; }
  /* the receipt sits under the countdown, at most 320px wide; coins scale with the box (% sizes) */
  .art { justify-self: center; max-width: 420px; margin-top: 32px; padding: 40px 44px 44px 50px; }
  .bill { max-width: 320px; }
  /* screen 2: steps above the stage, the stage full shell width */
  .show { grid-template-columns: minmax(0, 1fr); row-gap: 28px; justify-content: stretch; }
  .goal-sec__title { font-size: clamp(28px, 5.4vw, 48px); }
  .steps { grid-template-columns: 1fr 1fr; margin-top: 24px; }
}

@media (max-width: 960px) {
  :root { --gutter: 28px; }
}

@media (max-width: 720px) {
  :root { --gutter: 16px; }
  body { font-size: 15px; }

  .ticker__track { padding: 9px 0; font-size: 14px; }
  .ticker__track span::after { margin: 0 20px; }

  .nav__in { height: 52px; }
  .nav__logo { width: 84px; }
  .nav__install { padding: 6px 10px; font-size: 13px; }

  .hero__in { padding-top: 8px; padding-bottom: 44px; }
  .pair { font-size: 12px; }
  .pair__a, .pair__b { gap: 7px; padding: 9px 12px; }
  .pair__a { padding-right: 18px; }
  .pair__b { padding-left: 18px; }
  .pair__seam b { width: 24px; height: 24px; font-size: 15px; }
  .pair .glyph { width: 17px; height: 17px; }

  .hero__title { margin-top: 14px; font-size: clamp(28px, 8.6vw, 44px); line-height: 1.25; }
  .hero__lead { margin-top: 12px; font-size: 16px; line-height: 1.5; }

  /* phone: field on top, button full width under it; the bar keeps its shadow */
  .run-form { flex-direction: column; margin-top: 16px; }
  .field { flex: none; height: 50px; border-bottom: 2px solid var(--ink); }
  .run-form .cta { width: 100%; height: 52px; }
  .hero__fine { margin-top: 14px; font-size: 13px; }
  .count { margin-top: 14px; gap: 8px; }
  .count__label { white-space: nowrap; }
  .art { max-width: 360px; margin-top: 28px; padding: 30px 36px 34px 32px; }
  .art__coin--2 { right: -3%; width: 13%; }
  .bill__paper { --tooth: 12px; --edge: 6px; padding: calc(var(--edge) + 16px) 18px calc(var(--edge) + 18px); }
  .bill__title { padding-bottom: 11px; font-size: 22px; }
  .bill__rows { gap: 9px; margin-top: 13px; margin-bottom: 16px; }
  .bill__row { gap: 12px; font-size: 14px; }
  .bill__item { gap: 10px; }
  .bill__row--total { font-size: 16px; }
  .bill__row--net { font-size: 13px; }
  .bill__gift small { font-size: 12px; }
  .bill__stamp { font-size: 12px; padding: 3px 10px; }

  .goal-sec__in { padding-top: 64px; padding-bottom: 64px; }
  .goal-sec__title { font-size: clamp(26px, 8.5vw, 40px); }
  .steps { grid-template-columns: minmax(0, 1fr); gap: 6px; margin-top: 20px; }
  .step { padding: 10px 12px 11px 14px; gap: 4px; }
  .step__line { font-size: 15px; }
  .show { row-gap: 22px; }
  .stage { padding: 16px 14px 20px; }
  .gp { width: calc(100% - 24px); max-width: 390px; }
  .gp__head { padding: 18px 18px 10px; }
  .gp__body { padding: 10px 18px; }
  .gp__foot { padding: 10px 18px 18px; gap: 12px; }
  .gp__title { font-size: 16px; }
  /* the message is 2 lines at $60 and 1 line at $75: keep 2 lines of room so the cart never jumps */
  .mb__msg { min-height: 2.8em; font-size: 15px; margin-bottom: 18px; }

  .end__in { padding-top: 64px; padding-bottom: 56px; gap: 32px; }
  .end__in .cta { width: calc(100% - 4px); }
  .end__title { font-size: clamp(28px, 8.6vw, 44px); text-wrap: balance; }

  .dock {
    display: block; position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
    padding: 12px 20px calc(14px + env(safe-area-inset-bottom)) 16px;
    background: #fff; border-top: 2px solid var(--ink);
    transform: translateY(110%); transition: transform .2s ease;
  }
  .dock.is-on { transform: none; }
  .dock .cta { width: 100%; height: 52px; }
}

@media (max-width: 360px) {
  .count { flex-wrap: wrap; }
}

@media (prefers-reduced-motion: reduce) {
  .ticker__track { animation: none; }
  .pair, .run-form, .art__coin { animation: none; }
  .bill__paper, .bill__title, .bill__row, .bill__rule, .bill__gift, .bill__stamp { animation: none; }
  .v11-js .frame, .v11-js .frame.is-in { opacity: 1; animation: none; }
  .mb__fill, .cart, .dim, .step, .v11-js .cart__slot, .v11-js .cart__slot .cart__item, .gp__btn, .gp__check, .gp__card { transition: none; }
  .v11-js .stage.is-pop .gp { transition: none; }
  .mb__item.is-pop .mb__icon, .cart__slot.is-in .cart__tag { animation: none; }
  .cta, .dock, .run-form, .run-form .cta { transition: none; }
}

/* ───────── v12 · hero = the cart stage + one try box (base: shared note 21/10, then Vũ feedback 22/10) ───────── */
/* Left column: chip → H1 → lead → try box share ONE right edge (--col). H1 line 1 "Black Friday ads cost" is
   9.7 × font-size wide (Space Grotesk, measured 1280/1440/2000) → font = col / 9.8 lands it ≤6px inside the box edge. */
.hero__in { align-items: start; }
.hero__copy { --col: min(560px, 100cqi - 8px); } /* cqi resolves at the use site = the copy column */
.hero__title { font-size: calc(var(--col) / 9.8); }
.hero__lead { max-width: var(--col); margin-top: 20px; }
.pvA { max-width: var(--col); margin: 28px 8px 0 0; padding: 24px 24px 24px; border: 2px solid var(--ink); background: #fff; box-shadow: var(--shadow-lg); }
.pvA .pv__title { font: 700 22px/1.25 var(--display); letter-spacing: -.01em; }
.pvA .pv__intro { margin: 8px 0 18px; font: 400 15px/1.5 var(--body); color: var(--num); text-wrap: pretty; }
/* The box carries the shadow, so the joined bar inside never moves or grows a shadow of its own:
   hover / press only deepen the button (#000), as in every other joined bar. */
.pvA .run-form { margin: 0; box-shadow: none; animation: none; }
.pvA .run-form:has(.cta:hover):not(:has(.cta:active)), .pvA .run-form:has(.cta:active) { translate: none; box-shadow: none; }

/* Right column: the cart, top-aligned with the chip. Countdown lives in the nav (same as bfcm-cd). */
.art--stage { max-width: 600px; padding: 0; }
.nav__end { display: flex; align-items: center; gap: 20px; }
.nav .count { margin: 0; }
.art--stage .stages { position: relative; z-index: 1; }
/* Coins live behind the frame (z 0 < stages z 1): % peeks out of the lower-left corner, $ out of the upper-right.
   They can never cover the cart, the popup or Checkout; both stay inside the viewport (no sideways scroll). */
/* Desktop: the frame starts 40px under the chip row so the $ coin can rise above its top-right corner.
   Coins in px from the art top: padding 40 + frame 505 → % tucks under the frame's last 60px, $ peeks over its top edge. */
@media (min-width: 1024px) { .art--stage { padding-top: 40px; } }
.art--stage .art__coin--1 { left: -15%; top: 483px; z-index: 0; }
.art--stage .art__coin--2 { right: -2%; top: -26px; z-index: 0; }

/* Background: a print halftone over the right half, from right under the ticker (behind the nav) to the hero's
   bottom. Dots are an SVG circle (crisp at any DPR; a CSS radial-gradient dot blurs). The left edge starts 32px past
   the try box and fades in over 128px, so the button never sits on dots; the bottom fades too. Static, ink only. ≥1024.
   --box-x = the try box's right edge incl. shadow: shell inner width W, copy column = (W − 40) × 3/5, box = --col + 8. */
@media (min-width: 1024px) {
  .nav { position: relative; z-index: 2; }
  .nav__install:not(:hover) { background: #fff; } /* the halftone reaches behind the nav: keep the button solid */
  .nav .count__label { padding: 5px 6px; background: #fff; }
  .hero { --colv: min(560px, (min(var(--shell), 100% - var(--gutter) * 2) - 40px) * .6 - 8px); }
  .hero::before {
    --w: min(var(--shell), 100% - var(--gutter) * 2);
    --box-x: calc((100% - var(--w)) / 2 + var(--colv) + 8px);
    content: ""; position: absolute; top: -68px; right: 0; bottom: 0; left: 0; z-index: 0; pointer-events: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='1.4' fill='%23111111' fill-opacity='.13'/%3E%3C/svg%3E");
    background-size: 16px 16px; background-position: center;
    -webkit-mask-image: linear-gradient(to right, transparent calc(var(--box-x) + 32px), #000 calc(var(--box-x) + 160px)),
                        linear-gradient(to bottom, #000 72%, transparent 100%);
    -webkit-mask-composite: source-in;
            mask-image: linear-gradient(to right, transparent calc(var(--box-x) + 32px), #000 calc(var(--box-x) + 160px)),
                        linear-gradient(to bottom, #000 72%, transparent 100%);
            mask-composite: intersect;
  }
}
@media (min-width: 1600px) {
  .hero__copy { --col: min(clamp(560px, 32vw, 640px), 100cqi - 8px); }
  .hero { --colv: min(clamp(560px, 32vw, 640px), (min(var(--shell), 100% - var(--gutter) * 2) - 40px) * .6 - 8px); }
}

/* End: flat yellow button, no offset decor; no coupon footer (code line removed 22/10). */
.end { border-top: 0; }
.cta--onink, .cta--onink:active { box-shadow: none; }
@media (hover: hover) { .cta--onink:hover { transform: none; box-shadow: none; background: #fff; border-color: #fff; } }

@media (min-width: 1024px) and (max-width: 1199px) {
  .art--stage .art__coin--1 { left: -8%; } /* columns sit closer: keep clear of the try box's shadow */
}
@media (max-width: 1023px) {
  .art--stage { margin-top: 36px; }
}
@media (max-width: 720px) {
  .pvA { margin-top: 20px; padding: 18px 16px 16px; }
  .pvA .pv__title { font-size: 19px; }
  .pvA .pv__intro { font-size: 14px; margin-bottom: 14px; }
  .art--stage .art__coin--1 { display: none; } /* no room outside the frame on a phone — a 10px sliver reads as a glitch */
  .art--stage .art__coin--2 { right: -1%; top: -22px; }
  .nav__in { gap: 8px; }
  .nav__end { gap: 8px; }
  .nav__install { white-space: nowrap; }
  .nav .count__label { display: none; }
  .nav .count__cells { gap: 3px; }
  .nav .count__cell { padding: 4px 4px 3px; }
  .nav .count__cell b { font-size: 13px; }
  .nav .count__cell i { font-size: 10px; }
}
@media (max-width: 359px) { .nav .count__cell:last-child { display: none; } } /* 320: drop the seconds so logo + countdown + Install fit one row */

/* Try box: badge + 3-step line kept (Vũ 22/10 "giữ lại cả cái badge lẫn cái dòng hướng dẫn"). */
.pvA .pv__tag { display: inline-block; margin-bottom: 12px; padding: 6px 8px; background: var(--ink); color: var(--y); font: 700 12px/1 var(--mono); letter-spacing: .12em; text-transform: uppercase; }
.pvA .pv__flow { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin-top: 14px; font: 400 13px/1.3 var(--body); color: var(--num); }
.pvA .pv__flow i { font-style: normal; color: #b8960b; }
.pvA .run-status:not(:empty) + .pv__flow { margin-top: 10px; }
/* Short desktops (≤860 tall): tighter rhythm so the try box + its button stay in the first screen. */
@media (min-width: 1024px) and (max-height: 860px) {
  .hero__in { padding-top: 16px; }
  .hero__title { margin-top: 16px; }
  .hero__lead { margin-top: 14px; }
  .pvA { margin-top: 20px; padding: 18px 24px; }
  .pvA .pv__tag { margin-bottom: 8px; }
  .pvA .pv__intro { margin-bottom: 14px; }
  .pvA .pv__flow { margin-top: 10px; }
}

/* chip pair removed (Vũ 22/10) — the H1 opens the column */
.hero__title, .hero__title[class] { margin-top: 0; }
