/* =========================================================
   index-alt2.html — the journey page
   Layers over tokens.css + styles.css. Nothing here touches other pages.
   Order: browser surfaces → journey (hero, stage, steps, rail) → dock →
          moments → mission → final → vendors → responsive → reduced motion
   ========================================================= */

/* ---------- Browser surfaces ---------- */
.page-alt2 ::selection { background: var(--lavender); color: var(--ink); }
.page-alt2 { accent-color: var(--blue); }
.page-alt2 a:not(.btn):not(.badge) { text-underline-offset: .18em; text-decoration-thickness: 1.5px; }
.page-alt2 .footer__grid a, .page-alt2 .jstep__links a { text-decoration: none; }
.page-alt2 .footer__grid h3 { font-size: 1rem; margin-bottom: .8rem; }
.page-alt2 .footer__legal, .page-alt2 .review-card footer span { color: var(--ink-soft); }
.page-alt2 .final .btn--primary { box-shadow: 0 8px 20px -8px rgba(8, 14, 30, .5); }
.page-alt2 .footer__grid a:hover, .page-alt2 .jstep__links a:hover { text-decoration: underline; }

/* Primary fill at 4.8:1 (white on the site's deeper blue); hover a step darker */
.page-alt2 .btn--primary { background: var(--blue-deep); }
/* While the dock is up, the nav's twin of the same action steps back (desktop only) */
.page-alt2.dock-on .nav__cta { opacity: 0; visibility: hidden; transition: opacity var(--dur-fast), visibility 0s linear var(--dur-fast); }
.nav__cta { transition: opacity var(--dur-fast), visibility 0s; }

/* Secondary button on light ground (the docked "Get the free app") */
.btn--soft { color: #0b56b3; background: var(--blue-tint); } /* 6.1:1 on the tint */
.btn--soft svg { color: #0b56b3; }

/* Compact store badges inside the hero paths */
.badge--sm { padding: .45rem .9rem .45rem .7rem; border-radius: 10px; }
.badge--sm svg { width: 22px; height: 22px; }
.badge--sm span { font-size: .95rem; }
.badge--sm small { font-size: .72rem; }
.page-alt2 .badge small { font-size: .72rem; } /* store small print stays above the 11px floor */

/* ---------- Photo hero with an optional video ---------- */
.alt-hero__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center 62%;
  opacity: 0;
  transition: opacity 600ms var(--ease-out);
}
.alt-hero.has-video .alt-hero__video { opacity: 1; }

/* ---------- Journey: grid ---------- */
.journey {
  position: relative;
  padding-top: calc(var(--nav-h) + 3.5rem);
  padding-bottom: clamp(.5rem, 1.5vw, 1rem);
  background: var(--paper);
}
.journey__grid {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  grid-template-areas:
    "copy  stage"
    "intro stage"
    "steps stage";
  column-gap: clamp(2rem, 5vw, 5rem);
  align-items: start;
}
.journey__copy { grid-area: copy; }
.journey__intro { grid-area: intro; padding-top: clamp(2rem, 5vh, 3.5rem); scroll-margin-top: calc(var(--nav-h) + 1rem); }
.journey__steps { grid-area: steps; }
.journey__stage { grid-area: stage; position: sticky; top: calc(var(--nav-h) + 1.5rem); }

/* ---------- Hero copy ---------- */
.hero2__title {
  margin: 0;
  font-size: clamp(2.4rem, 3.8vw, 3.4rem);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -.025em;
  color: var(--ink);
  text-wrap: balance;
}
.hero2__line { display: block; }
.hero2__em {
  display: block;
  margin-top: .35em;
  font-size: .56em;
  font-weight: 300;
  font-style: italic;
  letter-spacing: -.01em;
  line-height: 1.2;
  color: var(--purple);
}
.hero2__lead {
  max-width: 30rem;
  margin-top: 1.1rem;
  font-size: var(--t-lead);
  color: var(--ink-soft);
}

/* ---------- The whole workflow in four beats ----------
   The ten-second version of the eight steps below. The separators are a drawn chevron carried on a
   mask, so they take the palette's purple and scale with the text — "&gt;&gt;" was characters standing
   in for an icon, which never sits right next to real type. */
.flow {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: .35rem .55rem;
  margin: 1.15rem 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--t-small);
  font-weight: 800;
  letter-spacing: -.005em;
  color: var(--ink);
}
.flow li { display: inline-flex; align-items: center; gap: .55rem; }
.flow li + li::before {
  content: "";
  flex: none;
  width: 1.05em; height: 1.05em;
  background: var(--purple);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h13m-5-5 5 5-5 5' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h13m-5-5 5 5-5 5' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
}
.hero2__note { margin-top: .9rem; font-size: var(--t-small); color: var(--ink-soft); }

/* The fork: one panel, two paths */
.paths {
  margin-top: 1.4rem;
  display: grid;
  grid-template-columns: 1fr;
  border-radius: var(--r-lg);
  background: var(--mist);
  overflow: hidden;
}
.paths__item { padding: 1.1rem 1.3rem 1.2rem; }
.paths__item + .paths__item { border-top: 1px solid var(--line); }
.paths__q { margin: 0 0 .8rem; font-weight: 800; color: var(--ink); font-size: var(--t-body); }
.paths__cta { width: 100%; }
.paths__stores { display: flex; flex-wrap: wrap; gap: .6rem; }
.paths__note { margin-top: .7rem; font-size: var(--t-small); color: var(--ink-soft); }

.assure {
  display: flex; flex-wrap: wrap; gap: .5rem 1.4rem;
  margin-top: 1.4rem;
  font-size: var(--t-small); font-weight: 700; color: var(--ink);
}
.assure li { position: relative; padding-left: 1.55rem; }
.assure li::before {
  content: "";
  position: absolute; left: 0; top: .2em;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--mint) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='m5.5 10.5 3 3 6-7' fill='none' stroke='%231a7f4b' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/14px no-repeat;
}

/* ---------- The stage: the "How it works" picture panel ----------
   ALL of its sizing lives in the six numbers below. Change them here to affect every page, or
   one page only by putting them on the element: <div class="stage" id="stage" style="--stage-max: 620px">
   ------------------------------------------------------------------ */
.stage {
  --stage-ratio: 4 / 5;      /* the shape of the panel AND of your pictures, on every screen.
                                Export the step pictures at this ratio (1200 x 1500 px) and they fill it exactly. */
  --stage-max: 528px;        /* widest the panel gets on desktop */
  --stage-h-mobile: 52svh;   /* how much of the phone's screen the panel may use (≤960px).
                                The width follows from the ratio, so the panel stays portrait on phones too. */
  --stage-fit: contain;      /* contain = show the whole picture · cover = fill the panel and crop the overflow */
  --stage-pad: 7%;           /* breathing room inside the panel. A PERCENTAGE of the panel width, so it
                                looks the same on a laptop and a phone. 0% = picture edge to edge. */
  position: relative;
  width: min(100%, calc((100svh - var(--nav-h) - 4.5rem) * .8), var(--stage-max));
  aspect-ratio: var(--stage-ratio);
  margin-inline: auto;
}

/* Static stage: one picture (or clip) per step, swapped with no motion. The drawing beneath is the fallback. */
.stage__panel--static .scene { transition: none; transform: none; filter: none; }
.stage__panel--static .scene > img,
.stage__panel--static .scene > video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: var(--stage-fit);
  padding: var(--stage-pad);
  z-index: 2;
}
.stage__panel {
  position: absolute; inset: 0;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: linear-gradient(160deg, var(--lavender), var(--peach));
  box-shadow: var(--shadow-card);
  isolation: isolate;
}
.stage__bg { position: absolute; inset: 0; opacity: 0; }
.stage__bg[data-bg="1"] { background: linear-gradient(160deg, #eee6ff, #ffe8dc); opacity: 1; }
.stage__bg[data-bg="2"] { background: linear-gradient(160deg, #e3f6ec, #eee6ff); }
.stage__bg[data-bg="3"] { background: linear-gradient(160deg, #ffe1e8, #ffe8dc); }
.stage__bg[data-bg="4"] { background: linear-gradient(160deg, #eee6ff, #e3f6ec); }
.stage__bg[data-bg="5"] { background: linear-gradient(160deg, #ffe8dc, #fff4cc); }
.stage__bg[data-bg="6"] { background: linear-gradient(160deg, #fff4cc, #e3f6ec); }
.stage__bg[data-bg="7"] { background: linear-gradient(160deg, #eee6ff, #ffe1e8); }
.stage__bg[data-bg="8"] { background: linear-gradient(160deg, #eee6ff, #ffe8dc); }

/* Layers: the box's top-left corner sits on the stage centre; the inner is pulled back by half,
   so GSAP's x/y/scale/rotation on .layer act around the object's visual centre. */
.layer {
  position: absolute; left: 50%; top: 50%;
  transform-origin: 0 0;
  will-change: transform;
}
.layer__in { width: 100%; height: 100%; transform: translate(-50%, -50%); }
.layer--pack    { width: 46%; aspect-ratio: 4 / 5; z-index: 2; }
.layer--phone   { width: 34%; aspect-ratio: 9 / 18.5; z-index: 4; }
.layer--gift    { width: 52%; aspect-ratio: 1; z-index: 3; }
.layer--sticker { width: 15%; aspect-ratio: 1 / 1.24; z-index: 5; }
.layer--phone-recipient { z-index: 6; }

/* Objects (built on the site's illustration primitives) */
.layer .pack { width: 100%; height: 100%; }
.obj-pack .pack__label small { color: var(--ink-soft); }
.layer .gift { width: 100%; height: 100%; }
.obj-gift .gift__ribbon::before, .obj-gift .gift__ribbon::after { width: 230%; height: 12%; top: -13%; }
.obj-phone {
  width: 100%; height: 100%;
  padding: 4%;
  border-radius: 12% / 6%;
  background: linear-gradient(160deg, #303a52, #151a26);
  box-shadow: var(--shadow-float), inset 0 0 0 1.5px rgba(255,255,255,.08);
}
.obj-phone__screen {
  position: relative; width: 100%; height: 100%;
  border-radius: 10% / 5%;
  overflow: hidden;
  background: #fff;
}
.obj-phone__screen { container-type: inline-size; }
.obj-phone .mini-screen b { font-size: clamp(.6rem, 9cqw, 1rem); }
.obj-phone .mini-screen small { font-size: clamp(.5rem, 6.5cqw, .75rem); text-wrap: balance; }
.obj-phone .mini-btn { font-size: clamp(.5rem, 6.5cqw, .85rem); padding: .3em .8em; white-space: nowrap; }
.obj-phone .mini-toast { font-size: clamp(.5rem, 6cqw, .72rem); }
.obj-phone .mini-rec-time { font-size: clamp(.5rem, 6cqw, .75rem); }
.scr { position: absolute !important; inset: 0; opacity: 0; visibility: hidden; }
.scr[data-scr="store"], .scr[data-scr="camera"] { opacity: 1; visibility: inherit; }
.scr__ok {
  padding: .35em .9em; border-radius: var(--r-pill);
  white-space: nowrap;
  background: var(--mint); color: #145c38 !important;
  font-weight: 800 !important;
}
.mini-screen--scan .scr__ok { opacity: 0; }

.obj-sticker {
  width: 100%; height: 100%;
  display: flex; flex-direction: column; align-items: center;
  padding: 8% 8% 6%;
  background: #fff;
  border-radius: 14% / 11%;
  box-shadow: var(--shadow-float);
}
.obj-sticker__qr { width: 100%; }
.obj-sticker__cap {
  margin-top: 6%;
  font-size: clamp(.45rem, .7vw, .62rem);
  font-weight: 800; letter-spacing: .01em;
  color: var(--purple);
  line-height: 1;
}

.tag--purple { background: var(--purple-tint); color: #5a2ed6; } /* 6.2:1 on the tint */
/* Your own pictures (assets/img/journey/): when a file loads it replaces the CSS drawing of that object */
.obj-img { display: none; width: 100%; height: 100%; object-fit: contain; }
.layer.has-img .obj-img { display: block; filter: drop-shadow(0 18px 28px rgba(31, 46, 77, .28)); }
.layer.has-img .obj-pack, .layer.has-img .obj-sticker, .layer.has-img .obj-gift { display: none; }
.scr__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 2; }
.scr.has-img > :not(.scr__img):not(.scr__ok) { display: none; }
.scr.has-img .scr__ok { position: absolute; left: 0; right: 0; bottom: 9%; width: max-content; margin-inline: auto; z-index: 3; }

.stage__tags { position: absolute; top: 6%; right: 6%; z-index: 7; height: 2rem; }
.stage__tag {
  position: absolute; right: 0; top: 0;
  white-space: nowrap;
  box-shadow: var(--shadow-card);
  opacity: 0; visibility: hidden;
}
.stage__tag[data-tag="1"] { opacity: 1; visibility: inherit; }

/* Without GSAP the stage shows step one, still and complete */
.stage:not(.has-gsap) .layer--phone, .stage:not(.has-gsap) .layer--gift { display: none; }
.stage:not(.has-gsap) .layer--pack { transform: translate(0, -3%); }
.stage:not(.has-gsap) .layer--sticker { left: 63%; top: 31%; transform: rotate(-8deg) scale(1.1); }

/* The rail: eight numbered stops in the column gap */
.rail {
  position: absolute; left: -3.4rem; top: 50%;
  transform: translateY(-50%);
  display: grid; gap: .45rem;
  z-index: 8;
}
.rail li { position: relative; z-index: 1; }
.rail__btn {
  width: 2rem; height: 2rem; border-radius: 50%;
  display: grid; place-items: center;
  font-size: var(--t-micro); font-weight: 800;
  color: var(--ink-soft);
  background: var(--paper);
  border: 1.5px solid var(--line);
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast), transform var(--dur-fast) var(--ease-out);
}
.rail__btn.is-active { background: var(--purple); border-color: var(--purple); color: #fff; transform: scale(1.08); }
.rail__btn:active { transform: scale(.94); }
.rail__track {
  position: absolute; left: 50%; top: 1rem; bottom: 1rem; width: 2px;
  transform: translateX(-50%);
  background: var(--line);
  border-radius: var(--r-pill); z-index: 0;
}
.rail__fill {
  display: block; width: 100%; height: 100%;
  background: var(--purple);
  transform-origin: top;
  transform: scaleY(var(--p, 0));
}

/* The step label under the picture on phones, in place of the row of orbs */
.stepnote { display: none; }

/* ---------- Steps ---------- */
.journey__steps { padding-top: .25rem; }
.steps__title { font-size: clamp(1.5rem, 2.6vw, 2rem); letter-spacing: -.02em; }
/* the same blue rule every other section heading carries, so this reads as a beginning */
.steps__title::after {
  content: "";
  display: block;
  width: 56px; height: 4px;
  margin: .9rem 0 0;
  border-radius: 2px;
  background: var(--blue);
}
.steps__sub { margin-top: .9rem; color: var(--ink-soft); max-width: 34ch; }
.steps { display: grid; margin-top: 1rem; }
.jstep {
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: 1.1rem;
  padding: 1.35rem 0;
  opacity: .34;
  transition: opacity 200ms var(--ease-out);
}
.jstep + .jstep { border-top: 1px solid var(--line); }
.steps { padding-bottom: 10vh; } /* just enough to hold the sticky picture while the last step is read */
.jstep.is-active { opacity: 1; }
.jstep__num {
  display: grid; place-items: center;
  width: 44px; height: 44px; border-radius: 50%;
  margin-top: .25rem;
  font-weight: 800; font-size: 1rem;
  color: var(--ink);
  background: var(--mist-deep);
  transition: background var(--dur-base), color var(--dur-base), transform var(--dur-base) var(--ease-out);
}
.jstep.is-active .jstep__num { background: var(--blue); color: #fff; transform: scale(1.06); }
.jstep[data-step="1"] .jstep__num { background: var(--purple); color: #fff; }
.jstep__body h3 { font-size: clamp(1.35rem, 1.9vw, 1.7rem); margin: .5rem 0 .6rem; max-width: 22ch; text-wrap: balance; }
.jstep__body p { max-width: 42ch; }
.jstep__body p + p { margin-top: .5rem; }
.jstep__cta { margin-top: 1rem; }
.jstep__links { margin-top: .6rem; display: flex; gap: .6rem; font-weight: 700; color: var(--blue-deep); }

/* ---------- Dock ---------- */
.dock {
  position: fixed; left: 50%; bottom: max(1rem, env(safe-area-inset-bottom));
  z-index: 90;
  display: flex; align-items: center; gap: .6rem;
  padding: .5rem .5rem .5rem 1.1rem;
  border-radius: var(--r-pill);
  background: rgba(255,255,255,.88);
  border: 1px solid rgba(255,255,255,.7);
  box-shadow: var(--shadow-nav);
  backdrop-filter: blur(16px) saturate(1.4);
  -webkit-backdrop-filter: blur(16px) saturate(1.4);
  transform: translate(-50%, 140%);
  opacity: 0; visibility: hidden;
  transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-fast), visibility 0s linear var(--dur-base);
}
.dock.is-visible { transform: translate(-50%, 0); opacity: 1; visibility: visible; transition-delay: 0s; }
.dock .btn { padding: .65rem 1.15rem; font-size: var(--t-small); }
.dock__where {
  display: flex; align-items: baseline; gap: .35rem;
  margin-right: .4rem;
  font-size: var(--t-small); font-weight: 700; color: var(--ink);
  white-space: nowrap;
}
.dock__where b { font-size: 1.1rem; color: var(--purple); font-variant-numeric: tabular-nums; }
.dock__of { color: var(--ink-soft); font-weight: 600; }
.dock.is-past .dock__where { display: none; }
.dock.is-past { padding-left: .5rem; }

/* ---------- Moments (editorial, not three equal cards) ---------- */
.mgrid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: clamp(1.25rem, 2.5vw, 2rem);
}
.mo { display: grid; border-radius: var(--r-lg); overflow: hidden; }
.mo__media { margin: 0; overflow: hidden; }
.mo__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 900ms var(--ease-out); }
.mo__body { padding: clamp(1.4rem, 2.5vw, 2.2rem); }
.mo__body h3 { font-size: var(--t-h3); margin-bottom: .6rem; }
.mo__body b { color: var(--ink); font-weight: 800; }
.mo--lead {
  grid-column: 1 / -1;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  align-items: stretch;
  background: var(--mint);
}
.mo--lead .mo__media { aspect-ratio: 3 / 2; }
.mo--lead .mo__body { align-self: center; padding: clamp(1.6rem, 3vw, 2.8rem); }
.mo--lead .mo__body h3 { font-size: clamp(1.5rem, 2.4vw, 2rem); }
.mo--peach { grid-column: 1 / 8; background: var(--peach); }
.mo--lavender { grid-column: 8 / -1; background: var(--lavender); }
.mo--peach .mo__media, .mo--lavender .mo__media { aspect-ratio: 16 / 10; }

/* ---------- Reviews: placeholders say so ---------- */
.reviews__note { margin-top: .25rem; font-size: var(--t-small); color: var(--ink-soft); text-align: center; }

/* ---------- App placeholders: labelled options, not blank blocks ---------- */
.page-alt2 .phone__ph-hero { position: relative; display: grid; place-items: center; }
.page-alt2 .phone__ph-hero .mini-face { width: 34%; }
.page-alt2 .phone__ph-hero .mini-rec-time { top: 8%; left: 8%; font-size: clamp(.5rem, .8vw, .7rem); }
.page-alt2 .phone__ph-row i, .page-alt2 .phone__ph-grid i {
  display: grid; place-items: end start; padding: 6%;
  font-style: normal; font-weight: 800; color: var(--ink);
  font-size: clamp(.5rem, .8vw, .68rem); line-height: 1.15;
}
.page-alt2 .phone__ph-clip {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 8%;
  font-size: clamp(.5rem, .8vw, .7rem); color: var(--ink);
}
.page-alt2 .phone__ph-clip b { font-weight: 800; }
.page-alt2 .phone__ph-clip small { font-size: .9em; color: var(--ink-soft); font-variant-numeric: tabular-nums; }

/* ---------- "Why this matters" as a hero band over the gift photo ---------- */
.why2 { min-height: 100svh; padding: clamp(4rem, 9vw, 7rem) 0 4rem; }
.why2 .hero__img { object-position: 70% center; }
@media (max-width: 960px) {
  /* the phone image is already cropped to portrait, so it needs no repositioning */
  .why2 .hero__img { object-position: center; }
  /* narrow screens: the photo sits behind the text, so the whole band gets a heavier, even scrim */
  .why2 .hero__scrim { background: linear-gradient(180deg, rgba(14, 22, 40, .8) 0%, rgba(14, 22, 40, .66) 60%, rgba(14, 22, 40, .74) 100%); }
}
/* the belief lines: white on the scrim, not the page's navy ink */
.why2__beliefs { color: #fff; }
/* reveal on scroll instead of the hero's load-time entrance */
.js .why2 .hero__line, .js .why2 .hero__actions, .js .why2 .hero__trust, .js .why2 .stats, .js .why2 .chip { animation: none; opacity: 1; transform: none; }
.js .why2 .reveal { opacity: 0; transform: translateY(12px); }
.js .why2 .reveal.is-in { opacity: 1; transform: none; transition: opacity var(--dur-reveal) var(--ease-out), transform var(--dur-reveal) var(--ease-out); }

/* ---------- Mission on peach ---------- */
.mission--peach { background: var(--peach); }
.mission--peach .mission__beliefs { color: var(--ink); }

/* ---------- Final ---------- */
.final2 .final__media img { object-position: center 40%; }

/* ---------- Vendors with the shop illustration ---------- */
.vendors2__inner {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
.vendors2 .vendors__copy .btn { margin-top: 1.2rem; }
.vendors2__art { margin: 0; border-radius: var(--r-lg); overflow: hidden; aspect-ratio: 4 / 3; }
.vendors2__art img { width: 100%; height: 100%; object-fit: cover; }

/* ---------- Hover (only where hover exists) ---------- */
@media (hover: hover) and (pointer: fine) {
  .page-alt2 .btn--primary:hover { background: #0b5ec4; } /* 6.1:1 */
  .btn--soft:hover { background: #d6e8ff; transform: translateY(-1px); }
  .rail__btn:hover { border-color: var(--purple); color: var(--purple); }
  .rail__btn.is-active:hover { color: #fff; }
  .mo:hover .mo__media img { transform: scale(1.03); }
}

/* ---------- Entrance (GSAP animates these in; nothing hides without it) ---------- */
html.gsap .page-alt2 [data-in] { opacity: 0; }

/* ---------- Responsive ---------- */
@media (max-width: 1100px) {
  .rail { left: -2.9rem; }
  .rail__btn { width: 1.8rem; height: 1.8rem; }
}

@media (max-width: 960px) {
  /* The bar gets out of the way as soon as the hero is behind you: a phone screen is mostly content. */
  :root { --nav-h-min: 46px; }
  .nav { padding-top: .9rem; }
  .nav.is-scrolled .nav__bar { transform: translateY(-.55rem); }
  .nav__bar { transition: transform var(--dur-base) var(--ease-out), height var(--dur-base) var(--ease-out), background var(--dur-base); }
  .nav.is-scrolled .nav__mark { width: 32px; height: 32px; }
  .nav.is-scrolled .nav__name { font-size: 1.05rem; }
  .nav.is-scrolled .nav__toggle { width: 38px; height: 38px; }
  .nav__mark, .nav__name, .nav__toggle { transition: width var(--dur-base) var(--ease-out), height var(--dur-base) var(--ease-out), font-size var(--dur-base) var(--ease-out); }

  .journey__grid {
    grid-template-columns: 1fr;
    grid-template-areas:
      "copy"
      "intro"
      "stage"
      "steps";
  }
  /* The marquee hands straight over to the journey — no dead band between them. */
  .journey { padding-top: 1.6rem; }

  /* One centred column: headline, its italic line, the two lead sentences and the reassurances. */
  .journey__copy { text-align: center; }
  .hero2__title { max-width: 16ch; margin-inline: auto; }
  .hero2__lead { margin-inline: auto; }
  .flow { justify-content: center; }
  .hero2__lead + .hero2__lead { margin-top: .6rem; }
  .paths__q, .paths__note { text-align: center; }
  .assure { justify-content: center; }
  .journey__stage {
    top: 0; z-index: 5;
    margin-top: 2rem;
    padding: calc(var(--nav-h-min) + .55rem) 0 .3rem;
    background: var(--paper);
  }
  .stage { width: 100%; max-width: 560px; aspect-ratio: auto; }
  .stage__panel { position: relative; inset: auto; width: 100%; }
  .stage__panel:not(.stage__panel--static) { aspect-ratio: 4 / 3; }
  /* Phones: keep the panel the same portrait shape as the pictures and cap it by height, so the
     picture fills it the way it does on a laptop instead of being letterboxed in a square.
     The width is worked out from the height and the ratio — calc reads "4 / 5" as 0.8. */
  .stage__panel--static {
    width: min(100%, calc(var(--stage-h-mobile) * (var(--stage-ratio))));
    height: auto;
    aspect-ratio: var(--stage-ratio);
    margin-inline: auto;
  }
  .layer--pack    { width: auto; height: 68%; }
  .layer--phone   { width: auto; height: 74%; }
  .stage__tags { left: 4%; right: auto; }
  .stage__tag { left: 0; right: auto; }
  .layer--gift    { width: auto; height: 60%; }
  .layer--sticker { width: auto; height: 22%; }
  .rail { display: none; } /* replaced by .stepnote below */
  .stepnote {
    display: flex; flex-direction: column; align-items: center; gap: .4rem;
    margin: .6rem auto 0;
    width: min(100%, calc(var(--stage-h-mobile) * (var(--stage-ratio))));
  }
  .stepnote__text { font-size: var(--t-small); font-weight: 700; color: var(--ink-mute); }
  .stepnote__text b { font-size: 1.05rem; font-weight: 800; color: var(--purple); }
  .stepnote__bar { width: 100%; height: 3px; border-radius: 2px; background: var(--line); overflow: hidden; }
  .stepnote__bar i {
    display: block; height: 100%; border-radius: 2px; background: var(--purple);
    transform: scaleX(var(--p, 0)); transform-origin: left;
    transition: transform var(--dur-base) var(--ease-out);
  }

  /* Tighter step text: the pictures are screenshots full of small detail, so they get the room. */
  .jstep__body h3 { font-size: 1.22rem; margin: .1rem 0 .35rem; line-height: 1.2; }
  .jstep__body p { font-size: 1rem; line-height: 1.45; }
  .jstep__cta { margin-top: .75rem; }
  .rail__track { display: none; }
  .rail__btn { width: 1.9rem; height: 1.9rem; }
  .journey__steps { padding-top: 1.5rem; }
  .jstep { padding: 1.2rem 0; opacity: 1; }
  .steps { padding-bottom: 12vh; }
  .jstep.is-active .jstep__num { transform: none; }
  .jstep__body h3 { margin-top: .3rem; }

  .dock {
    left: 0; right: 0; bottom: 0;
    transform: translateY(120%);
    border-radius: var(--r-md) var(--r-md) 0 0;
    padding: .7rem var(--gutter) calc(.7rem + env(safe-area-inset-bottom));
    gap: .5rem;
  }
  .dock.is-visible { transform: translateY(0); }
  .dock__where { display: none; }
  /* Both docked labels stay on one line at every phone width: they shrink to fit rather than wrap. */
  .dock .btn {
    flex: 1 1 auto; min-width: 0;
    padding: .8rem .5rem;
    white-space: nowrap; text-align: center;
    font-size: clamp(.78rem, 3.4vw, .9375rem);
  }

  /* Text slides under the sticky picture as you scroll; fade it out rather than chopping a line in half. */
  .journey__stage::after, .app__stage::after {
    content: ""; position: absolute; left: 0; right: 0; top: 100%;
    height: 1.5rem; pointer-events: none;
  }
  .journey__stage::after { background: linear-gradient(var(--paper), rgba(255,255,255,0)); }
  .app__stage::after { background: linear-gradient(var(--mist), rgba(245,248,252,0)); }

  /* The app screenshots carry fine detail too — show them bigger, and let the dots recede. */
  .app__stage { padding: calc(var(--nav-h-min) + .55rem) 0 .4rem; }
  .app__stage .phone__frame { width: 216px; padding: 9px; border-radius: 34px; }
  .app__stage .phone__screen { border-radius: 26px; }
  .app__stage .phone__notch { top: 14px; height: 17px; width: 34%; }
  .app--six .app__feature { padding: 1rem 0; }
  .app--six .app__feature h3 { font-size: 1.15rem; margin-bottom: .2rem; }
  .app--six .app__feature p { font-size: 1rem; line-height: 1.45; }
  .app--six .chip-icon { width: 44px; height: 44px; }
  .app--six .chip-icon svg { width: 20px; height: 20px; }

  /* Phones: the three moments run sideways instead of stacking, the same gesture as the reviews
     below them. It turns roughly three screens of scrolling into one. The track breaks out of the
     container's gutter so cards reach the screen edge, and the next one peeks to show it moves. */
  .mgrid {
    display: flex;
    gap: 1rem;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    margin-inline: calc(var(--gutter) * -1);
    padding: .25rem var(--gutter) 1rem;
    scroll-padding-inline: var(--gutter);
  }
  .mgrid::-webkit-scrollbar { display: none; }
  /* The per-card scroll reveal is for the stacked desktop grid. In a sideways track the next card
     sits mostly off-screen, falls under the observer's threshold and never fades in — so the peek
     that tells you the row scrolls would be invisible. The cards simply arrive with the section. */
  .js .mgrid .reveal { opacity: 1; transform: none; }
  .mo {
    flex: 0 0 min(80vw, 340px);
    scroll-snap-align: start;
    border: 1px solid var(--line);
  }
  /* one media shape across the three, so the row reads as a set rather than three odd sizes */
  .mo--lead { grid-template-columns: 1fr; }
  .mo--lead .mo__media,
  .mo--peach .mo__media,
  .mo--lavender .mo__media { aspect-ratio: 4 / 3; }
  .mo--lead .mo__body { align-self: start; }
  .mo__body { padding: 1.1rem 1.15rem 1.3rem; }
  .mo--lead .mo__body h3, .mo__body h3 { font-size: 1.2rem; margin-bottom: .4rem; }
  .mo__body p { font-size: var(--t-small); line-height: 1.5; }

  .vendors2__inner { grid-template-columns: 1fr; }
  .vendors2__art { max-width: 520px; }
}

@media (max-width: 560px) {
  .hero2__title { font-size: 2.4rem; }
  .hero2__em { font-size: .6em; }
  .paths__item { padding: 1.1rem 1.1rem 1.15rem; }
  .paths__stores { flex-direction: column; }
  .paths__stores .badge { justify-content: center; }
  .assure { gap: .4rem .9rem; }
  .stage__panel:not(.stage__panel--static) { aspect-ratio: 5 / 4; }
  .stage__tags { top: 5%; right: 5%; }
  .jstep { grid-template-columns: 36px 1fr; gap: .9rem; }
  .jstep__num { width: 36px; height: 36px; font-size: .9rem; }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html.gsap .page-alt2 [data-in] { opacity: 1; }
  .js .why2 .reveal { opacity: 1; transform: none; }
  .jstep { transition: none; }
  .mo__media img { transition: none; }
  .dock { transition: opacity var(--dur-fast), visibility 0s linear var(--dur-fast); transform: translate(-50%, 0); }
  .dock.is-visible { transform: translate(-50%, 0); }
  .rail__btn.is-active { transform: none; }
}
@media (prefers-reduced-motion: reduce) and (max-width: 960px) {
  .dock, .dock.is-visible { transform: none; }
}

/* ---------- The app section's slide dots: markers, not furniture ---------- */
.page-alt2 .app__dots { gap: .4rem; }
.page-alt2 .app__dots i {
  width: 6px; height: 6px; border-radius: 50%;
  background: #c9d3e2; transform: none;
  transition: background var(--dur-base);
}
.page-alt2 .app__dots i.is-active { width: 18px; border-radius: 3px; background: var(--purple); }

}

/* =========================================================
   "Know a real QKeep sticker" — the security section
   The artwork is a plain <img>; every marker is placed over it by the --x/--y on its
   own element, so swapping the sticker design means editing those numbers and nothing else.
   ========================================================= */
.security {
  background: linear-gradient(180deg, var(--paper) 0%, var(--lavender) 55%, var(--paper) 100%);
}
.secure { position: relative; }

.secure__art {
  position: relative;
  margin: 0 auto;
  width: 100%;
  max-width: 520px;
}
.secure__art img { width: 100%; height: auto; filter: drop-shadow(0 26px 40px rgba(31, 46, 77, .26)); }

/* A marker: sits at its own --x/--y over the artwork, its centre on that point */
.secure__pin {
  position: absolute;
  left: var(--x); top: var(--y);
  width: 2.1rem; height: 2.1rem;
  margin: -1.05rem 0 0 -1.05rem;
  display: grid; place-items: center;
  border-radius: 50%;
  font-size: var(--t-small); font-weight: 800; line-height: 1;
  color: #fff; background: var(--purple);
  box-shadow: 0 2px 4px rgba(31, 46, 77, .25), 0 10px 22px -8px rgba(31, 46, 77, .55);
  transition: transform var(--dur-fast) var(--ease-out), background var(--dur-fast);
}
/* the soft ring that makes a marker read as "look here" */
.secure__pin::after {
  content: "";
  position: absolute; inset: -6px;
  border-radius: 50%;
  border: 2px solid var(--purple);
  opacity: .45;
  animation: secure-ring 2.6s var(--ease-out) infinite;
}
.secure__pin[data-secure="2"]::after { animation-delay: .35s; }
.secure__pin[data-secure="3"]::after { animation-delay: .7s; }
.secure__pin[data-secure="4"]::after { animation-delay: 1.05s; }
@keyframes secure-ring {
  0%   { transform: scale(.88); opacity: .5; }
  70%  { transform: scale(1.5); opacity: 0; }
  100% { transform: scale(1.5); opacity: 0; }
}
.secure__pin.is-lit, .secure__pin:focus-visible { transform: scale(1.18); background: var(--blue-deep); }
.secure__pin:active { transform: scale(.94); }

/* A feature card */
.secure__list { display: grid; gap: .9rem; margin: 0; padding: 0; list-style: none; }
.secure__item {
  display: grid; grid-template-columns: 2rem 1fr; gap: .85rem;
  padding: 1rem 1.15rem;
  border-radius: var(--r-md);
  background: var(--paper);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-card);
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out), border-color var(--dur-fast);
}
.secure__item.is-lit { transform: translateY(-2px); border-color: var(--purple); box-shadow: var(--shadow-float); }
.secure__num {
  display: grid; place-items: center;
  width: 2rem; height: 2rem; border-radius: 50%;
  font-size: var(--t-small); font-weight: 800; line-height: 1;
  color: #fff; background: var(--purple);
}
.secure__item h3 { font-size: 1.1rem; margin-bottom: .25rem; }
.secure__item p { font-size: var(--t-small); }

.secure__note {
  max-width: 62ch; margin: clamp(2rem, 4vw, 3rem) auto 0;
  padding: 1rem 1.25rem;
  border-radius: var(--r-md);
  background: var(--paper);
  border: 1px solid var(--line);
  text-align: center; font-size: var(--t-small);
}
.secure__note strong { color: var(--purple); }

/* ---------- Laptops: the sticker holds the centre, the four cards sit around it ---------- */
@media (min-width: 961px) {
  .secure { min-height: 34rem; display: grid; place-items: center; }
  .secure__art { max-width: 460px; grid-area: 1 / 1; }
  .secure__list { grid-area: 1 / 1; width: 100%; height: 100%; display: block; pointer-events: none; }
  .secure__item {
    position: absolute; width: min(28%, 19rem);
    pointer-events: auto;
  }
  .secure__item[data-secure="1"] { left: 0;  top: 0; }
  .secure__item[data-secure="4"] { left: 0;  bottom: 0; }
  .secure__item[data-secure="2"] { right: 0; top: 0; }
  .secure__item[data-secure="3"] { right: 0; bottom: 0; }
  /* real leader lines, drawn from the measured positions in js/alt2.js */
  .secure__wires {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    overflow: visible; pointer-events: none; z-index: 0;
  }
  .secure__wires path {
    fill: none;
    stroke: var(--purple);
    stroke-width: 1.6;
    stroke-linecap: round;
    opacity: .34;
    transition: opacity var(--dur-fast);
  }
  .secure__wires path.is-lit { opacity: .95; }
  .secure__art { z-index: 1; }
  .secure__item { z-index: 2; }
}

/* ---------- Phones: the sticker as large as it will go, then the list ---------- */
@media (max-width: 960px) {
  .secure { display: grid; gap: 1.2rem; }
  .secure__art { max-width: 100%; }
  .secure__pin { width: 1.9rem; height: 1.9rem; margin: -.95rem 0 0 -.95rem; }

  /* The four features run sideways under the sticker, the same gesture as Moments and the
     reviews. The track breaks out of the container's gutter so cards reach the screen edge,
     and the next one peeks to show the row moves. */
  .secure__list {
    display: flex;
    gap: 1rem;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    margin-inline: calc(var(--gutter) * -1);
    padding: .25rem var(--gutter) 1rem;
    scroll-padding-inline: var(--gutter);
  }
  .secure__list::-webkit-scrollbar { display: none; }
  .secure__item {
    flex: 0 0 min(80vw, 330px);
    scroll-snap-align: start;
    padding: 1rem 1.1rem 1.15rem;
  }
}

/* ---------- Motion: entrances are set up in js/alt2.js; this is the resting state ---------- */
html.gsap .security [data-reveal] { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  html.gsap .security [data-reveal] { opacity: 1; }
  .secure__pin::after { animation: none; }
  .secure__pin, .secure__item { transition: none; }
}

/* ---------- Clips inside the app carousel ----------
   .app-scene styles its <img> but nothing else; a <video> needs the same treatment, one layer
   above the still so a slide can carry both (the still shows until the clip is ready). */
.app-scene video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 3;
  background: #fff;
}

/* ---------- The two paths, now a band of their own after the eight steps ---------- */
/* it follows straight on from the last step, so it needs less air above it than a fresh section */
.pathsband { padding-top: clamp(1.75rem, 3vw, 2.5rem); }
.pathsband .paths { margin-top: 0; }
.pathsband .assure { justify-content: center; margin-top: 1.1rem; }
@media (min-width: 961px) {
  /* Side by side, and on the page's own 1200px grid so it lines up with every other section
     rather than floating as a narrow box in the middle of a wide screen. */
  .pathsband .paths { grid-template-columns: 1fr 1fr; }
  .pathsband .paths__item + .paths__item { border-top: 0; border-left: 1px solid var(--line); }
  .pathsband .paths__item {
    display: grid;
    align-content: start;
    justify-items: center;
    padding: clamp(1.5rem, 2.6vw, 2.25rem) clamp(1.6rem, 3vw, 2.75rem);
    text-align: center;
  }
  /* the button sizes to its label at this width instead of stretching the full column */
  .pathsband .paths__cta { width: auto; }
  .pathsband .paths__stores { justify-content: center; }
  .pathsband .paths__q { font-size: 1.05rem; }
}
@media (max-width: 960px) {
  .journey__intro {
    margin-top: 2.25rem;
    padding-top: 2.25rem;
    border-top: 1px solid var(--line);   /* a clean break from the hero copy above */
    text-align: center;
  }
  .journey__intro .steps__title::after { margin-inline: auto; }
  .journey__intro .steps__sub { margin-inline: auto; }
  .steps { padding-bottom: 6vh; }
  .journey { padding-bottom: .5rem; }
  .pathsband { padding-top: 1.75rem; }
}

/* ---------- Example scenes: the label travels with the card ----------
   The track scrolls sideways, so a single note under the section is easy to miss. Each card
   carries its own flag, which is what keeps the illustrations from reading as testimonials. */
.review-card__flag {
  position: absolute; top: .9rem; left: .9rem; z-index: 3;
  padding: .3rem .7rem;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .92);
  color: var(--ink);
  font-size: var(--t-micro); font-weight: 800; letter-spacing: .01em;
  box-shadow: var(--shadow-card);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.page-alt2 .review-card footer span { font-weight: 700; color: var(--ink-mute); }
