/* v3 — the hybrid.
   ------------------------------------------------------------------
   B's paper card, C's chapter labels and (desktop only) route rail, and
   a v1-style journey background that changes by chapter behind it.

   Load order matters here: base.css sets the tokens and the shared
   typography, this file only adds the card, the journey and the offer.

   Readability rule for this page: ALL text sits on the opaque card.
   Nothing is ever set over a photograph. The background is only visible
   in the side margins and through the four windows, which carry no text. */

:root {
  --kraft: #EDE2CE;
  --card-edge: rgba(120, 92, 58, .22);
}

/* The journey layer is behind everything, so the page itself must not
   paint over it. html keeps a solid colour for overscroll. */
/* The `hidden` attribute has to actually hide. A class selector such as
   `.ph-inline { display: block }` outranks the browser's own
   `[hidden] { display: none }`, which is how the Bloom placeholder stayed
   on the page after being marked hidden. This makes the attribute win
   wherever it is used -- and it is used for three switchable blocks on
   this page: the ships-by line, the review slot and the melt video. */
[hidden] { display: none !important; }

html { background: #2A1A10; }
body { background: transparent; }

/* ---------------------------------------------------------------
   The journey
   --------------------------------------------------------------- */

.journey {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background: #2A1A10;
}
.journey .jl,
.journey picture {
  position: absolute;
  inset: 0;
}
.journey .jl {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity .9s ease;
}
.journey .jl.is-on { opacity: 1; }

/* A last light scrim on top of the baked-in darkening, so the card edge
   always reads. Measured in Phase 5. */
.journey-scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom, rgba(22,13,8,.30), rgba(22,13,8,.12) 40%, rgba(22,13,8,.32));
}

.page { position: relative; z-index: 1; }

/* ---------------------------------------------------------------
   The card
   --------------------------------------------------------------- */

.card {
  position: relative;
  background: var(--card);
  margin: 0 15px;
  padding: 20px 0 24px;
  box-shadow: 0 1px 0 rgba(120, 92, 58, .18), 0 16px 34px -20px rgba(20, 12, 6, .8);
  /* A very faint fibre. Two tiny gradients, no request. */
  background-image:
    radial-gradient(circle at 12% 22%, rgba(160, 130, 90, .05) 0 1px, transparent 1px),
    radial-gradient(circle at 68% 61%, rgba(160, 130, 90, .045) 0 1px, transparent 1px);
  background-size: 17px 17px, 23px 23px;
}
.card-first { padding-top: 22px; }

/* The windows: the only places the journey shows through the middle of
   the page. Deliberately empty — no text ever sits on a photograph. */
.window { height: 124px; }
.window:last-of-type { height: 156px; }

.wrap { padding: 0 var(--pad); }

/* ---------------------------------------------------------------
   Masthead, hero
   --------------------------------------------------------------- */

.masthead { padding: 0 var(--pad) 14px; }
.weave {
  height: 9px;
  margin: 16px 0 0;
  background:
    repeating-linear-gradient(135deg, var(--rule) 0 2px, transparent 2px 9px),
    repeating-linear-gradient(45deg,  var(--rule) 0 2px, transparent 2px 9px);
  opacity: .85;
}

.hero { padding-top: 20px; padding-bottom: 22px; }

.hero-fig { margin: 0 auto 4px; }
.hero-fig img,
.print img {
  background: #fff;
  border: 1px solid var(--card-edge);
  padding: 8px;
  box-shadow: 0 8px 18px -14px rgba(70, 48, 24, .7);
}

.letter { padding-top: 22px; }

/* ---------------------------------------------------------------
   Chapter labels (C's waypoints). Real text; they stand alone when the
   rail is not drawn.
   --------------------------------------------------------------- */

.chapter {
  position: relative;
  margin: 1.7em 0 .9em;
  line-height: 1.35;
  padding-top: 1.1em;
  border-top: 1px solid var(--rule);
}
.letter > .chapter:first-child { margin-top: .4em; padding-top: 0; border-top: 0; }

.ch-place {
  display: block;
  font-family: var(--sans);
  font-size: .74rem;
  font-weight: 700;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--mark);
}
.ch-note {
  display: block;
  font-family: var(--serif);
  font-style: italic;
  font-size: .98rem;
  color: var(--ink-muted);
  margin-top: .1em;
}

/* ---------------------------------------------------------------
   The route rail — desktop only, per Austin. Decorative.
   --------------------------------------------------------------- */

.rail { display: none; }

/* ---------------------------------------------------------------
   Honest things, stamp, placeholders
   --------------------------------------------------------------- */

.letter h2 {
  font-family: var(--serif);
  font-size: 1.44rem;
  line-height: 1.2;
  margin: 1.7em 0 .5em;
}

.honest { list-style: none; margin: 0 0 1.4em; padding: 0; }
.honest li {
  position: relative;
  padding-left: 18px;
  margin-bottom: .75em;
}
.honest li::before {
  content: "";
  position: absolute;
  left: 0; top: .62em;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--mark);
}

.stamp {
  width: 188px;
  margin: 2.2em auto 1.4em;
  padding: 11px 10px 9px;
  border: 2px solid var(--mark);
  border-radius: 4px;
  color: var(--mark);
  text-align: center;
  transform: rotate(-3.2deg);
  opacity: .8;
  font-family: var(--sans);
  text-transform: uppercase;
}
.stamp span { display: block; }
.stamp-top { font-size: .62rem; letter-spacing: .3em; }
.stamp-no  { font-size: 1.16rem; letter-spacing: .1em; line-height: 1.15; margin: 1px 0 3px; }
.stamp-bot { font-size: .56rem; letter-spacing: .13em; }

.placeholder { margin: 1.8em 0; }
.ph-box, .ph-inline {
  display: block;
  border: 2px dashed var(--rule);
  border-radius: 6px;
  padding: 22px 18px;
  text-align: center;
  background: rgba(216, 197, 168, .12);
}
.ph-inline { margin: 1.8em 0; }
.ph-k {
  display: block;
  font-family: var(--sans);
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--mark);
}
.ph-t {
  display: block;
  font-family: var(--serif);
  font-style: italic;
  font-size: .92rem;
  line-height: 1.45;
  color: var(--ink-muted);
  margin-top: .3em;
}

/* ---------------------------------------------------------------
   Signature
   --------------------------------------------------------------- */

.sig {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 2em 0 .4em;
  padding-top: 1.3em;
  border-top: 1px solid var(--rule);
}
.sig img { width: 54px; height: 54px; border-radius: 50%; }
.sig-name {
  display: block;
  font-family: var(--serif);
  font-size: 1.24rem;
  line-height: 1.2;
}
.sig-where {
  display: block;
  font-size: .84rem;
  color: var(--ink-muted);
}

/* ---------------------------------------------------------------
   The offer
   --------------------------------------------------------------- */

.offer { padding-top: 26px; }
.offer h2 {
  font-family: var(--serif);
  font-size: clamp(1.7rem, 7.4vw, 2.2rem);
  line-height: 1.12;
  margin: 0 0 .35em;
  text-align: center;
}
.offer-lede { font-size: 1.06rem; margin-bottom: 1.2em; }

.price { text-align: center; margin: 1.1em 0 .3em; }
.price-fig {
  font-family: var(--serif);
  font-size: 2.6rem;
  font-weight: 700;
  line-height: 1;
}
.price-ship {
  display: block;
  font-size: .98rem;
  color: var(--ink-muted);
  margin-top: .3em;
}
.price-per {
  text-align: center;
  font-size: .94rem;
  color: var(--ink-muted);
  max-width: 34em;
  margin: 0 auto 1.6em;
}

.box-head {
  font-family: var(--serif);
  font-size: 1.24rem;
  margin: 1.7em 0 .6em;
}
.box { list-style: none; margin: 0 0 1.5em; padding: 0; }
.box li {
  position: relative;
  padding-left: 20px;
  margin-bottom: .85em;
  font-size: .98rem;
}
.box li::before {
  content: "";
  position: absolute;
  left: 0; top: .58em;
  width: 8px; height: 8px;
  border: 1.6px solid var(--mark);
  border-radius: 2px;
}
.box em { color: var(--ink-muted); font-size: .94rem; }

.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin: 1.5em 0; }
.pair figure { margin: 0; }
.pair figcaption { font-size: .78rem; }

.founding {
  background: rgba(216, 197, 168, .3);
  border-left: 3px solid var(--mark);
  padding: 14px 16px;
  margin: 1.6em 0;
  font-size: .98rem;
}

.ships { color: var(--ink-muted); font-size: .95rem; text-align: center; margin: 1.4em 0 0; }
.ships-by {
  text-align: center;
  font-size: .95rem;
  margin: .5em 0 0;
  color: var(--mark);
  font-weight: 600;
}

.ask { font-size: .93rem; color: var(--ink-muted); margin: 0; text-align: center; line-height: 1.5; }
/* The phone number is the one link a reader might tap with a thumb while
   holding the phone in the other hand, and one $279 order has already
   come through it. Padded out to clear the 44px tap floor without
   turning the sentence into a stack of buttons. */
.ask a {
  color: var(--mark);
  display: inline-block;
  padding: 12px 6px;
  min-height: 44px;
  box-sizing: content-box;
  line-height: 20px;
}

/* ---------------------------------------------------------------
   Guarantee, Q&A, trust, footer
   --------------------------------------------------------------- */

.guarantee {
  margin-top: 30px;
  padding-top: 26px;
  padding-bottom: 6px;
  border-top: 1px solid var(--rule);
  text-align: center;
}
.guarantee h2 {
  font-family: var(--serif);
  font-size: 1.5rem;
  line-height: 1.18;
  margin: 0 0 .45em;
}
.guarantee p { max-width: 34em; margin: 0 auto; color: var(--ink-muted); }

.qa { margin-top: 34px; padding-top: 26px; border-top: 1px solid var(--rule); }
.qa > h2 {
  font-family: var(--serif);
  font-size: 1.5rem;
  margin: 0 0 1em;
  text-align: center;
}
.q { margin-bottom: 1.5em; }
.q h3 {
  font-family: var(--sans);
  font-size: 1rem;
  font-weight: 700;
  margin: 0 0 .3em;
}
.q p { margin: 0; color: var(--ink-muted); }

.trust { margin-top: 34px; padding-top: 26px; border-top: 1px solid var(--rule); text-align: center; }
.trust h2 { font-family: var(--serif); font-size: 1.36rem; margin: 0 0 .9em; }
.facts { list-style: none; display: grid; grid-template-columns: 1fr 1fr; gap: 14px 10px; margin: 0 0 1em; padding: 0; }
.fact-k { display: block; font-family: var(--serif); font-size: 1rem; }
.fact-v { display: block; font-size: .86rem; color: var(--ink-muted); line-height: 1.4; }
.facts-note { font-size: .82rem; color: var(--ink-muted); max-width: 34em; margin: 0 auto; }

.foot { margin-top: 34px; padding-top: 22px; border-top: 1px solid var(--rule); text-align: center; }
.foot-legal { font-size: .81rem; line-height: 1.55; color: var(--ink-muted); max-width: 36em; margin: 0 auto .5em; }
.foot-photo { font-style: italic; }
.foot-copy { font-size: .81rem; color: var(--ink-muted); margin: .8em 0 0; }

/* ---------------------------------------------------------------
   Tablet and desktop
   --------------------------------------------------------------- */

@media (min-width: 760px) {
  .card {
    max-width: 720px;
    margin: 0 auto;
    padding: 36px 0 40px;
  }
  .wrap { padding: 0 60px; }
  .window { height: 160px; }
  .window:last-of-type { height: 190px; }

  .pair { gap: 20px; }
  .facts { grid-template-columns: repeat(4, 1fr); }

  /* The route. Only drawn here, where there is room for it beside the
     card. Every chapter label keeps working without it. */
  .rail {
    display: block;
    position: absolute;
    top: 120px;
    bottom: 120px;
    left: 50%;
    margin-left: -398px;
    width: 18px;
    z-index: 2;
    pointer-events: none;
  }
  .rail svg { width: 100%; height: 100%; display: block; }
  .rail .halo { stroke: rgba(255, 253, 248, .55); }
  .rail .ink  { stroke: rgba(255, 253, 248, .85); }

  /* The waypoint dots sit ON the rail, which is outside the card, so
     they are cream with a dark ring rather than the card colour.
     Geometry: the rail's centre is at 50% - 398px + 9px; the chapter
     label's left edge is at 50% - 360px + 60px of padding. The dot is
     13px, so it needs to start 95px to the left of the label. */
  .chapter::before,
  .offer[data-scene]::before {
    content: "";
    position: absolute;
    left: -136px;
    width: 13px;
    height: 13px;
    border-radius: 50%;
    background: #FFFDF8;
    box-shadow: 0 0 0 3px rgba(22, 13, 8, .5);
  }
  .chapter::before { top: 1.45em; }
  .letter > .chapter:first-child::before { top: .35em; }
  .offer[data-scene]::before { top: 2.1em; }
  .offer { position: relative; }
}

@media (prefers-reduced-motion: reduce) {
  .journey .jl { transition: none; }
  .stamp { transform: none; }
}


/* ---------------------------------------------------------------
   Density.

   Everything above the offer is competing with the reader's patience:
   each 1,000px before the offer costs about 3 reach points at that
   depth (Phase 1 §2). These rules buy that space back out of spacing
   and out of the height of tall portrait photographs -- by insetting
   them rather than cropping them -- and not out of any copy.
   --------------------------------------------------------------- */

.letter p { margin: 0 0 1em; }
.letter .in { margin: 1.15em 0; }
.letter figcaption { margin-top: .5em; }

/* Portrait photographs run narrower than the column instead of being
   cropped. Nothing is lost from the picture. */
.print.inset picture,
.print.small picture { display: block; }
.print.inset img { width: 78%; margin: 0 auto; }
.print.small img  { width: 62%; margin: 0 auto; }

.cta { margin: 1.8em 0 1.5em; }
.stamp { margin: 1.7em auto 1.1em; }
.placeholder { margin: 1.3em 0; }
.sig { margin: 1.6em 0 .2em; padding-top: 1.1em; }
.letter h2 { margin: 1.4em 0 .45em; }
.honest li { margin-bottom: .6em; }

@media (min-width: 760px) {
  .print.inset img { width: 68%; }
  .print.small img  { width: 52%; }
}

/* ---------------------------------------------------------------
   The melt video

   Same framing as the photographs so it reads as another picture in
   the letter rather than as an embed. It carries [hidden] until the
   files exist, so the slot can sit in the markup without a broken
   player showing.
   --------------------------------------------------------------- */

.melt {
  display: block;
  width: 100%;
  height: auto;
  background: #fff;
  border: 1px solid var(--card-edge);
  padding: 8px;
  box-shadow: 0 8px 18px -14px rgba(70, 48, 24, .7);
}

@media (prefers-reduced-motion: reduce) {
  /* journey.js does not start it; the poster frame is what is seen. */
  .melt { outline: none; }
}

/* The subscribe line under the price. Deliberately plain: it is a statement
   of what the options cost, not a second offer competing with the first. */
.price-sub {
  text-align: center; margin: .5em 0 .2em;
  font-size: 1.02rem; line-height: 1.5; color: var(--ink);
}
.price-sub-detail {
  text-align: center; margin: 0 0 1.2em;
  font-size: .88rem; line-height: 1.55; color: var(--ink-muted);
}
.stars { color: var(--mark); letter-spacing: .06em; }
.etsy-line { text-align: center; margin: .5em 0 0; font-size: .86rem; }
.etsy-line a { color: var(--ink-muted); }

/* ---------------------------------------------------------------
   Goodbye to / Hello to

   Sits at the end of the lab card, immediately before the price. It is the
   last beat of the argument: the story, then the lab, then a plain list of
   what you are and are not getting.

   Everything here is readable with no JavaScript: the words are marked up
   with <s>, so the meaning does not depend on the drawn line. The line is a
   pseudo-element that grows on scroll, and only when motion is allowed.
   --------------------------------------------------------------- */

.gh { padding: 26px 0 8px; }
.gh-h {
  font-family: var(--serif);
  font-size: 1.22rem; text-align: center; margin: 0 0 1.1em; color: var(--ink);
}
.gh-grid { display: grid; gap: 18px; justify-items: center; }
.gh-col { width: 100%; }
.gh-k {
  font-family: var(--sans);
  font-size: .72rem; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; text-align: center;
  color: var(--ink-muted); margin: 0 0 .7em;
}
.gh-list { list-style: none; margin: 0; padding: 0; text-align: center; }
.gh-list li { font-size: 1.02rem; line-height: 1.5; margin-bottom: .42em; color: var(--ink); }
.gh-hi li { font-weight: 600; }

/* The strike is drawn, not typed: <s> loses its own line so the two cannot
   double up, and the drawn one is what animates. */
.gh-bye s { text-decoration: none; position: relative; }
.gh-bye s::after {
  content: ""; position: absolute; left: -3%; right: -3%; top: 54%; height: 2px;
  background: var(--mark); transform-origin: left center;
}

.gh-fig { margin: 2px 0 6px; text-align: center; }
.gh-fig img {
  width: 62vw; max-width: 260px; height: auto; aspect-ratio: 1;
  border-radius: 50%; object-fit: cover;
  border: 3px solid var(--card);
  box-shadow: 0 6px 20px rgba(46, 28, 18, .18);
}
.gh-badge {
  display: inline-block; margin-top: .75em; padding: 5px 13px;
  border-radius: 999px; background: var(--mark); color: #fff;   /* 8.34:1 inverted; measured below */
  font-family: var(--sans); font-size: .68rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
}

@media (min-width: 760px) {
  .gh-grid { grid-template-columns: 1fr auto 1fr; align-items: center; gap: 22px; }
  .gh-h { font-size: 1.4rem; }
}

/* The drawn line is an enhancement: armed by JavaScript, skipped entirely
   under reduced motion, and never hides the words. */
html.gh-anim .gh-bye s::after { transform: scaleX(0); transition: transform .5s ease; }
html.gh-anim .gh.is-struck .gh-bye s::after { transform: scaleX(1); }
html.gh-anim .gh.is-struck li:nth-child(2) s::after { transition-delay: .09s; }
html.gh-anim .gh.is-struck li:nth-child(3) s::after { transition-delay: .18s; }
html.gh-anim .gh.is-struck li:nth-child(4) s::after { transition-delay: .27s; }

/* ---------------------------------------------------------------
   The hero carving, as a link
   --------------------------------------------------------------- */

.hero-link { display: block; border-radius: 10px; }
.hero-link:focus-visible { outline: 3px solid var(--ink, #2e1c12); outline-offset: 4px; }

/* ---------------------------------------------------------------
   Tap a photograph to see it bigger
   --------------------------------------------------------------- */

.is-zoomable { cursor: zoom-in; }
.is-zoomable:focus-visible { outline: 3px solid var(--ink, #2e1c12); outline-offset: 3px; }

.has-lightbox { overflow: hidden; }

.lightbox {
  position: fixed; inset: 0; z-index: 9999;
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
  background: rgba(20, 12, 8, .92);
  opacity: 0; transition: opacity .18s ease;
  cursor: zoom-out;
  -webkit-tap-highlight-color: transparent;
}
.lightbox.is-open { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .lightbox { transition: none; } }

.lightbox__img {
  max-width: 100%; max-height: 100%;
  width: auto; height: auto;
  border-radius: 8px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, .5);
}

.lightbox__close {
  position: absolute; top: 10px; right: 12px;
  width: 44px; height: 44px;          /* a real touch target */
  display: flex; align-items: center; justify-content: center;
  font-size: 30px; line-height: 1;
  color: #faf6f0; background: rgba(0, 0, 0, .35);
  border: 1px solid rgba(250, 246, 240, .5); border-radius: 50%;
  cursor: pointer;
}
.lightbox__close:focus-visible { outline: 3px solid #faf6f0; outline-offset: 2px; }


/* ======================================================================
   v5 opening: the first screen, and the How it works strip under it.

   The whole point is the fold. 85% of this traffic is inside the Facebook
   or Instagram in-app browser, whose usable height on a common phone is
   about 660px once their chrome is accounted for. So the first screen is
   budgeted, not just styled: the photo is capped with aspect-ratio and
   max-height instead of being allowed to take its intrinsic square, which
   is what pushed the button under the fold before.
   ====================================================================== */
.first { padding-top: 4px; text-align: center; }
/* margin-inline MUST stay auto. base.css gives every h1 `max-width: 14ch`
   and centres the box with `margin: .55em auto .34em`; writing a three-value
   shorthand here reset the sides to 0, so the 327px box sat hard against the
   left of a 520px column and only the text inside it was centred. On desktop
   that put the headline 97px left of the photo and the button. */
.first__h1 {
  margin: 0 auto .4em;
  font-size: clamp(1.35rem, 6.2vw, 2.1rem);
  line-height: 1.18;
  text-wrap: balance;
}
.first__line {
  margin: 0 auto .7em;
  max-width: 34em;
  font-size: clamp(.92rem, 3.7vw, 1.05rem);
  line-height: 1.45;
}
.first__shot { display: block; margin: 0 auto .6em; max-width: 420px; }
/* The hero file is cut to 3:2 at build time and shown at 3:2, so nothing
   is downloaded to be cropped away and nothing is stretched. The ratio is
   declared so the box is reserved before the image arrives. */
.first__shot img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 3 / 2;
  border-radius: 10px;
}
.first__stars { margin: 0 0 .25em; font-size: .9rem; }
.first__stars .stars { color: #c9a227; letter-spacing: .06em; }
.first__price { margin: 0 0 .7em; font-size: .95rem; font-weight: 700; }
.first__cta { margin-top: 0; }

/* Short phones: give the photo less room rather than lose the button. */
@media (max-height: 700px) {
  .first__h1 { font-size: clamp(1.25rem, 5.6vw, 1.8rem); }
}

.how { padding-top: 6px; }
.how__h { text-align: center; margin: 0 0 .7em; font-size: 1.15rem; }
.how__steps {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 12px; margin: 0 0 1.1em; padding: 0; list-style: none;
}
.how__step { margin: 0; min-width: 0; text-align: center; }
.how__shot {
  display: block; width: 100%; height: auto;
  aspect-ratio: 1 / 1; object-fit: cover; border-radius: 8px;
}
/* Centred by flex, not by line-height: the face's digits do not sit on the
   line-box centre, so line-height:20px left them visibly high in the dot. */
.how__n {
  display: inline-flex; align-items: center; justify-content: center;
  margin-top: 6px;
  width: 20px; height: 20px; line-height: 1; border-radius: 999px;
  background: #c9a227; color: #2e1c12; font-weight: 800; font-size: .72rem;
}
.how__t { margin: 4px 0 0; font-size: .8rem; line-height: 1.3; }
.how__note { margin: 0 0 1em; }

.quotes { display: grid; gap: 10px; }
.quote { margin: 0; padding: 10px 14px; border-left: 3px solid #c9a227; }
.quote p { margin: 0 0 .35em; font-style: italic; }
.quote cite { font-style: normal; font-size: .78rem; opacity: .8; }
.quote .stars { color: #c9a227; }
.quotes__note { margin: 2px 0 0; font-size: .72rem; opacity: .7; }

.history__h { font-size: 1.1rem; margin: 0 0 .5em; }

/* The fold budget. On a short screen -- which is every in-app browser --
   the masthead is the cheapest thing to shrink, because the logo is
   decoration and the button is the point. Measured: this moves the first
   button's bottom edge from 695px to inside a 660px viewport. */
@media (max-height: 760px) {
  .masthead { padding-bottom: 6px; }
  .masthead img { max-width: 92px; height: auto; }
  .weave { margin-top: 8px; }
  .first { padding-top: 0; }
  .first__h1 { margin-bottom: .3em; }  /* bottom only: the sides stay auto */
  .first__line { margin-bottom: .5em; font-size: .9rem; }
  .first__shot { margin-bottom: .45em; }
  .first__price { margin-bottom: .5em; }
}

/* ----------------------------------------------------------------------
   How it works: a stacked row per step on a phone, three across on desktop.

   At 390px the three-across strip gave each photo about 110px and forced
   "Drop it into hot coffee" onto three lines. One step per row instead:
   a square photo on the left at 38% of the row, the number and the words
   on the right, vertically centred against it. The photos are cropped
   square at build time, so object-fit never has to rescue an odd shape.

   Desktop is untouched -- the three-column grid above still applies from
   760px up.
   ---------------------------------------------------------------------- */
.how__say { display: contents; }

@media (max-width: 759px) {
  .how__steps { grid-template-columns: 1fr; gap: 14px; }
  .how__step {
    display: grid;
    grid-template-columns: 38% 1fr;
    align-items: center;
    gap: 14px;
    text-align: left;
  }
  .how__say {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
  }
  .how__n { margin-top: 0; flex: 0 0 auto; }
  .how__t { margin: 0; font-size: .95rem; line-height: 1.3; }
}

@media (min-width: 760px) {
  .how__say { display: block; }
}

/* The step photos are links to the product page as well. They are
   aria-hidden and out of the tab order on purpose: the words beside each
   one are not a link, and the page already has four real buttons, so a
   screen reader or a keyboard would otherwise meet three unlabelled
   duplicates of the same destination. A thumb still hits them. */
.how__shotlink { display: block; }
.how__shotlink img { display: block; }

/* Every buy button is the same object: same width inside the content
   padding, same height, same radius, same size of type. The reviews CTA
   had lost its .wrap in the v5 restructure and rendered 360px wide against
   316 for the rest; the markup is fixed, and this keeps the rest honest
   even if a future button lands outside a wrap. */
.cta .btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 56px;
  padding: 14px 20px;
  border-radius: 10px;
  font-size: clamp(1rem, 4.3vw, 1.05rem);
  line-height: 1.2;
  text-align: center;
  text-wrap: balance;
}
.cta-note { text-wrap: balance; }
