/* ============================================================================
   LOYALTY CARDS — the landing page
   ----------------------------------------------------------------------------
   Fourteen bands and a footer, in the order the story is told.

   Three rules hold the whole thing together:

   1. BACKGROUNDS RUN TO THE WINDOW EDGE. CONTENT NEVER DOES. Every band is
      100% wide; everything you read sits inside .hold, which stops at 1440.

   2. THE PAGE CHANGES COLOUR SLOWLY. Light bands are transparent — they let
      <body> show through — and the scroll engine writes body's background
      from whichever band owns the viewport. The 1.1s transition on body is
      what makes it a fade rather than a switch.

   3. NO TWO NEIGHBOURING BANDS SHARE A SHAPE. Full-bleed image, then a
      split, then a bento, then a centred stage, then a split the other way,
      then a marquee. If two sections in a row would land on the same grid,
      one of them is wrong.

   Dark bands are inset and rounded rather than edge-to-edge, which is what
   removes the hard seam you would otherwise get against a tinted ground.
   The two photographic bands — the hero and the closing CTA — are the
   exception: those are true full bleed, because an inset photograph reads
   as a picture of a room and a full-bleed one reads as the room.
   ========================================================================== */

:root{
  /* How far the film hangs past the end of its own band and into the dark
     one. Both sides of the seam are derived from this single number — the
     film's negative margin pulls the tag wall up by exactly this much, and
     the tag wall adds exactly this much back as padding so its heading
     still starts where it would have. Change it in one place or the
     heading collides with the film. */
  --vt-overlap:clamp(140px,24vw,380px);
}

 /* ── Headlines ───────────────────────────────────────────────────────────
    Every section heading is written to fit TWO lines, and two is a budget
    that has to be defended at both ends of the range.

    At the wide end the hard <br> in the markup does it. At the narrow end the
    same <br> is the problem: it splits a heading that was already going to
    wrap, and 44 characters in two forced halves becomes four lines on a
    375px phone. So the break is a class, and below 760px it stops breaking
    and lets the text flow — where balance then splits it evenly.

    The floor of the size clamp is 26px rather than 32px for the same reason:
    at 26px a 375px screen fits about 26 characters a line, and no heading on
    this page is longer than 52. */
h2{text-wrap:balance}
.brk{display:none}
@media (min-width:760px){ .brk{display:inline} }
@media (max-width:759px){ h2{font-size:clamp(26px,7vw,34px)} }

/* ── Band scaffolding ────────────────────────────────────────────────── */
/* overflow:hidden is load-bearing, not tidying. The glows are deliberately
   positioned past the band's edges, and without this they widen the document
   — body's overflow-x:hidden stops you scrolling to the gap, but the page is
   still wider than the window and every centred thing sits slightly off. */
/* clip with a margin, not hidden. The glows are placed with negative offsets
   so they bleed past the band — that is the whole point of them — and
   overflow:hidden cut them dead at the boundary. Where a glow's bright middle
   sat outside the section, the cut showed as a hard horizontal line across
   the top of it. overflow-clip-margin lets the bleed run on for a bit so the
   glow has faded by the time anything is clipped. */
.band{position:relative;padding:clamp(84px,9.5vw,152px) 0;z-index:1;
  /* Clip sideways, never vertically. The glows are deliberately larger than
     their band and bleed into the neighbour — that soft handover IS the
     section transition. overflow-clip-margin:180px let them bleed exactly
     180px and then cut, and a radial gradient still at full strength when it
     is cut draws a hard horizontal line across the page. #numbers' glow
     starts 425px above its own section, so it was sliced 245px early.
     overflow-x:clip still stops a glow widening the document, which is the
     only thing the clip was ever for; overflow-y:visible lets the gradient
     finish fading on its own. (clip may pair with visible; hidden may not —
     hidden on one axis forces the other to compute as auto.) */
  overflow-x:clip;overflow-y:visible}
.band-tight{padding:clamp(60px,6.5vw,96px) 0}
/* For a band that ENDS in a full-bleed element. A marquee has no last line
   of text for the next band's top padding to measure itself against, so the
   normal 137 + 137 between two light bands reads as a hole rather than as
   rhythm. */
.band-flush-b{padding-bottom:clamp(44px,4.6vw,72px)}
/* For a band with a child that is MEANT to hang out of it. .band clips by
   default so the glows cannot widen the document, so a band that spills has
   to opt out — and then it must not carry a glow, or that escapes too. */
.band-spill{overflow:visible}
.band-dark{background:var(--purple-ink);color:rgba(255,255,255,.8);
  border-radius:clamp(26px,3.6vw,52px);
  /* This one DOES clip both ways, and should: it is a rounded inset panel
     with its own solid background, so the clip lands on an edge you can
     already see rather than slicing a gradient across open page. clip, not
     hidden — hidden makes the element a scroll container, which is what
     silently killed position:sticky across the whole site once already. */
  margin:0 clamp(10px,1.6vw,22px);overflow:clip}
.band-dark h1,.band-dark h2,.band-dark h3,.band-dark h4{color:#fff}
.band-dark a{color:var(--peach)}

/* The glow. The single most load-bearing decorative element on the page:
   an enormous, very soft radial that sits behind the content and bleeds
   past the band edges. It is what stops a flat colour reading as flat. */
.glow{position:absolute;border-radius:50%;pointer-events:none;z-index:0;
  filter:blur(60px);opacity:.75}
.band > .hold,.band > .hold-mid,.band > .hold-narrow{z-index:2}

.lede{font-size:clamp(17.5px,1.5vw,21px);line-height:1.6;color:var(--muted);max-width:56ch}
.band-dark .lede{color:rgba(255,255,255,.72)}
.head-row{display:grid;grid-template-columns:1.15fr .85fr;gap:clamp(24px,4vw,70px);
  align-items:end;margin-bottom:clamp(40px,5vw,72px)}
.head-row .lede{padding-bottom:6px}
@media (max-width:860px){.head-row{grid-template-columns:1fr;align-items:start;gap:20px}}

/* A rounded photographic frame. */
.media{border-radius:var(--r-xl);overflow:hidden;position:relative;
  background:var(--line-2);isolation:isolate}
.media img{width:100%;height:100%;object-fit:cover;display:block}
 /* The caption on a photograph. A real piece of glass, not a flat white pill:
    a bright hairline along the top edge where the light would catch it, a soft
    shadow under it so it sits ABOVE the photo rather than in it, and enough
    blur that it stays legible over whatever happens to be behind it. */
.media-tag{position:absolute;top:clamp(14px,1.6vw,22px);left:clamp(14px,1.6vw,22px);
  z-index:3;max-width:calc(100% - clamp(28px,3.2vw,44px));
  display:inline-flex;align-items:center;gap:10px;
  padding:11px 18px;border-radius:16px;
  font-size:clamp(12.5px,1vw,14px);font-weight:600;letter-spacing:-.01em;
  line-height:1.3;color:var(--ink);
  background:rgba(255,255,255,.62);
  border:1px solid rgba(255,255,255,.7);
  border-bottom-color:rgba(255,255,255,.34);
  box-shadow:0 10px 30px -12px rgba(25,14,46,.42),
             inset 0 1px 0 rgba(255,255,255,.9);
  -webkit-backdrop-filter:blur(18px) saturate(180%);
  backdrop-filter:blur(18px) saturate(180%)}
.media-tag i{font-size:16px;line-height:0;color:var(--purple);flex-shrink:0}
/* Frosted rather than see-through where the viewer has asked for that, and
   opaque where blur is not supported at all — otherwise white-on-white. */
@supports not (backdrop-filter:blur(1px)){
  .media-tag{background:rgba(255,255,255,.93)}
}
@media (prefers-reduced-transparency:reduce){
  .media-tag{background:#fff;-webkit-backdrop-filter:none;backdrop-filter:none}
}

/* ============================================================================
   2 · HERO
   ========================================================================== */
.hero{position:relative;min-height:100svh;display:flex;align-items:flex-end;
  padding:calc(var(--nav-h) + 60px) 0 clamp(36px,5vw,72px);overflow:hidden}
.hero-img{position:absolute;inset:0;z-index:0}
.hero-img img{width:100%;height:100%;object-fit:cover;object-position:62% 40%;
  transform:scale(1.06);transition:transform 1.6s cubic-bezier(.2,.7,.3,1)}
.hero.lit .hero-img img{transform:none}
/* Two scrims, not one. The vertical lifts the copy off the floor; the
   horizontal darkens only the column the copy sits in, so the subject on
   the right stays fully lit instead of being muddied along with it. */
/* The scrims were written for a dusk photograph and carried over to a bright
   one, where they were the thing making the hero look dark rather than the
   image. Measured on the composite: the headline sat at 11.8:1 against white
   and the body at 17:1, where AA asks 3:1 and 4.5:1. That is five times the
   darkening the text actually needed, spent on hiding a photograph somebody
   chose for being bright.

   Lightened to roughly half. Re-measured after, because a scrim you cannot
   see through is a scrim you cannot check by eye. */
.hero-img:before{content:'';position:absolute;inset:0;z-index:1;
  background:linear-gradient(180deg,rgba(25,14,46,.30) 0%,rgba(25,14,46,0) 34%,
                             rgba(25,14,46,.18) 58%,rgba(25,14,46,.74) 100%)}
.hero-img:after{content:'';position:absolute;inset:0;z-index:1;
  background:linear-gradient(94deg,rgba(25,14,46,.56) 0%,rgba(25,14,46,.26) 34%,
                             rgba(25,14,46,0) 62%)}
.hero .hold{position:relative;z-index:3;width:100%}
/* One column, capped in px rather than ch: the chips and the buttons below
   the headline have to sit inside the same measure, and a ch cap set from
   the headline's own font-size would be far too narrow for them. */
.hero-copy{max-width:min(660px,56%)}
.hero h1{color:#fff;margin-bottom:22px;font-size:clamp(40px,5vw,70px)}
.hero h1 em{font-style:normal;color:var(--peach)}
.hero-sub{font-size:clamp(17px,1.5vw,20.5px);line-height:1.55;color:rgba(255,255,255,.84);
  max-width:48ch;margin-bottom:32px}
.hero-btns{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:clamp(36px,5vw,64px)}
.hero-note{font-size:14px;color:rgba(255,255,255,.6);margin:16px 0 0}

/* The glass strip of proof under the copy. */
.hero-strip{display:flex;gap:10px;flex-wrap:wrap}
.chip{display:inline-flex;align-items:center;gap:9px;padding:11px 18px;
  border-radius:var(--pill);font-size:14.5px;font-weight:450;color:#fff;
  background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.22);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}
.chip i{color:var(--peach);font-size:17px;line-height:0}

/* The hint that there is more below. */
.hero-scroll{position:absolute;left:50%;bottom:22px;z-index:4;transform:translateX(-50%);
  width:26px;height:42px;border:1.5px solid rgba(255,255,255,.4);border-radius:var(--pill);
  display:flex;justify-content:center;padding-top:8px}
.hero-scroll i{display:block;width:3px;height:8px;border-radius:2px;background:#fff;
  animation:scrolldot 2s cubic-bezier(.4,0,.2,1) infinite}
@keyframes scrolldot{0%{transform:translateY(0);opacity:0}
  26%{opacity:1}70%{transform:translateY(15px);opacity:0}100%{opacity:0}}
@media (max-width:1040px){.hero-copy{max-width:min(660px,74%)}}
@media (max-width:720px){
  .hero{min-height:100svh;padding:calc(var(--nav-h) + 56px) 0 34px}
  .hero-copy{max-width:none}
  /* A phone shows about a quarter of this photograph's width, so WHICH
     quarter decides whether the hero still tells the story. At 66% it is a
     man in a van; at 74% the same window holds his face, the QR card on the
     counter, the cup changing hands and the customer's phone. Checked by
     rendering the three candidate windows side by side rather than nudging
     it until it looked right. For this photograph that window is 72%: below it
     the barista and the QR card fall outside, above it her face does. */
  .hero-img img{object-position:72% 44%}
  .hero-scroll{display:none}
  /* On a phone the copy runs the full width, so a scrim that darkens only
     the left column darkens nothing useful. Replace it with a vertical one
     that lifts the whole lower half off the photograph. */
  /* Lightened with the desktop pair and for the same reason: measured at
     7.1:1 on the headline and 14.3:1 on the body, against 3 and 4.5. */
  .hero-img:after{background:linear-gradient(180deg,rgba(25,14,46,.38) 0%,
    rgba(25,14,46,.24) 28%,rgba(25,14,46,.64) 62%,rgba(25,14,46,.88) 100%)}
  .hero-sub{font-size:16.5px;margin-bottom:26px}
  .hero-btns{gap:10px;margin-bottom:26px}
  /* Four chips stacked is 214px of hero that the headline needs more. One
     scrolling row costs 46px and still shows there are four. */
  .hero-strip{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;
    margin:0 calc(var(--gutter) * -1);padding:0 var(--gutter)}
  .hero-strip::-webkit-scrollbar{display:none}
  .chip{flex-shrink:0;padding:10px 15px;font-size:13.5px}
  .hero-note{font-size:13px;margin-top:14px}
}

/* ============================================================================
   3 · THE PAIN — image column against a numbered ledger
   ========================================================================== */
.pain-grid{display:grid;grid-template-columns:.92fr 1.08fr;gap:clamp(28px,4.4vw,76px);
  align-items:center}
.pain-grid .media{aspect-ratio:4/5}
.pain-list{display:flex;flex-direction:column}
.pain-item{display:grid;grid-template-columns:auto 1fr;gap:20px;
  padding:26px 0;border-top:1px solid var(--line)}
.pain-item:first-child{border-top:none;padding-top:0}
.pain-item .n{font-size:14px;font-weight:600;color:var(--orange);
  font-variant-numeric:tabular-nums;padding-top:5px;letter-spacing:.04em}
.pain-item h3{margin-bottom:7px}
.pain-item p{font-size:16px;color:var(--muted);line-height:1.6;margin:0}
@media (max-width:860px){.pain-grid{grid-template-columns:1fr}
  .pain-grid .media{aspect-ratio:3/2}}

/* ============================================================================
   4 · WHAT CHANGES — a banner, then before/after cards
   ========================================================================== */
.banner{border-radius:var(--r-xl);overflow:hidden;aspect-ratio:21/8;
  margin-bottom:clamp(28px,3.4vw,54px);position:relative}
.banner img{width:100%;height:100%;object-fit:cover;object-position:50% 46%}
.banner:after{content:'';position:absolute;inset:0;
  background:linear-gradient(100deg,rgba(25,14,46,.5),rgba(25,14,46,0) 58%)}
.banner-copy{position:absolute;left:0;bottom:0;z-index:2;padding:clamp(22px,3vw,46px);
  max-width:34ch}
.banner-copy p{color:#fff;font-size:clamp(18px,2vw,27px);line-height:1.3;
  letter-spacing:-.025em;margin:0;font-weight:400}
@media (max-width:720px){.banner{aspect-ratio:4/3}}

.ba-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(12px,1.4vw,20px)}
.ba{background:var(--white);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:clamp(22px,2.2vw,30px);display:flex;flex-direction:column;gap:14px}
.ba .ic{width:44px;height:44px;border-radius:13px;background:var(--lilac-soft);
  color:var(--purple);display:flex;align-items:center;justify-content:center;font-size:22px}
.ba h3{margin:0}
.ba .was{font-size:14.5px;color:var(--faint);line-height:1.5;margin:0;
  padding-bottom:12px;border-bottom:1px dashed var(--line)}
.ba .now{font-size:15.5px;color:var(--text);line-height:1.55;margin:0}
.ba .now b{color:var(--ink);font-weight:600}
@media (max-width:980px){.ba-grid{grid-template-columns:1fr 1fr}}
@media (max-width:560px){.ba-grid{grid-template-columns:1fr}}

/* ============================================================================
   5 · THE NUMBERS — a bento of live data
   ========================================================================== */
.bento{display:grid;grid-template-columns:repeat(12,1fr);gap:clamp(12px,1.4vw,20px)}
.tile{background:var(--white);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:clamp(24px,2.4vw,34px);display:flex;flex-direction:column;position:relative;
  overflow:hidden}
.tile h4{font-size:13px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted);margin-bottom:auto}
.tile .big{font-size:clamp(52px,6vw,82px);font-weight:500;letter-spacing:-.05em;
  line-height:1;color:var(--ink);font-variant-numeric:tabular-nums;margin:28px 0 10px}
.tile .cap{font-size:15px;color:var(--muted);line-height:1.55;margin:0}
.tile .src{font-size:12.5px;color:var(--faint);margin:16px 0 0}
.t-4{grid-column:span 4}.t-5{grid-column:span 5}
.t-7{grid-column:span 7}.t-8{grid-column:span 8}
@media (max-width:960px){.t-4,.t-5,.t-7,.t-8{grid-column:span 12}}

/* The bar chart. Heights are written from JS so a bar cannot animate
   before it is on screen, and the label rides the top of the bar. */
.chart{display:flex;align-items:flex-end;gap:clamp(8px,1.4vw,20px);
  height:clamp(160px,18vw,230px);margin-top:26px}
.bar-col{flex:1;display:flex;flex-direction:column;justify-content:flex-end;
  align-items:center;gap:10px;height:100%}
.bar{width:100%;border-radius:10px 10px 4px 4px;height:0;
  transition:height 1.25s cubic-bezier(.2,.7,.3,1);position:relative;
  background:var(--lilac)}
.bar.hi{background:linear-gradient(180deg,var(--orange),var(--orange-deep))}
.bar .v{position:absolute;left:0;right:0;top:-26px;text-align:center;font-size:14px;
  font-weight:600;color:var(--ink);opacity:0;transition:opacity .5s .7s}
.bar.lit .v{opacity:1}
.bar-col .lbl{font-size:13px;color:var(--muted);text-align:center;line-height:1.3}

/* The ring. One SVG circle, dash-offset driven from JS. */
.ring-wrap{display:flex;align-items:center;gap:clamp(18px,2.4vw,34px);margin-top:24px}
.ring{width:clamp(118px,13vw,160px);flex-shrink:0;position:relative}
.ring svg{width:100%;height:auto;display:block;transform:rotate(-90deg)}
.ring .track{fill:none;stroke:var(--line);stroke-width:9}
.ring .val{fill:none;stroke:var(--purple);stroke-width:9;stroke-linecap:round;
  transition:stroke-dashoffset 1.4s cubic-bezier(.2,.7,.3,1)}
.ring .mid{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-size:clamp(24px,2.6vw,32px);font-weight:600;color:var(--ink);letter-spacing:-.03em}

/* ── What it costs against what it returns ───────────────────────────────
   The sum on the left, the picture on the right.

   Spacing is on one scale here and not hand-typed per element: 14px inside a
   group, 26px between groups, 36px between halves. The version this replaced
   had seven different gaps and read as a form somebody had given up on.
   ========================================================================== */
.t-12{grid-column:span 12}
#pbTile h4{margin-bottom:clamp(22px,2.4vw,30px)}

.pb{display:grid;grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);
  gap:clamp(30px,4vw,64px);align-items:center}
@media (max-width:880px){ .pb{grid-template-columns:1fr;gap:36px} }

/* ── The sum ────────────────────────────────────────────────────────────── */
/* Display type, so it gets display-type treatment: tight leading and NEGATIVE
   tracking, which large text needs and body text does not. */
.pb-say{font-size:clamp(27px,3.1vw,42px);line-height:1.1;letter-spacing:-.04em;
  color:var(--ink);margin:0;font-weight:400;text-wrap:balance}
.pb-say em{font-style:normal;color:var(--purple);font-weight:500}
.pb-sub{font-size:15px;line-height:1.55;color:var(--muted);margin:14px 0 0;max-width:34ch}

.pb-fields{display:flex;flex-wrap:wrap;gap:26px;margin-top:26px}
.pb-f{flex:1 1 180px;min-width:0}
.pb-f label{display:block;font-size:12.5px;font-weight:600;color:var(--muted);
  letter-spacing:.01em;margin-bottom:9px}

.pb-in{display:flex;align-items:center;gap:4px;
  background:var(--white);border:1px solid var(--line);border-radius:var(--pill);
  padding:5px}
.pb-in:focus-within{border-color:var(--purple);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--purple) 13%,transparent)}
.pb-val{flex:1;min-width:0;display:flex;align-items:baseline;justify-content:center;gap:1px}
.pb-val i{font-style:normal;font-size:14px;color:var(--faint);font-weight:500}
.pb-val input{width:100%;min-width:0;border:0;background:none;outline:none;font:inherit;
  font-size:18px;font-weight:600;color:var(--ink);text-align:center;
  font-variant-numeric:tabular-nums;padding:6px 0;
  -moz-appearance:textfield;appearance:textfield}
/* The native spinners are 11px of hit target fighting the real buttons. */
.pb-val input::-webkit-outer-spin-button,
.pb-val input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}

/* Feedback on press, not on release — a button that waits for the click to
   finish before acknowledging it is what makes a page feel like a document. */
.pb-in button{width:40px;height:40px;flex-shrink:0;border-radius:50%;border:0;
  cursor:pointer;background:var(--lilac-soft);color:var(--purple);
  font-size:19px;line-height:1;display:grid;place-items:center;
  transition:background-color .18s,transform 90ms ease-out}
.pb-in button:hover{background:var(--lilac)}
.pb-in button:active{transform:scale(.88)}

/* ── The picture ────────────────────────────────────────────────────────── */
.pb-cap{font-size:13.5px;color:var(--muted);line-height:1.5;margin:0}
.pb-cap b{color:var(--ink);font-weight:600}
.pb-cap-b{margin-top:10px;max-width:38ch}
.pb-big{font-size:clamp(40px,5.6vw,72px);font-weight:500;letter-spacing:-.05em;
  line-height:1;color:var(--purple);font-variant-numeric:tabular-nums;
  margin:12px 0 0}
.pb-big.short{color:var(--faint)}

/* One bar, three parts. The sliver at the end is the whole argument, so it
   keeps a minimum width — below about 1.5% it stops being visible at all and
   the reader cannot see the thing being compared. */
.pb-bar{display:flex;gap:3px;height:34px;margin-top:26px;
  border-radius:var(--pill);overflow:hidden;background:var(--line-2)}
.pb-seg{height:100%;width:0;border-radius:3px;
  transition:width .8s cubic-bezier(.22,.68,.3,1)}
.pb-seg:first-child{border-radius:var(--pill) 3px 3px var(--pill)}
.pb-seg:last-child{border-radius:3px var(--pill) var(--pill) 3px}
.pb-seg.keep{background:linear-gradient(100deg,var(--purple),var(--purple-deep))}
.pb-seg.free{background:var(--lilac)}
.pb-seg.cost{background:var(--orange)}

.pb-key{list-style:none;display:flex;flex-wrap:wrap;gap:8px 22px;
  margin:14px 0 0;padding:0}
.pb-key li{display:flex;align-items:center;gap:7px;font-size:13px;color:var(--muted)}
.pb-key i{width:10px;height:10px;border-radius:3px;flex-shrink:0}
.pb-key i.keep{background:var(--purple)}
.pb-key i.free{background:var(--lilac)}
.pb-key i.cost{background:var(--orange)}
.pb-key b{color:var(--ink);font-weight:600;font-variant-numeric:tabular-nums}

#pbTile .src{margin-top:clamp(22px,2.6vw,32px)}

@media (max-width:560px){
  .pb-fields{gap:18px}
  .pb-f{flex:1 1 100%}
  .pb-bar{height:28px}
  /* 36px is a comfortable mouse target and a poor thumb one. */
  .pb-in button{width:44px;height:44px;font-size:21px}
}
@media (prefers-reduced-motion:reduce){
  .pb-seg{transition:width .2s}
  .pb-in button{transition:background-color .18s}
}

/* The tile that holds a photograph. */
.tile-img{padding:0;border:none;position:relative;min-height:260px}
.tile-img img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.tile-img:after{content:'';position:absolute;inset:0;
  background:linear-gradient(0deg,rgba(25,14,46,.86) 0%,rgba(25,14,46,.18) 56%,
                             rgba(25,14,46,0) 100%)}
.tile-img .q{position:relative;z-index:2;margin-top:auto;padding:clamp(24px,2.4vw,34px);
  color:#fff;font-size:clamp(17px,1.7vw,22px);line-height:1.4;letter-spacing:-.02em}
.tile-img .q span{display:block;margin-top:12px;font-size:13.5px;
  color:rgba(255,255,255,.66);letter-spacing:0}

/* ============================================================================
   6 · THE CARD — a dark stage, the card turning, benefits in glass
   ========================================================================== */
.stage{position:relative;min-height:clamp(520px,62vw,700px);
  display:grid;place-items:center}
.stage-card{width:clamp(280px,34vw,480px);position:relative;z-index:3}
.glassbox{position:absolute;z-index:4;width:clamp(210px,19vw,268px);
  padding:20px 22px;border-radius:var(--r);
  background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.2);
  -webkit-backdrop-filter:blur(16px) saturate(1.4);backdrop-filter:blur(16px) saturate(1.4);
  box-shadow:0 24px 60px -34px rgba(0,0,0,.7);
  opacity:0;transform:translateY(22px) scale(.96);
  transition:opacity .7s cubic-bezier(.2,.7,.3,1),transform .7s cubic-bezier(.2,.7,.3,1)}
.glassbox.in{opacity:1;transform:none}
.glassbox .ic{width:36px;height:36px;border-radius:11px;margin-bottom:13px;
  background:rgba(255,255,255,.16);color:var(--peach);
  display:flex;align-items:center;justify-content:center;font-size:19px}
.glassbox h4{font-size:16px;font-weight:600;margin-bottom:6px;letter-spacing:-.015em}
.glassbox p{font-size:13.8px;line-height:1.5;color:rgba(255,255,255,.74);margin:0}
.gb-1{top:4%;left:0}
.gb-2{top:22%;right:0}
.gb-3{bottom:20%;left:2%}
.gb-4{bottom:2%;right:3%}
@media (max-width:1040px){
  .stage{min-height:0;display:block}
  .stage-card{width:min(440px,78vw);margin:0 auto clamp(34px,5vw,54px)}
  .glassbox{position:static;width:auto}
  .glass-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
}
@media (max-width:620px){.glass-grid{grid-template-columns:1fr}}

/* ============================================================================
   7 · SETUP — a phone that plays the five steps through to the reward
   ========================================================================== */
.setup-grid{display:grid;grid-template-columns:1.02fr .98fr;
  gap:clamp(30px,5vw,88px);align-items:center}
@media (max-width:900px){.setup-grid{grid-template-columns:1fr;gap:40px}}

.steps{display:flex;flex-direction:column}
.step{display:grid;grid-template-columns:auto 1fr;gap:20px;padding:22px 0;
  border-top:1px solid var(--line);cursor:pointer;background:none;border-left:none;
  border-right:none;border-bottom:none;text-align:left;font-family:var(--font);
  width:100%;transition:opacity .4s}
.step:first-of-type{border-top:none}
.step .n{width:34px;height:34px;border-radius:50%;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
  font-size:14px;font-weight:600;font-variant-numeric:tabular-nums;
  background:var(--line-2);color:var(--muted);
  transition:background-color .4s,color .4s,transform .4s}
.step h3{margin-bottom:6px;color:var(--faint);transition:color .4s}
.step p{font-size:15.5px;color:var(--faint);line-height:1.55;margin:0;
  max-width:44ch;transition:color .4s}
.step.on .n{background:var(--orange);color:#fff;transform:scale(1.06)}
.step.on h3{color:var(--ink)}
.step.on p{color:var(--muted)}
.step.done .n{background:var(--lilac-soft);color:var(--purple)}

/* The progress rail — a thin line that fills as the phone advances. */
.step-rail{height:3px;border-radius:2px;background:var(--line);margin-top:28px;overflow:hidden}
.step-rail i{display:block;height:100%;width:0;border-radius:2px;background:var(--orange);
  transition:width .6s cubic-bezier(.4,0,.2,1)}

/* ── The phone ───────────────────────────────────────────────────────────
   A brushed metal rim, a glass inner bezel, and a screen that is a
   container — so everything inside it is sized in cqw and the whole device
   scales as one object. */
.phone{--dev:clamp(250px,28vw,330px);
  width:var(--dev);margin:0 auto;position:relative;
  /* The rim is a calc of --dev, not a percentage: percentage padding resolves
     against the CONTAINING BLOCK's width, and this column is twice the phone's
     width, so 2.6% drew a 15.7px rim where 8.6px was meant — and it thickened
     as the window grew. */
  aspect-ratio:1/2.04;border-radius:13.5% / 6.6%;padding:calc(var(--dev) * .026);
  background:linear-gradient(145deg,#4A4258,#201A2E 42%,#120D1E);
  box-shadow:0 2px 2px rgba(255,255,255,.22) inset,
             0 -2px 3px rgba(0,0,0,.6) inset,
             0 50px 90px -46px rgba(25,14,46,.62)}
.phone-screen{position:relative;width:100%;height:100%;overflow:hidden;
  border-radius:11.4% / 5.4%;background:var(--paper);container-type:inline-size;
  box-shadow:0 0 0 1px rgba(0,0,0,.6)}
.phone-notch{position:absolute;top:2.4%;left:50%;transform:translateX(-50%);z-index:9;
  width:30%;height:3.1%;border-radius:var(--pill);background:#0C0718}
.scr{position:absolute;inset:0;display:flex;flex-direction:column;
  padding:13cqw 6.5cqw 7cqw;opacity:0;visibility:hidden;
  transition:opacity .55s ease,visibility .55s,transform .55s cubic-bezier(.2,.7,.3,1);
  transform:translateY(10px)}
.scr.on{opacity:1;visibility:visible;transform:none}
.scr-title{font-size:6.2cqw;font-weight:600;letter-spacing:-.03em;color:var(--ink);
  line-height:1.15;margin-bottom:2.4cqw}
.scr-sub{font-size:4cqw;color:var(--muted);line-height:1.45;margin:0 0 6cqw}
.scr .lc{margin-bottom:5cqw}
.scr-spacer{flex:1}
.scr-btn{display:flex;align-items:center;justify-content:center;gap:2cqw;
  padding:4.4cqw;border-radius:var(--pill);background:var(--ink);color:#fff;
  font-size:4.2cqw;font-weight:500}
.scr-btn.accent{background:var(--orange)}
.scr-field{border:1px solid var(--line);border-radius:3cqw;padding:4cqw;
  font-size:4cqw;color:var(--faint);background:#fff;margin-bottom:3cqw}
.scr-field b{display:block;font-size:3.2cqw;color:var(--muted);font-weight:500;
  margin-bottom:1.4cqw;letter-spacing:.06em;text-transform:uppercase}
.scr-field.filled{color:var(--ink)}
/* The scan screen: a poster with a QR, framed by camera brackets. */
.scr-scan{flex:1;border-radius:5cqw;background:var(--ink);position:relative;
  display:flex;align-items:center;justify-content:center;overflow:hidden}
.scr-scan .poster{width:62%;background:#fff;border-radius:3cqw;padding:5cqw 4cqw;
  text-align:center}
.scr-scan .poster .qr{width:100%;aspect-ratio:1;margin-bottom:3cqw}
.scr-scan .poster .t{font-size:3.4cqw;font-weight:600;color:var(--ink);line-height:1.3}
.scr-scan .brackets{position:absolute;inset:14%;border-radius:4cqw;
  box-shadow:0 0 0 2px var(--peach) inset;
  clip-path:polygon(0 0,32% 0,32% 2.5%,2.5% 2.5%,2.5% 32%,0 32%,0 68%,2.5% 68%,
    2.5% 97.5%,32% 97.5%,32% 100%,0 100%,0 100%,100% 100%,100% 68%,97.5% 68%,
    97.5% 97.5%,68% 97.5%,68% 100%,100% 100%,100% 0,68% 0,68% 2.5%,97.5% 2.5%,
    97.5% 32%,100% 32%,100% 0)}
/* The reward moment. */
.scr-reward{flex:1;display:flex;flex-direction:column;align-items:center;
  justify-content:center;text-align:center;gap:3cqw}
.scr-reward .burst{width:22cqw;height:22cqw;border-radius:50%;background:var(--orange);
  color:#fff;display:flex;align-items:center;justify-content:center;font-size:11cqw}
.scr-reward .big{font-size:7cqw;font-weight:600;letter-spacing:-.035em;color:var(--ink);
  line-height:1.1}
.scr-reward .sm{font-size:4cqw;color:var(--muted);line-height:1.45;max-width:26ch}

/* ============================================================================
   8 · THE STUDIO — a working configurator
   ========================================================================== */
.studio{display:grid;grid-template-columns:.92fr 1.08fr;gap:clamp(22px,2.8vw,44px);
  align-items:stretch}
@media (max-width:900px){
  .studio{grid-template-columns:1fr}
  /* Once these stack, the card has to come FIRST. The editor is a column of
     inputs; put it on top and the thing every one of those inputs changes is
     pushed off the bottom of the screen, so you type blind and only find the
     card by scrolling. Source order stays editor-then-card because that is
     the sensible reading and tab order on a desktop, where they sit side by
     side and neither is "first". */
  .studio-stage{order:-1}
}
.studio-panel{background:var(--white);border:1px solid var(--line);
  border-radius:var(--r-lg);padding:clamp(24px,2.6vw,38px)}
.studio-panel .f{margin-bottom:22px}
.ctl-label{display:block;font-size:12.5px;font-weight:600;letter-spacing:.12em;
  text-transform:uppercase;color:var(--muted);margin-bottom:12px}

/* Upload. The real input is hidden behind a label so the control can be
   styled; the preview replaces the icon once a file is chosen. */
.upload{display:flex;align-items:center;gap:14px;padding:14px 16px;
  border:1.5px dashed var(--line);border-radius:var(--r-sm);cursor:pointer;
  transition:border-color .2s,background-color .2s}
.upload:hover{border-color:var(--purple);background:var(--lilac-soft)}
.upload input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.upload .box{width:42px;height:42px;border-radius:11px;background:var(--lilac-soft);
  color:var(--purple);display:flex;align-items:center;justify-content:center;
  font-size:20px;flex-shrink:0;overflow:hidden}
.upload .box img{width:100%;height:100%;object-fit:contain}
.upload .tx{font-size:14.5px;color:var(--muted);line-height:1.4}
.upload .tx b{display:block;color:var(--ink);font-weight:600;font-size:15px}

/* Swatches and icon chips. */
/* Chips at a fixed size, wrapping to fill the column — which is what this
   always was. A fixed five-column grid looked tidy in isolation and wrong in
   place: it stopped filling the panel and sat as a narrow block against the
   left edge while everything above it ran the full width.

   flex:0 0 is the part that matters. As plain flex children these shrink to
   squeeze one more onto a line, which is how ten stamp icons ended up
   smaller than the colour chips directly above them. */
.swatches{display:flex;flex-wrap:wrap;gap:9px;margin-bottom:24px}
/* 38px visual, 44px reach — same trick as the dots, so the swatch grid keeps
   its rhythm and the target still clears the floor. */
.sw:after{content:'';position:absolute;top:50%;left:50%;
  width:44px;height:44px;transform:translate(-50%,-50%)}
.sw{flex:0 0 38px;height:38px;border-radius:11px;border:2px solid transparent;
  cursor:pointer;padding:0;position:relative;
  box-shadow:0 0 0 1px rgba(25,14,46,.1) inset;transition:transform .16s,border-color .2s}
.sw:hover{transform:translateY(-2px)}
.sw[aria-pressed="true"]{border-color:var(--ink)}
.sw[aria-pressed="true"]:after{content:'';position:absolute;inset:0;border-radius:8px;
  box-shadow:0 0 0 2px #fff inset}
.icons{display:flex;flex-wrap:wrap;gap:9px}
.ic-pick{flex:0 0 42px;height:42px;border-radius:12px;border:1.5px solid var(--line);
  background:#fff;color:var(--muted);cursor:pointer;font-size:19px;
  display:flex;align-items:center;justify-content:center;
  transition:border-color .2s,color .2s,background-color .2s}
.ic-pick:hover{border-color:var(--purple);color:var(--purple)}
.ic-pick[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:#fff}

/* The stage follows the card. --stage is written from JS as a heavily
   darkened version of whichever skin is selected, so a pale card gets a
   ground it can sit on and a dark card gets one in its own family.

   It is a background-COLOUR, not a gradient, because background-image does
   not transition — and a stage that snaps while the card eases is the one
   detail that would make the whole control feel cheap. The fixed sheen on
   ::before supplies the depth the gradient used to. */
.studio-stage{border-radius:var(--r-lg);padding:clamp(30px,4vw,56px);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:22px;
  background-color:var(--stage,#1A0B40);position:relative;overflow:hidden;
  transition:background-color .6s cubic-bezier(.4,0,.2,1)}
.studio-stage:before{content:'';position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(72% 56% at 50% 34%,rgba(255,255,255,.16),transparent 70%),
             linear-gradient(162deg,rgba(255,255,255,.07),rgba(0,0,0,.42))}
.studio-stage .preview{width:min(430px,100%);position:relative;z-index:2}
/* The flip control. A card that turns needs to look like it will turn
   before anyone touches it, and a cursor change is not enough on a phone. */
.flipbtn{position:relative;z-index:2;display:inline-flex;align-items:center;gap:9px;
  padding:11px 20px;border-radius:var(--pill);cursor:pointer;font-family:var(--font);
  font-size:14.5px;font-weight:500;color:#fff;
  background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.26);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  transition:background-color .2s,border-color .2s,transform .08s}
.flipbtn:hover{background:rgba(255,255,255,.24);border-color:rgba(255,255,255,.4)}
.flipbtn:active{transform:translateY(1px)}
.flipbtn i{font-size:17px;line-height:0}
.studio-stage .sayso{z-index:2}
.studio-stage .sayso{position:relative;z-index:2;text-align:center;font-size:14.5px;
  color:rgba(255,255,255,.62);max-width:36ch;line-height:1.55;margin:0}

/* ============================================================================
   9 · THE CAROUSEL — a marquee of trades
   ========================================================================== */
.marquee{overflow:hidden;position:relative;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
.marquee-track{display:flex;gap:clamp(12px,1.4vw,20px);width:max-content;
  animation:slide 52s linear infinite}
.marquee:hover .marquee-track{animation-play-state:paused}
@keyframes slide{to{transform:translateX(-50%)}}
@media (prefers-reduced-motion:reduce){.marquee-track{animation:none}}
/* Bigger, and taller than they are wide by more than before. These are the
   only photographs on the page showing the actual trade a reader belongs to,
   so they can afford the room. */
.trade{width:clamp(244px,23vw,330px);flex-shrink:0}
.trade .media{aspect-ratio:3/4;margin-bottom:16px}
.trade .media img{transition:transform .9s cubic-bezier(.2,.7,.3,1)}
.trade:hover .media img{transform:scale(1.05)}
.trade h4{font-size:18px;font-weight:600;margin-bottom:5px;letter-spacing:-.015em}
.trade p{font-size:15px;color:var(--muted);margin:0;line-height:1.5}

/* ============================================================================
   10 · THE TAGS — the hero's ground again, with everything that fits on it
   ========================================================================== */
.tagband{position:relative;overflow:hidden;background:var(--purple-ink)}
 /* The hero photograph again, but blurred past recognition. At any opacity
    where you can still make out a person it stops being a ground and starts
    being a badly reproduced picture, so it is pushed down until all that
    survives is the warmth and the direction of its light. */
.tagband-bg{position:absolute;inset:0;z-index:0;opacity:.16}
.tagband-bg img{width:100%;height:100%;object-fit:cover;filter:blur(64px) saturate(1.5);
  transform:scale(1.25)}
.tagband:after{content:'';position:absolute;inset:0;z-index:1;
  background:radial-gradient(130% 90% at 50% 8%,rgba(100,50,200,.42),rgba(25,14,46,.94) 68%)}
/* Name the two content wrappers rather than using `> *`. The blurred
   backdrop is a sibling of theirs and it is positioned absolute — a `> *`
   rule here has the same specificity and comes later, so it was quietly
   turning the backdrop back into a relative, in-flow element. The image
   then took its natural height in the flow (804px at this width) and pushed
   the whole band down by that much. That was the gap above this heading. */
.tagband > .hold,
.tagband > .hold-mid{position:relative;z-index:2}
 /* Pills that take the width of their own label, wrapping into centred rows —
    the shape this wall has always had, just smaller. A fixed column grid gave
    every trade the same box and the ragged, typeset look went with it.

    The phone is the exception. At 375px auto-width pills still wrapped into
    eleven ragged rows, so there and only there they become two equal columns —
    still fully rounded, so it reads as the same object laid out tidily rather
    than as a different component. */
.tags{display:flex;flex-wrap:wrap;justify-content:center;
  gap:clamp(8px,.85vw,11px);max-width:1080px;margin:0 auto}
.tag{display:inline-flex;align-items:center;gap:8px;
  padding:10px 18px;border-radius:var(--pill);white-space:nowrap;
  font-size:clamp(13px,1.05vw,15px);font-weight:450;color:rgba(255,255,255,.88);
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.18);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  transition:background-color .5s,border-color .5s,color .5s,transform .5s}
.tag i{font-size:15px;line-height:0;color:rgba(255,255,255,.5);transition:color .5s;
  flex-shrink:0}
@media (max-width:560px){
  .tags{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
  .tag{justify-content:center;padding:10px 12px;white-space:normal;text-align:center}
}
.tag.lit{background:var(--orange);border-color:var(--orange);color:#fff;
  transform:translateY(-3px)}
.tag.lit i{color:#fff}

/* ============================================================================
   11 · PRICING
   ========================================================================== */
.plans{display:grid;grid-template-columns:1fr 1fr;gap:clamp(14px,1.8vw,24px);
  max-width:980px;margin:0 auto}
@media (max-width:760px){.plans{grid-template-columns:1fr}}
.plan{background:var(--white);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:clamp(26px,2.8vw,40px);display:flex;flex-direction:column;position:relative}
.plan.feature{border-color:var(--ink);border-width:1.5px}
.plan .badge{position:absolute;top:-12px;left:clamp(26px,2.8vw,40px);
  background:var(--orange);color:#fff;font-size:12px;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;padding:6px 14px;border-radius:var(--pill)}
.plan h3{font-size:22px;margin-bottom:6px}
.plan .blurb{font-size:15px;color:var(--muted);margin:0 0 24px;line-height:1.5;min-height:3em}
.plan .price{display:flex;align-items:baseline;gap:6px;margin-bottom:4px}
.plan .price .amt{font-size:clamp(44px,4.6vw,58px);font-weight:500;letter-spacing:-.045em;
  color:var(--ink);line-height:1}
.plan .price .per{font-size:15px;color:var(--muted)}
.plan .trial{font-size:14px;color:var(--purple);font-weight:500;margin:0 0 26px}
.plan ul{list-style:none;margin:0 0 30px;padding:0;display:flex;flex-direction:column;gap:13px}
/* See the note on .ob-note in site.css: the icon's box is one line of the
   text beside it, and it must not stretch to a wrapped paragraph's height. */
.plan li{--fs:15.5px;--lh:1.5;
  display:flex;gap:11px;font-size:var(--fs);line-height:var(--lh);color:var(--text)}
.plan li i{color:var(--purple);flex-shrink:0;align-self:flex-start;
  display:grid;place-items:center;
  block-size:calc(var(--fs) * var(--lh));font-size:18px;line-height:1}
.plan li.off{color:var(--faint)}
.plan li.off i{color:var(--faint)}
.plan .btn{margin-top:auto}
.plan-note{text-align:center;font-size:14.5px;color:var(--muted);margin:26px auto 0;
  max-width:60ch;line-height:1.6}

/* ============================================================================
   12 · THE GUARANTEE
   ========================================================================== */
.gtee{display:grid;grid-template-columns:.78fr 1.22fr;gap:clamp(28px,4.4vw,74px);
  align-items:center}
.gtee .media{aspect-ratio:4/5}
.gtee-list{display:flex;flex-direction:column;gap:22px;margin-top:30px}
.gtee-list > div{display:grid;grid-template-columns:auto 1fr;gap:16px}
.gtee-list .ic{width:44px;height:44px;border-radius:13px;background:var(--white);
  border:1px solid var(--line);color:var(--purple);
  display:flex;align-items:center;justify-content:center;font-size:21px;flex-shrink:0}
.gtee-list h4{font-size:17px;margin-bottom:5px}
.gtee-list p{font-size:15.5px;color:var(--muted);line-height:1.6;margin:0}
@media (max-width:860px){.gtee{grid-template-columns:1fr}
  .gtee .media{aspect-ratio:3/2}}

/* ============================================================================
   13 · FAQ
   ========================================================================== */
.faq{border-top:1px solid var(--line)}
.faq details{border-bottom:1px solid var(--line)}
.faq summary{list-style:none;cursor:pointer;padding:26px 44px 26px 0;position:relative;
  font-size:clamp(17px,1.6vw,20px);font-weight:500;color:var(--ink);letter-spacing:-.02em;
  line-height:1.4}
.faq summary::-webkit-details-marker{display:none}
.faq summary:after{content:'\002B';position:absolute;right:4px;top:50%;
  transform:translateY(-50%);font-size:24px;font-weight:300;color:var(--purple);
  transition:transform .3s}
.faq details[open] summary:after{content:'\2212'}
.faq .ans{padding:0 44px 28px 0;font-size:16.5px;line-height:1.7;color:var(--muted);
  max-width:68ch}
.faq .ans p{margin-bottom:12px}

/* ============================================================================
   14 · THE CLOSE
   ========================================================================== */
.close{position:relative;min-height:clamp(520px,66vh,680px);overflow:hidden;
  display:flex;align-items:center;text-align:center}
.close-img{position:absolute;inset:0;z-index:0}
.close-img img{width:100%;height:100%;object-fit:cover;object-position:50% 54%}
.close-img:after{content:'';position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(25,14,46,.82),rgba(25,14,46,.6) 46%,
                             rgba(25,14,46,.9))}
.close .hold{position:relative;z-index:2;width:100%}
.close h2{color:#fff;max-width:19ch;margin-left:auto;margin-right:auto}
.close h2 em{font-style:normal;color:var(--peach)}
/* Centred, but the gap ABOVE comes from the rhythm in site.css. This used
   to be a margin shorthand, which set margin-top:0 at a higher specificity
   than `h2 + p` and quietly held this one paragraph tighter than every other
   lede on the site. */
.close p{color:rgba(255,255,255,.82);font-size:clamp(17px,1.5vw,20px);
  max-width:50ch;margin-left:auto;margin-right:auto;margin-bottom:34px;line-height:1.55}
.close .hero-btns{justify-content:center;margin-bottom:0}
.close .hero-note{margin-top:22px}

/* ============================================================================
   10 · IN THEIR WORDS — one film
   ----------------------------------------------------------------------------
   A single player, as wide as the content gets. It sits between the trade
   marquee and the tag wall, which are both grids of small repeating things;
   one large quiet rectangle is the rest the eye needs before the wall.

   The frame is dark on a warm ground, which also ramps the page down into
   the dark tag band underneath instead of dropping into it.
   ========================================================================== */
/* The film is the seam. It ends its own band early, hangs past the edge,
   and lands on the dark one — so the two grounds are separated by the thing
   you are meant to look at rather than by a strip of empty paper.

   Three things have to agree for that to work:
     · the band stops short              #voices padding-bottom: 0
     · the film reaches past it          margin-bottom: -(--vt-overlap)
     · the band it lands on makes room   #tags padding-top: --vt-overlap + its own

   And the band has to out-rank its neighbour in the stacking order, because
   .band gives every band a z-index of 1 and the later sibling would
   otherwise paint straight over the overhang. */
/* The band above it ends flush under a full-bleed marquee, so this one does
   not need a full band's worth of lead-in on top of that. */
#voices{padding-top:clamp(64px,6.4vw,104px);padding-bottom:0;z-index:5}
.vt{margin:0 0 calc(var(--vt-overlap) * -1);position:relative;z-index:2}
#tags{padding-top:calc(var(--vt-overlap) + clamp(54px,5.6vw,92px))}
.vt-frame{position:relative;aspect-ratio:16/9;border-radius:var(--r-xl);overflow:hidden;
  background:var(--ink);isolation:isolate;
  box-shadow:0 2px 3px rgba(25,14,46,.05),0 60px 90px -56px rgba(25,14,46,.6)}
.vt-video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;
  background:var(--ink);
  /* Bias the crop up: faces sit in the top third, and a film that is not
     exactly 16:9 should lose floor, not head. */
  object-position:50% 34%}

/* A scrim only along the bottom, so the meta row stays readable over any
   frame the film happens to be paused on. */
.vt-frame:after{content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(0deg,rgba(25,14,46,.72) 0%,rgba(25,14,46,0) 34%);
  transition:opacity .4s}
.vt.playing .vt-frame:after{opacity:0}

.vt-play{position:absolute;z-index:3;top:50%;left:50%;transform:translate(-50%,-50%);
  width:clamp(74px,7vw,96px);aspect-ratio:1;border-radius:50%;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  font-size:clamp(26px,2.4vw,32px);color:var(--ink);
  background:rgba(255,255,255,.9);border:1px solid rgba(255,255,255,.7);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
  box-shadow:0 18px 44px -18px rgba(0,0,0,.6);
  transition:transform .28s cubic-bezier(.2,.7,.3,1),background-color .25s,opacity .3s,visibility .3s}
.vt-play:hover{transform:translate(-50%,-50%) scale(1.07);background:#fff}
.vt-play:active{transform:translate(-50%,-50%) scale(.98)}
.vt-play i{line-height:0;margin-left:4px}   /* optical centring of a triangle */
.vt.playing .vt-play{opacity:0;visibility:hidden}

/* A ring that breathes, so the button reads as the one thing to press.
   It is drawn on a pseudo-element rather than the button so the hover
   scale and the pulse cannot fight over the same transform. */
.vt-play:before{content:'';position:absolute;inset:-10px;border-radius:50%;
  border:1px solid rgba(255,255,255,.5);animation:vtpulse 2.8s ease-out infinite}
@keyframes vtpulse{
  0%{transform:scale(.92);opacity:.9}
  70%{transform:scale(1.16);opacity:0}
  100%{opacity:0}}
@media (prefers-reduced-motion:reduce){.vt-play:before{animation:none;opacity:.5}}

.vt-meta{position:absolute;z-index:2;left:clamp(16px,1.8vw,26px);bottom:clamp(16px,1.8vw,26px);
  display:flex;align-items:center;gap:9px;transition:opacity .4s,visibility .4s}
.vt.playing .vt-meta{opacity:0;visibility:hidden}
.vt-meta span{display:inline-flex;align-items:center;gap:6px;
  padding:8px 14px;border-radius:var(--pill);font-size:13.5px;font-weight:500;color:#fff;
  background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.24);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}
.vt-meta i{font-size:16px;line-height:0}

/* Shown only when the film is genuinely missing — the state is detected, not
   written into the markup, so it clears itself the moment a file lands. */
.vt-badge{position:absolute;z-index:3;top:clamp(16px,1.8vw,26px);left:clamp(16px,1.8vw,26px);
  padding:8px 16px;border-radius:var(--pill);font-size:12.5px;font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;color:var(--ink);background:var(--peach);
  border:1px solid rgba(25,14,46,.1)}
.vt-badge[hidden]{display:none}
/* No film means no running time either — a duration on a player that has
   nothing to play is a small invented fact, and this section exists to not
   make those. */
.vt.no-film .vt-meta,
.vt.no-film .vt-cap{display:none}
.vt.no-film .vt-play{cursor:not-allowed;opacity:.45}
.vt.no-film .vt-play:hover{transform:translate(-50%,-50%);background:rgba(255,255,255,.9)}
.vt.no-film .vt-play:before{animation:none;opacity:0}

/* Below the frame is past the seam, so this is always on the dark band. */
.vt-cap{margin:20px auto 0;max-width:52ch;text-align:center;
  font-size:15px;line-height:1.6;color:rgba(255,255,255,.62)}

@media (max-width:620px){
  /* At 4:3 a 16:9 film is cropped on the SIDES, not top and bottom, so the
     subject needs to be centred horizontally — which is why object-position
     above biases vertically only. */
  .vt-frame{aspect-ratio:4/3;border-radius:var(--r-lg)}
  .vt-meta .vt-cc{display:none}
}

/* ── The studio's own rig ────────────────────────────────────────────────
   Same 3D card as the stage in section six, but under the hand rather than
   on a loop: it holds still until you turn it, and the turn is a CSS
   transition rather than a JS tick because there is nothing to synchronise
   a sheen against — nothing is moving between clicks. */
.studio-stage .stage3d{perspective:1300px}
.studio-stage .card3d{transition:transform .9s cubic-bezier(.3,.8,.3,1);cursor:pointer}
.studio-stage .card3d.flipped{transform:rotateY(180deg)}
.studio-stage .card3d .face{box-shadow:0 34px 54px -26px rgba(0,0,0,.6)}
/* Held still, so the sheen has no rotation to derive itself from. It would
   be a highlight that never moves — the exact tell the rig exists to avoid. */
.studio-stage .sheen{display:none}

/* ============================================================================
   GROW WITH US — the affiliate band
   ----------------------------------------------------------------------------
   What is left here after the role picker was taken out: the band's own
   heading block. The picker recoloured the whole band on click, which is why
   .growband had a background transition — both are gone, and the band now
   takes one ground like every other section.
   ========================================================================== */
.grow-head{max-width:720px;margin:0 0 clamp(36px,4vw,56px)}

/* ============================================================================
   THE APP CAROUSEL — one screen at a time, the rest still there
   ----------------------------------------------------------------------------
   Full-bleed, because a row of handsets that stops at the text column reads
   as a widget rather than a stage.

   Every slide is laid out from the centre by transform alone — translate,
   scale, blur, opacity — so the whole thing moves on the compositor and
   nothing reflows while it animates. The centre one is larger and sharp;
   its neighbours are smaller, softened and dimmed, and they sharpen as they
   come in. It loops, so there is no end to arrive at.
   ========================================================================== */
/* The stage hugs the centre handset. It used to be 660px tall around a
   520px phone, and the leftover lilac under it read as a section that had
   not finished loading. A phone at this lane width is about 2.16 times its
   own width, so the stage is derived from the lane rather than guessed. */
/* clip on x, visible on y. The handsets run off both edges and are cropped
   there, which is the look — but overflow:hidden cropped them vertically
   too, and the shadow under each phone got sliced into a hard-edged band
   across the bottom of the stage. clip is the one value that can pair with
   visible without forcing the other axis to auto; site.css relies on the
   same trick on <body>. */
.appstage{position:relative;width:100%;
  --lane:clamp(206px,18vw,248px);
  /* The real, visible gap between two handsets. The centre is scaled up 7%,
     which would eat about 8px off each side of its own gap — place() nudges
     its neighbours outward by that half-spill so every gap on the row
     measures the same. */
  --gap:clamp(28px,2.9vw,42px);
  height:calc(var(--lane) * 2.16 + 110px);
  overflow-x:clip;overflow-y:visible}

.appstage-track{position:absolute;inset:0}

/* One gap wide, no height, out of the flow and out of the tree. It exists so
   the browser resolves --gap's clamp() into a real pixel width that lane()
   can read; a custom property read straight off the element computes to its
   own token text, not to pixels. */
.appgap-probe{position:absolute;top:0;left:0;width:var(--gap);height:0;
  visibility:hidden;pointer-events:none}

/* left:0;right:0 with auto side margins centres an absolutely positioned
   box without arithmetic. It used to be left:50% with the transform carrying
   a -w/2 correction, which left the centre slide forty pixels off because
   the correction and the element's own width were being read at different
   moments. The transform now carries ONLY the lane offset. */
.appshot{position:absolute;top:50%;left:0;right:0;margin-inline:auto;width:var(--lane);
  transform-origin:50% 50%;
  will-change:transform,filter,opacity;
  transition:transform .78s cubic-bezier(.22,1,.3,1),
             filter .78s cubic-bezier(.22,1,.3,1),
             opacity .78s cubic-bezier(.22,1,.3,1);
  cursor:pointer}
/* The centre sits above its neighbours only because it is scaled up and its
   shadow should fall across them; nothing overlaps otherwise. */
.appshot[data-at="0"]{cursor:default;z-index:5}

/* The handset. Titanium rim, black bezel, the island over the glass, a
   hairline of light along the top edge, and a shadow in two parts. */
.appshot-phone{position:relative;border-radius:clamp(30px,3vw,42px);padding:3px;
  background:linear-gradient(145deg,#8E8A96 0%,#45414C 18%,#2A2630 46%,#6F6B77 82%,#3A3640 100%);
  box-shadow:0 1px 2px rgba(0,0,0,.5),
             0 12px 24px -10px rgba(25,14,46,.45),
             0 44px 80px -30px rgba(25,14,46,.55)}
.appshot-phone-in{position:relative;border-radius:clamp(27px,2.7vw,39px);padding:5px;
  background:#07060A;overflow:hidden}
.appshot-phone img{display:block;width:100%;height:auto;border-radius:clamp(22px,2.3vw,34px)}
.appshot-phone:after{content:'';position:absolute;inset:0;border-radius:inherit;
  pointer-events:none;z-index:3;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.55), inset 0 -1px 0 rgba(255,255,255,.14)}
.appshot-phone-in:before{content:'';position:absolute;top:11px;left:50%;
  transform:translateX(-50%);width:30%;height:17px;border-radius:12px;
  background:#07060A;z-index:2}
.appshot-btns{position:absolute;inset:0;pointer-events:none;z-index:0}
.appshot-btns i{position:absolute;background:linear-gradient(90deg,#6B6773,#39353F);
  border-radius:2px;display:block}
.appshot-btns i:nth-child(1){left:-2.5px;top:30%;width:2.5px;height:5%}
.appshot-btns i:nth-child(2){left:-2.5px;top:39%;width:2.5px;height:8%}
.appshot-btns i:nth-child(3){left:-2.5px;top:50%;width:2.5px;height:8%}
.appshot-btns i:nth-child(4){right:-2.5px;top:36%;width:2.5px;height:12%}

/* The caption belongs to the centre slide only, so it is one element under
   the stage rather than one per phone — otherwise eight captions sit in the
   blur with their phones and the eye has nowhere to rest. */
/* Caption and controls on one line: the arrows belong beside the words they
   change, not floating over the handsets they would otherwise cover. */
/* The caption GROWS, the arrows do not move.
   With the caption sized to its own content the whole row re-centred on every
   slide, so the arrows walked in and out as the words changed length. The row
   is now a fixed box and the caption takes whatever is left inside it, which
   pins both arrows to the same two positions on every slide. */
.appcap-row{display:flex;align-items:center;justify-content:center;
  gap:clamp(14px,2.4vw,34px);
  margin:clamp(20px,2.2vw,28px) auto 0;
  width:100%;max-width:640px}
.appcap{text-align:center;min-height:60px;flex:1 1 auto;min-width:0}
.appcap b{display:block;font-size:20px;font-weight:600;
  letter-spacing:-.02em;color:var(--ink)}
.appcap span{display:block;margin-top:8px;font-size:15px;color:var(--muted);
  max-width:52ch;margin-left:auto;margin-right:auto}
.appcap.swap b,.appcap.swap span{animation:cap-in .5s cubic-bezier(.22,1,.3,1) both}
@keyframes cap-in{from{opacity:0;transform:translate3d(0,7px,0)}}

/* Dots, centred under the caption. */
.appdots{display:flex;justify-content:center;gap:8px;margin-top:clamp(16px,1.8vw,22px)}
/* The dot you SEE is 7px; the dot you can HIT is 44. A 7px-tall target is
   not a control on a phone, it is a dare. The visual stays exactly as it
   was — ::after only enlarges the hit area, and sits under nothing. */
.appdot{width:7px;height:7px;border-radius:50%;border:0;padding:0;cursor:pointer;position:relative;
  background:rgba(25,14,46,.18);transition:background .3s ease,width .3s ease}
.appdot:after{content:'';position:absolute;top:50%;left:50%;
  width:44px;height:44px;transform:translate(-50%,-50%)}
.appdot[aria-current="true"]{background:var(--purple);width:22px;border-radius:4px}
.appdot:focus-visible{outline:2px solid var(--purple);outline-offset:3px}

.appstage-btn{flex-shrink:0;
  width:48px;height:48px;border-radius:50%;display:grid;place-items:center;cursor:pointer;
  background:rgba(255,255,255,.9);border:1px solid rgba(25,14,46,.1);color:var(--ink);
  box-shadow:0 12px 30px -14px rgba(25,14,46,.45);
  transition:transform .3s cubic-bezier(.22,1,.3,1),background .3s ease}
.appstage-btn:hover{transform:scale(1.08);background:#fff}
.appstage-btn:active{transform:scale(.96)}
.appstage-btn:focus-visible{outline:2px solid var(--purple);outline-offset:3px}
@media (max-width:520px){
  .appcap-row{gap:12px}
  .appstage-btn{width:42px;height:42px}
}

@media (prefers-reduced-motion:reduce){
  .appshot{transition:none}
  .appcap.swap b,.appcap.swap span{animation:none}
}

/* ============================================================================
   THE AFFILIATE BENTO
   ----------------------------------------------------------------------------
   One photograph, two solid blocks. The photograph carries the people and
   the way in; the blocks carry what an affiliate actually gets, in flat
   colour, because a benefit is read and a photograph is only looked at.

   The previous version put glass over the photograph and tinted washes in
   the blocks. The glass sampled a backdrop that changed partway up it and
   rendered the seam as a dark band through its own middle, and the washes
   were too pale to read as deliberate. Both are gone.
   ========================================================================== */
.bento{display:grid;grid-template-columns:1.04fr .96fr;
  grid-template-rows:auto auto;gap:clamp(12px,1.3vw,18px)}
.bento-tall{grid-row:1 / span 2}

.bcell{position:relative;overflow:hidden;border-radius:var(--r-lg);isolation:isolate}
.bcell-img{position:absolute;inset:0;z-index:0}
.bcell-img img{width:100%;height:100%;object-fit:cover;display:block}

/* Ink from the bottom only, and not much of it — the photograph should stay
   a photograph. No blur: the type sits on the dark end of the gradient and
   does not need the picture softened underneath it. */
.bcell-img:after{content:'';position:absolute;inset:0;
  background:linear-gradient(to top,rgba(16,8,32,.86) 0%,rgba(16,8,32,.52) 32%,
             rgba(16,8,32,.12) 62%,transparent 86%)}

.bcell-body{position:relative;z-index:2;padding:clamp(24px,2.6vw,38px);
  display:flex;flex-direction:column;height:100%}

.bento-tall{min-height:clamp(460px,50vw,600px)}
.bento-tall .bcell-body{justify-content:flex-end}

/* The statement sits ON the photograph, so it needs a surface of its own
   rather than type floating on a picture. Dark glass, not light: the window
   behind these people is the brightest thing in the frame, and white type on
   light glass over a bright photograph is a contrast failure waiting for the
   one shot where the sun is in the window.
   The scrim underneath is a smooth gradient with no hard stop in it — a
   backdrop boundary crossing a backdrop-filter renders as a dark step
   through the middle of the card, which is exactly what sank the last glass
   panel here. */
.bglass{background:rgba(18,9,38,.46);
  -webkit-backdrop-filter:blur(16px) saturate(135%);
  backdrop-filter:blur(16px) saturate(135%);
  border:1px solid rgba(255,255,255,.14);border-radius:var(--r);
  padding:clamp(20px,2.3vw,30px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 22px 54px -30px rgba(0,0,0,.75)}
.bento-tall h3{color:#fff;font-size:clamp(21px,2.2vw,29px);line-height:1.16;
  letter-spacing:-.03em;font-weight:400;max-width:20ch}
.bento-tall p{color:rgba(255,255,255,.86);font-size:14.5px;line-height:1.6;
  margin-top:12px}
/* Full width, inside the card. It was a pill hanging off the bottom-left
   corner of a photograph with nothing holding it. */
.bento-tall .btn{margin-top:clamp(18px,2vw,24px)}
.btn-block{display:flex;width:100%;justify-content:center}

/* The two solid blocks. Brand colour, not a tint of it. */
.bflat{display:flex;flex-direction:column;justify-content:center;
  min-height:clamp(214px,21vw,268px)}
.bflat-deep{background:var(--purple-ink);color:#fff}
.bflat-deep h3{color:#fff}
/* Was full --orange. A 500x400 block of #FF6432 beside a 500x400 block of
   #2B1263 is two accents at full strength competing on a lilac ground, and
   it won every staring contest on the page — including the one against the
   headline. The pair is now DARK and LIGHT of the same family: the orange
   survives at full strength where it belongs, on the one button. */
.bflat-warm{background:var(--peach-soft);color:var(--ink)}
.bflat-warm h3{color:var(--ink)}

.bflat h3{font-size:clamp(19px,1.9vw,24px);line-height:1.18;letter-spacing:-.025em;
  font-weight:500;margin-bottom:clamp(14px,1.6vw,20px)}

/* Four ticked lines of identical weight give the eye nothing to land on, so
   nobody reads any of them. The terms ARE numbers, so they are set as
   numbers: the figure carries, the line underneath explains. */
.bstats{display:grid;grid-template-columns:1fr 1fr;
  gap:clamp(18px,2.1vw,28px) clamp(16px,2vw,26px);margin:0;padding:0}
.bstat dt{font-size:clamp(30px,3.3vw,44px);line-height:1;font-weight:500;
  letter-spacing:-.035em;font-variant-numeric:tabular-nums}
.bstat dd{margin:7px 0 0;font-size:13.5px;line-height:1.45}

.bflat-deep .bstat dt{color:var(--peach)}
.bflat-deep .bstat dd{color:rgba(255,255,255,.76)}
/* Full ink, not a percentage of it — the label is small, and small text on a
   tinted ground is where contrast quietly fails. */
.bflat-warm .bstat dt{color:var(--purple-deep)}
.bflat-warm .bstat dd{color:var(--text)}

@media (max-width:520px){ .bstats{gap:16px 14px} }

@media (max-width:860px){
  .bento{grid-template-columns:1fr}
  .bento-tall{grid-row:auto;min-height:clamp(420px,86vw,500px)}
}
@media (prefers-reduced-motion:reduce){ .bcell{transition:none} }
