/* BFCM landing — Cart Drawer (bfcm-cd), a copy of the Free Gift v11 frame (hero, ticker, keep bars, end) with screen 2
   rebuilt as one AOV Cart Drawer: announcement → reward bar → upsell (production v2 styled, style 1, default colours;
   spec cd-real-ui-spec.md §2/§3/§4.2/§4.4). Page style unchanged from v11: ink + white/paper, yellow only for emphasis,
   red only for the error mark. 2px ink borders, square corners, offset yellow shadow with an ink rim. The widgets inside
   the drawer carry production colours only — no BFCM skin. */

: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. The widest line is line 2, "Give them one more thing to add." = 15.12 × font-size
   in Space Grotesk (Arial 14.93) + .2em of yellow padding → font = (column − 28px) / 15.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) / 15.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; }

/* ── hero illustration: one focal point, the cart drawer (fixed height, see "drawer shell") + 4 coins BEHIND it,
   peeking out at its edges only — never over the widget. The frame keeps the whole column (464px at 1280–1440); its
   8px yellow shadow spills into the gutter (margin-right −8px). */
.art { position: relative; justify-self: end; width: calc(100% + 8px); max-width: 488px; margin-right: -8px; }

/* ── receipts (screen 2): a white sheet with zig-zag top/bottom edges (mask on .bill__paper); the ink rim and the
   offset shadow are drop-shadows on .bill (a filter on the masked element itself would be cut by the mask). */
.bill { position: relative; width: 100%;
  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 */
/* all four sit behind the drawer (z 0 < frame z 1): two sharp ones half out at the lower-left and upper-right edges,
   two small soft ones peeking from the left and right edges */
/* the coins live in the free strip between the copy column and the drawer (≥64px at 1280–1440), whole, never under or
   over the drawer and never cut by the viewport; coin-4 has no free spot left → off. Below 1100 (drawer under the
   form, flush left) there is no strip → all off. */
/* staggered, not a column: big low and far from the drawer, mid-size high and closer, small one hugging the edge */
/* coin-1 (%) is the big one (100px) and follows the upsell band (placed by JS, partly behind the drawer); the two small
   ones stay high in the strip, clear of the band, the tag and its arrow */
/* r5: at most 3 coins, three clear sizes, all WHOLE in the free strip between the copy column and the drawer — none
   under or peeking past the drawer. 1100–1599 (strip 84–96px): two coins, % 60 low + small 36 high, different x.
   ≥1600 (strip ~180px): % 100 low · $ 60 high · small 36 in between, staggered. */
.art__coin--1 { --r: -8deg; left: -74px; top: 60%; width: 60px; z-index: 0; }
.art__coin--2 { display: none; }
.art__coin--3 { --r: 6deg; left: -42px; top: 12%; width: 36px; z-index: 0; }
.art__coin--4 { display: none; }
.art.is-debug .art__coin { outline: 2px solid red; outline-offset: -1px; }

/* coins (hero): drop into place once on load, then float out of phase.
   receipts (screen 2), once when scrolled to (.vs.is-in, bfcm-cd.js §3b): the left one fades up → the right one prints
   out of the slot (.55s) → its rows one by one → the gift row lights up → the stamp lands; "You keep" counts up (JS). */
@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; } }

.cd-js .vs .bill { opacity: 0; }
.vs.is-in .bill { opacity: 1; }
.vs.is-in .bill--before { animation: bill-row .4s ease both; }
.vs.is-in .bill--after .bill__paper { animation: bill-print .55s cubic-bezier(.2, .8, .3, 1) .45s both; }
.vs.is-in .bill--after .bill__title, .vs.is-in .bill--after .bill__row, .vs.is-in .bill--after .bill__rule { animation: bill-row .22s ease both; }
.vs.is-in .bill--after .bill__title { animation-delay: .85s; }
.vs.is-in .bill--after .bill__row:nth-child(1) { animation-delay: .97s; }
.vs.is-in .bill--after .bill__row:nth-child(2) { animation-delay: 1.07s; }
.vs.is-in .bill--after .bill__row:nth-child(3) { animation-delay: 1.17s; }
.vs.is-in .bill--after .bill__row:nth-child(4) { animation-delay: 1.27s; }
.vs.is-in .bill--after .bill__rule { animation-delay: 1.35s; }
.vs.is-in .bill--after .bill__row:nth-child(6) { animation-delay: 1.43s; }
.vs.is-in .bill--after .bill__row:nth-child(7) { animation-delay: 1.51s; }
.vs.is-in .bill--after .bill__gift { animation: bill-lit .6s ease 1.55s both; }
.vs.is-in .bill--after .bill__stamp { animation: bill-stamp .28s cubic-bezier(.3, 1.6, .5, 1) 2.3s 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 · two carts, before / after (two receipts) ───────── */
.goal-sec { background: var(--paper); border-top: 2px solid var(--ink); }
.goal-sec__in { padding-top: 72px; padding-bottom: 72px; }
/* one centred block: H2 · the two receipts · the note, all on its left edge */
.cmp { max-width: 880px; margin-inline: auto; container-type: inline-size; }
/* the widest line is line 2, "One upsell gets two rewards." = 13.11 × font-size (Space Grotesk 700, −.03em; Arial 13.0)
   + .2em of yellow padding → sized from the block, one line each, capped at 60px */
.goal-sec__title { font: 700 clamp(30px, calc((100cqi - 24px) / 13.6), 60px)/1.24 var(--display); letter-spacing: -.03em; text-wrap: balance; }
/* the left receipt recedes (narrower, grey rim + grey shadow, muted), the right one leads (yellow shadow, stamp);
   both start on the same top line */
.vs { display: grid; grid-template-columns: minmax(0, 340px) minmax(0, 420px); justify-content: space-between; align-items: start; gap: 40px; margin-top: 40px; }
.bill--before { filter: drop-shadow(1.5px 0 0 var(--muted)) drop-shadow(-1.5px 0 0 var(--muted)) drop-shadow(0 1.5px 0 var(--muted)) drop-shadow(0 -1.5px 0 var(--muted))
          drop-shadow(6px 6px 0 var(--track)); }
.bill--before .bill__paper { color: var(--num); }
.bill--before .bill__title { font-size: 22px; border-bottom-color: var(--muted); }
.bill--before .bill__thumb { border-color: var(--muted); }
.bill--before .bill__thumb--icon { color: var(--num); }
.bill--before .bill__rule { border-top-color: var(--muted); }
/* "You keep": the line each receipt ends on — the amount is the answer, so it is the largest number on the paper */
.bill__row--keep { align-items: center; margin-top: 2px; font-size: 18px; }
.bill__keep { padding: 2px 8px; margin-right: -8px; font: 700 28px/1.1 var(--display); letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.bill--before .bill__keep { background: #E4E2DC; color: var(--num); }
.bill--after .bill__keep { background: var(--y); color: var(--ink); }

/* the stage: one AOV Cart Drawer in an ink frame with the offset yellow shadow (v6 frame). The drawer's own blocks run
   edge to edge inside the frame (announcement, upsell band), like the real drawer. */
/* The drawer: fixed height like a real one; header + announcement + reward bar pinned on top, footer pinned at the
   bottom, the body (items + upsell band) scrolls inside — JS rests it on a row edge.
   Shell = Boxed (floating, radius 24) in the landing's frame: 2px ink rim + offset yellow shadow, both at r24. */
.frame {
  position: relative; z-index: 1; height: var(--cd-h, 596px); margin-right: 8px; /* room for the 8px shadow */
  container-type: inline-size;
  background: #fff; border: 2px solid var(--ink); border-radius: 24px; overflow: hidden;
  /* r5: the offset shadow is ink, not yellow — the yellow checkout slab sits on the bottom edge and a yellow shadow
     fused with it, so the lower corner read as broken. Same 8px offset, same r24. */
  box-shadow: 8px 8px 0 var(--ink);
}
.stage { position: relative; height: 100%; background: #fff; }

/* ── Boxed (cart-drawer-templates.md §4) in the BFCM skin ──
   knobs: ink #111 · surface #fff · footer #111 / on-footer #fff · announcement #111 / #fff · action (checkout) #FFD23F
   on #111 · divider + card border #e5e5e5 · progress fill #111 / track #e5e5e5 · upsell Add #FFD23F glyph #111 ·
   footer chip #2a2a2a · muted #6e6e6e. Font Jost (Boxed googleFonts). Icons: tabler-style strokes, 1.5. */
.cd {
  --cd-ink: #111111; --cd-line: #e5e5e5; --cd-muted: #6e6e6e; --cd-y: #FFD23F;
  display: flex; flex-direction: column; height: 100%; font: 400 14px/1.4 "Jost", var(--body); color: var(--cd-ink);
  font-variant-numeric: tabular-nums; transition: opacity .25s ease;
}
.cd svg { fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.stage.is-reset .cd { opacity: 0; }
.cd p { margin: 0; }
.cd > * { flex: none; }
.cd > .cd__body { flex: 1 1 auto; min-height: 0; overflow: hidden; }
.cd__tail { height: 0; } /* set by JS so the scroll can rest on a row edge */

/* header · HeaderStyle1 (Boxed id 2): height 64, title 24/600 lh 37 left at 20, rule under, ring close 32 at 16/16 */
.cd__head { position: relative; display: flex; align-items: center; height: 64px; padding: 0 64px 0 20px; border-bottom: 1px solid var(--cd-line); }
.cd__title { font-size: 24px; font-weight: 600; line-height: 37px; }
.cd__x { position: absolute; top: 16px; right: 16px; display: grid; place-items: center; width: 32px; height: 32px; border: 1px solid var(--cd-ink); border-radius: 50%; }
.cd__x svg { display: block; }

/* line items · CardStyle3: each line framed (padding 12, 1px border, r8), image 88 r4, gap 24, info min-h 84
   space-between, name 16/500, bottom row price 16/600 left + square stepper r4 right; row gap 12, no dividers */
.cd__list { padding: 16px 20px 0; }
.cd__item { display: flex; align-items: stretch; gap: 24px; padding: 12px; border: 1px solid var(--cd-line); border-radius: 8px; background: #fff; }
.cd__slot .cd__item { margin-top: 12px; }
.cd__img { flex: none; width: 88px; height: 88px; border-radius: 4px; object-fit: cover; background: #F4F4F4; }
.cd__meta { flex: 1; min-width: 0; min-height: 84px; display: flex; flex-direction: column; justify-content: space-between; gap: 8px; }
.cd__name { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font-size: 16px; font-weight: 500; line-height: 23px; }
.cd__tag { padding: 1px 8px; border-radius: 4px; background: var(--cd-y); color: var(--cd-ink); font-size: 12px; font-weight: 500; line-height: 18px; }
.cd__bot { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.cd__price { font-size: 16px; font-weight: 600; line-height: 20px; white-space: nowrap; }
.cd__was { margin-left: 4px; font-size: 12px; font-weight: 400; color: var(--cd-muted); }
.cd__qty { display: inline-flex; align-items: center; height: 32px; border: 1px solid var(--cd-line); border-radius: 4px; font-size: 14px; }
.cd__qty i { display: grid; place-items: center; width: 30px; height: 100%; }
.cd__qty svg { display: block; }
.cd__qty b { min-width: 20px; font-weight: 500; text-align: center; }

/* footer · FooterStyle3: solid #111, padding-top 20, gap 12; big subtotal (label 16/400, price 24/500) + three round
   36 utility buttons (#2a2a2a, white 20 glyphs, gap 12); full-bleed checkout slab h64 r0, 16/700 + arrow 18, top rule */
.cd__foot { display: flex; flex-direction: column; gap: 12px; padding-top: 20px; background: var(--cd-ink); color: #fff; }
.cd__sumrow { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 0 20px; }
.cd__sumblock { display: flex; flex-direction: column; }
.cd__sumlabel { font-size: 16px; font-weight: 400; line-height: 23px; }
.cd__sum { font-size: 24px; font-weight: 500; line-height: 32px; }
.cd__chips { display: flex; gap: 12px; }
.cd__chips i { display: grid; place-items: center; width: 36px; height: 36px; border-radius: 50%; background: #2a2a2a; color: #fff; }
.cd__chips svg { display: block; }
.cd__checkout {
  display: flex; align-items: center; justify-content: center; gap: 8px; height: var(--cd-co-h, 64px);
  background: var(--cd-y); color: var(--cd-ink); box-shadow: inset 0 1px 0 #070707;
  font-size: 16px; font-weight: 700; line-height: 1;
}
.cd__checkout svg { display: block; }

/* added rows (upsell item, gift): each opens its own row (grid-rows 0fr → 1fr) and slides in */
.cd__slot { display: grid; grid-template-rows: 1fr; }
.cd__slot-in { min-height: 0; overflow: hidden; }
.cd-js .cd__slot { grid-template-rows: 0fr; transition: grid-template-rows .35s cubic-bezier(.2, 1, .3, 1); }
.cd-js .cd__slot .cd__item { opacity: 0; transform: translateX(-18px); transition: opacity .2s ease, transform .2s ease; }
.cd-js .cd__slot.is-in { grid-template-rows: 1fr; }
.cd-js .cd__slot.is-in .cd__item { opacity: 1; transform: none; transition: opacity .3s ease .12s, transform .35s cubic-bezier(.2, 1, .3, 1) .12s; }
.cd__slot.is-in .cd__tag { animation: bfm-pop .3s cubic-bezier(.2, 1.6, .4, 1) .35s both; }
.stage.is-measure *, .stage.is-measure *::before { transition: none !important; animation: none !important; }

/* announcement · flat band (Boxed G4: no gradient), #111 / #fff, 14/400 ls .56, padding 12 4; carousel arrows both sides */
.ann { position: relative; width: 100%; padding: 12px 4px; background: var(--cd-ink); color: #fff; }
.ann__view { overflow: hidden; margin: 0 40px; }
.ann__track { display: flex; transition: transform .5s cubic-bezier(.4, 0, .2, 1); }
.ann__slide { flex: 0 0 100%; text-align: center; font-size: 14px; font-weight: 400; letter-spacing: .56px; line-height: 20px; }
.ann__arrow { position: absolute; top: 50%; display: grid; place-items: center; width: 32px; height: 32px; transform: translateY(-50%); transition: opacity .15s ease, transform .15s ease; }
.ann__arrow svg { display: block; }
.ann__arrow--prev { left: 8px; }
.ann__arrow--next { right: 8px; }
.ann__arrow.is-press { opacity: .6; transform: translateY(-50%) scale(.86); }

/* rewards · RewardMultiStyle2: message above 14/500 centred; one segment per goal (flex row gap 8, h6 r4, track
   #e5e5e5, fill #111, the active one partly filled); label under each 12/500 centred, reached ink / unreached muted;
   padding 16 20 0. No checkpoints, no ticks. */
.rb { display: flex; flex-direction: column; gap: 8px; width: 100%; padding: 16px 20px 0; background: #fff; }
.rb__msg { font-size: 14px; font-weight: 500; line-height: 20px; text-align: center; }
/* the longest message ("Congratulations! …" = 338px at 14/500 Jost) needs a 378px frame: narrower → keep 2 lines of
   room through the whole loop so the reward bar never changes height */
@container (max-width: 377.5px) { .rb__msg { min-height: 40px; } }
.rb__segs { display: flex; gap: 8px; align-items: flex-start; }
.rb__seg { flex: 1 0 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 4px; }
.rb__bar { position: relative; width: 100%; height: 6px; border-radius: 4px; background: var(--cd-line); overflow: hidden; }
.rb__fill { position: absolute; inset: 0 auto 0 0; width: 0; border-radius: 4px; background: var(--cd-ink); transition: width .3s; }
.rb__label { font-size: 12px; font-weight: 500; line-height: 1.4; text-align: center; color: var(--cd-muted); }
.rb__seg.is-done .rb__label { color: var(--cd-ink); }
/* reaching a goal: the label pops once (scale only) · step 2: the next segment breathes twice (height only) */
@keyframes rb-pop { 0% { scale: 1; } 45% { scale: 1.18; } 100% { scale: 1; } }
.rb__seg.is-pop .rb__label { animation: rb-pop .4s cubic-bezier(.3, 1.5, .5, 1); }
@keyframes rb-next { 0%, 100% { scale: 1 1; } 50% { scale: 1 1.7; } }
.rb__seg.is-next .rb__bar { animation: rb-next .7s ease-in-out 2; }

/* upsell · Boxed card (UpsellStyle2): band #fff padding 20 0, heading 16/600 + page arrows; card full width, padding 16,
   1px border r4, gap 16, thumb 72 r4, name 14/500, price 14/400; Add = round 36 (#FFD23F, cart glyph 18 #111, 1.75).
   One card per page (the second sits on the next page); one card left = no arrows. */
.up { display: flex; flex-direction: column; gap: 12px; width: 100%; padding: var(--up-pad, 20px) 0; background: #fff; }
.up__head { display: flex; align-items: center; gap: 8px; padding: 0 20px; }
.up__title { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 16px; font-weight: 600; line-height: 23px; }
.up__arrows { display: flex; gap: 8px; margin-inline-start: auto; }
.up__arrow { display: grid; place-items: center; width: 24px; height: 24px; }
.up__arrow svg { display: block; }
.up.is-one .up__arrows { display: none; }
.up__track { overflow: hidden; padding: 0 20px; }
.up__rail { display: flex; gap: 20px; }
.up__card {
  flex: 0 0 100%; display: flex; align-items: center; gap: 16px; min-width: 0; padding: 16px;
  border: 1px solid var(--cd-line); border-radius: 4px; background: #fff; transition: opacity .25s ease;
}
.up__card.is-out { opacity: 0; }
.up__card.is-gone { display: none; }
.up__thumb { flex: none; width: 72px; height: 72px; border-radius: 4px; object-fit: cover; }
.up__row { flex: 1; min-width: 0; display: flex; align-items: center; gap: 16px; }
.up__info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.up__name { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 14px; font-weight: 500; line-height: 20px; }
.up__price { font-size: 14px; font-weight: 400; line-height: 20px; }
.up__add {
  position: relative; flex: none; display: grid; place-items: center; width: 36px; height: 36px; border-radius: 999px;
  background: var(--cd-y); color: var(--cd-ink); transition: opacity .15s ease, transform .1s ease;
}
.up__add svg { display: block; stroke-width: 1.75; }
.up__add.is-press { transform: scale(.9); }
.up__add.is-busy { opacity: .7; }
.up__add.is-busy svg { visibility: hidden; }
.up__spin { position: absolute; inset: 0; margin: auto; width: 18px; height: 18px; border-radius: 50%; border: 2px solid rgba(17, 17, 17, .25); border-top-color: var(--cd-ink); opacity: 0; }
.up__add.is-busy .up__spin { opacity: 1; animation: up-spin .7s linear infinite; }
@keyframes up-spin { to { rotate: 360deg; } }

/* mouse pointer (decor over the drawer, upsell phase only): flies in from the free strip (≥1100) or the drawer's left
   edge (<1100), clicks Add (pointer scales .9 + a small ripple at the hotspot), then backs off and fades. White arrow,
   #111 outline, soft shadow. Hotspot = the arrow tip = (3, 2) on the 24 grid → (3.25, 2.17) at 26px. */
.cursor {
  position: absolute; z-index: 6; left: 0; top: 0; width: 26px; height: 26px; pointer-events: none; opacity: 0;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, .28));
}
.cursor svg { display: block; fill: #fff; stroke: #111; stroke-width: 1.5; stroke-linejoin: round; transform-origin: 3.25px 2.17px; transition: scale .12s ease; }
.cursor.is-on { opacity: 1; }
.cursor.is-fly { transition: translate .7s cubic-bezier(.3, .7, .2, 1), opacity .15s ease; }
.cursor.is-out { opacity: 0; transition: translate .4s ease-in, opacity .3s ease; }
.cursor.is-press svg { scale: .9; }
.cursor__ripple {
  position: absolute; left: 3.25px; top: 2.17px; width: 30px; height: 30px; margin: -15px 0 0 -15px;
  border: 2px solid #111; border-radius: 50%; opacity: 0; pointer-events: none;
}
@keyframes cursor-ripple { from { scale: .3; opacity: .8; } to { scale: 1.25; opacity: 0; } }
.cursor.is-press .cursor__ripple { animation: cursor-ripple .45s ease-out; }


/* coins burst from the $90 milestone when the cart reaches it, then fade (decor layer over the stage) */
.burst { position: absolute; z-index: 3; 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; }

.goal-sec__note { margin-top: 28px; font: 400 13px/1.45 var(--body); color: var(--muted); }

/* ───────── 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); }
}

/* ≥1100 the drawer stands beside the copy: equal room above and below, so the 596px frame + its shadow sit inside the
   two cut lines of .hero-fx at 1280×800 */
@media (min-width: 1100px) {
  /* A drawer's proportions: narrow and tall (h/w ≥ 1.6). Its height = the band between the two cut lines of .hero-fx
     less 16px at each end (top inset 2vw, the bottom line moved to 16px from the hero edge to give it room); its width
     = height / 1.6, kept to 380–420. The drawer is centred on the cut-line band (it is the tallest thing in the hero, so
     it, not the copy, sets the frame; the copy column centres on it). */
  .hero {
    --fx-top: clamp(16px, 2vw, 48px); --fx-bot: 16px;
    --cd-h: clamp(560px, calc(min(100svh - var(--bars), 1000px) - var(--fx-top) - 56px), 820px);
  }
  /* top: cut line + 16 · bottom: 16 + the 8px shadow + 16 + cut line inset */
  .hero__in { padding-top: calc(var(--fx-top) + 16px); padding-bottom: 40px; }
  .art { width: calc(clamp(380px, var(--cd-h) / 1.6, 420px) + 8px); max-width: none; }
}

/* Short desktops (≤860 tall): the drawer may run past the two cut lines (they sit behind it): 12px under the nav and
   12px above the viewport edge, so the end state (upsell row + gift row + the whole upsell band) fits the body.
   Width ≥ 408 keeps the longest reward message on one line (a narrower frame needs 2 lines of room, see .rb__msg). */
@media (min-width: 1100px) and (max-height: 860px) {
  .hero { --cd-h: calc(100svh - var(--bars) - 24px); }
  .hero__in { padding-top: 12px; padding-bottom: 12px; }
  .art { width: calc(clamp(408px, var(--cd-h) / 1.6, 420px) + 8px); }
}
/* ≤820 tall: upsell thumb at the spec's ×0.8 · ≤780 tall: tighter cart rows (photo stays 64) */
/* SHORTFALL (filled in after measuring): Boxed rows are taller than the old ones, so on short desktops the end state
   (Moisturizer + gift + whole band) needs cuts, in this order, stopping when it fits: (a) checkout 64 → 52 ·
   (b) row image 88 → 72 + row padding 12 → 10 · (c) band padding 20 → 16, footer padding-top 20 → 12 ·
   (d) a uniform zoom ≥ .92 on the drawer content. Measured need (Moisturizer + gap + gift + band): 374 at a–c;
   body has 394 at 1440×900 (a–c enough), 355 at 1280×800 (→ zoom .96), 323 at 1366×768 (→ zoom .92).
   (d) overturns the r2 rule "never scale the widget" — that rule was set by main, not by Vũ, and Vũ's rule (whole
   upsell row + gift + band at the end) is the one that must hold. The frame size itself does not change.
   a–c apply at every desktop height: the ≥1600 frame (700, capped in r3b) is no taller than 1440×900's 708, so it
   needs them too (without them 1920×1080 hid the Moisturizer row at the end). */
@media (min-width: 1100px) {
  .cd { --cd-co-h: 52px; }                                          /* (a) */
  .cd__item { padding: 10px; }                                       /* (b) */
  .cd__img { width: 72px; height: 72px; }
  .cd__meta { min-height: 72px; }
  .up { --up-pad: 16px; }                                            /* (c) */
  .cd__foot { padding-top: 12px; }
}
@media (min-width: 1100px) and (max-height: 800px) { .cd { zoom: .96; } /* height: 100% resolves against the frame, so the zoomed drawer still fills it exactly */ } /* (d) */
@media (min-width: 1100px) and (max-height: 780px) { .cd { zoom: .92; } } /* (d) */

@media (min-width: 1600px) {
  /* zig-zag: $ 60 high-middle · small 36 near the drawer · % 100 low and far */
  .art__coin--1 { left: -164px; top: 64%; width: 100px; }
  .art__coin--2 { --r: 10deg; display: block; left: -100px; top: 8%; width: 60px; }
  .art__coin--3 { left: -50px; top: 36%; }
  /* tall screens: the drawer stops at ~700 (h/w 1.67), no empty body under the band at the start of the loop */
  .hero { --cd-h: clamp(560px, calc(min(100svh - var(--bars), 1000px) - var(--fx-top) - 56px), 700px); }
  /* 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: 488px; }
}

/* Below 1100: one column — copy and form first, the drawer under the countdown (left edge, ≤480 wide). */
@media (max-width: 1099px) {
  .hero__in { grid-template-columns: minmax(0, 1fr); }
  .hero__title { font-size: clamp(30px, calc((100cqi - 8px) / 15.6), 52px); }
  .hero__title .hero__l1 { padding-bottom: 0; }
  .art { justify-self: start; width: 100%; max-width: 488px; margin: 40px 0 0; }
  .art__coin { display: none; }
}
/* Below 1024: screen 2 receipts stack (the right one first in reading order stays second), H2 sized by viewport */
@media (max-width: 1023px) {
  .vs { grid-template-columns: minmax(0, 420px); justify-content: start; gap: 32px; }
  .bill--before { width: 100%; }
  .goal-sec__title { font-size: clamp(28px, 5.4vw, 48px); }
}

@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; }
  /* phone: the drawer takes the column (gutter 16); its height leaves room for the 80px dock under it */
  .art { margin-top: 32px; }
  /* height: frame top 16px under the screen top → Checkout ends ≥2px above the 80px dock */
  .frame { --cd-h: min(596px, calc(100svh - 98px)); }
  /* phone: compact cart rows so a row + the whole upsell band fit the body (238px at 375×667) */
  /* phone: the same cuts as short desktops (a–c) — the end state shows the gift row + the whole band */
  .cd { --cd-co-h: 52px; }
  .cd__item { padding: 10px; gap: 16px; }
  .cd__img { width: 72px; height: 72px; }
  .cd__meta { min-height: 72px; }
  .up { --up-pad: 16px; }
  .cd__foot { padding-top: 12px; }
  .cd { zoom: .92; }   /* (d): a row + the whole band fit the body at the start */
  .cd__list { padding-top: 12px; }
  /* no room beside the drawer on a phone (16px gutters): the coins would only show as clipped scraps — off */
  .art__coin { display: none; }
  .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, .bill__row--keep { 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); }
  .vs { margin-top: 28px; }
  .bill__keep { font-size: 24px; }
  /* phone: the upsell thumb at the spec's mobile factor (×0.8 of 86) */

  .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; }
  .cursor { display: none; }
  .vs .bill, .vs .bill__paper, .vs .bill__title, .vs .bill__row, .vs .bill__rule, .vs .bill__gift, .vs .bill__stamp { animation: none !important; opacity: 1; }
  .cd-js .frame, .cd-js .frame.is-in { opacity: 1; animation: none; }
  .rb__fill, .cd, .ann__track, .cd-js .cd__slot, .cd-js .cd__slot .cd__item, .up__card, .up__add { transition: none; }
  .rb__seg.is-pop .rb__label, .rb__seg.is-next .rb__bar, .cd__slot.is-in .cd__tag, .burst.is-on i { animation: none; }
  .cta, .dock, .run-form, .run-form .cta { transition: none; }
}

/* ───────── r6 (22/10) · same treatment as FG v12: try box, one right edge, countdown out of the copy column,
   halftone background, flat end CTA, no coupon footer ───────── */
/* Left column: chip → lead → try box share ONE right edge (--col = min(560, column − 8)). The H1 uses FG v12's size
   (col / 9.8) so both landings read at the same scale (Vũ 22/10: CD looked bigger at col / 8.7); it wraps to 4 lines,
   also when the hero stacks <1100 (capped at --col). */
/* Copy stays centred on the drawer, lifted up to 22px so chip → logo reads like FG v12 (measured 22/10: CD sat 21–24px lower
   at every height — its hero padding is 46/40 vs FG 32/48 and its copy column is 26px shorter). */
/* Below ~800px tall FG overflows its hero and the gap floors at 52px, so the lift ramps in with the viewport height. */
@media (min-width: 1100px) { .hero__copy { translate: 0 calc(-1 * clamp(0px, (100svh - 760px) / 2, 22px)); } }
.hero__copy { --col: min(560px, 100cqi - 8px); }
.hero__title { max-width: var(--col); 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; 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: the joined bar never sinks or grows its own shadow — hover / press only deepen the button */
.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; }

/* Countdown in the nav, left of Install app (the drawer fills the hero's height, so there is no row above it). */
.nav__end { display: flex; align-items: center; gap: 20px; }
.nav .count { margin: 0; }

/* Background: print halftone over the right half, from under the ticker (behind the nav) to the hero's bottom. SVG dots
   (crisp at any DPR). Left edge starts 32px past the try box, full after 160px; bottom fades. Static, ink only. ≥1024.
   --box-x = try box right edge incl. shadow: shell inner 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; }
  .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); }
}

/* Short desktops: the copy column must not outgrow the drawer (it would push the frame past the fold) — tighter rhythm. */
@media (min-width: 1100px) and (max-height: 800px) {
  .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; }
}
/* the drawer holds its place under the nav even if the copy column runs a few px longer (badge + 3-step line) */
@media (min-width: 1100px) and (max-height: 860px) { .hero__in > .art { align-self: start; } }

/* Decor kept to the side (Vũ 22/10): where the right margin has room (≥1400: ≥100px past the drawer's shadow), the
   small coin leaves the strip between copy and drawer and sits beside the drawer's right edge, level with the reward bar. */
@media (min-width: 1400px) {
  .art__coin--3 { left: auto; right: -64px; top: 24%; }
}

/* End: flat yellow button, no offset decor; no coupon footer, no dashed rules. */
.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 (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; }
  .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; }

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

/* ───────── r8 (22/10) · overall heights follow FG v12 (Vũ: "lấy FG làm chuẩn sửa CD") ─────────
   Same hero padding as FG (32/48, 16 on ≤860-tall screens). The drawer no longer takes a viewport-based fixed height:
   it stretches to the copy column — top on the H1, bottom on the try box (both shadows 8px) — so CD's hero reads at
   FG's height. `contain: size` keeps the drawer's own content out of the row height (the copy column sets it); the body
   still scrolls inside and bfcm-cd.js measures it live, so the sequence and the row snapping are unchanged. */
@media (min-width: 1100px) {
  .hero__in { align-items: start; padding-top: 32px; padding-bottom: 48px; }
  .hero__in > .art { align-self: stretch; display: flex; flex-direction: column; width: min(428px, calc(100% + 8px)); }
  .frame { flex: 1 1 auto; height: auto; min-height: 0; contain: size; }
}
@media (min-width: 1100px) and (max-height: 860px) {
  .hero__in { padding-top: 16px; padding-bottom: 48px; }
}
@media (min-width: 1100px) { .hero__copy { translate: none; } } /* r8: copy and drawer share one row top (old optical lift dropped) */
/* Short desktops — the same rhythm as FG v12 (≤860 tall), last in the file so the try-box base rules above can't undo it */
@media (min-width: 1100px) and (max-height: 860px) {
  .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; }
}
/* FG's right column (40px coin room + 505 frame + its decor = 626px) can be taller than the copy (≤860-tall screens), which
   makes FG's hero row taller and shifts its centring. Give CD's row the same floor so both heroes centre identically;
   align-content: start keeps the row (and the drawer, which follows the copy) at the copy's own height. */
@media (min-width: 1100px) {
  .hero__in { align-content: start; min-height: calc(626px + 32px + 48px); }
}
@media (min-width: 1100px) and (max-height: 860px) {
  .hero__in { min-height: calc(626px + 16px + 48px); }
}
