/* v24: the hero's story (since v25 Pooja's Birthday, assets/landing/moment; photo paths in js/landing-photos.js): the three proofs
   under the hero (the best rise, a close call, ten seconds). v25 tells the reframe around them (the
   human problem, same moment from many views, start and scan in, the Album, start): see "v25" further
   down; v26's private live Album, straight under the hero, is at the very end. The hero's own scene is in css/hero.css. Every loop moves only
   transform and opacity, plays → holds → fades softly → starts again, and never shows a reset.
   hero-story.js decides when they run (.story-enhanced, [data-playing], .story-suspended); without it,
   or with reduced motion, each demo simply shows its final frame. Scoped to .hero-story. */

/* ---------- Shared by the three proofs ---------- */
.story-demo { position: relative; width: 100%; min-width: 0; justify-self: center; }
.story-caption { margin-top: 18px; font-size: 14px; color: var(--muted); text-align: center; }

/* ---------- The best rise: the slots stay, the photos travel; the crown belongs to #1 ---------- */
.story-rank { --row: 74px; max-width: 440px; }
.story-rank-stage { position: relative; display: grid; grid-template-columns: 40px minmax(0, 1fr); column-gap: 6px; }
.story-rank-labels { display: grid; grid-auto-rows: var(--row); }
.story-rank-labels li {
  display: flex; flex-direction: column; justify-content: center; gap: 2px; padding-bottom: 10px;
  font-size: 15px; font-weight: 650; font-variant-numeric: tabular-nums; color: var(--muted);
}
.story-rank-labels li:first-child { color: var(--gold-ink); }
.story-crown { width: 22px; height: 16.5px; fill: url(#crown-gold); filter: drop-shadow(0 0 2px #f3bd4a8c); transform-origin: 50% 80%; }
.story-rank-rows { position: relative; height: calc(var(--row) * 4); min-width: 0; }
.story-rank-row {
  --end: 0; position: absolute; left: 0; right: 0; top: 0; height: calc(var(--row) - 10px);
  display: flex; align-items: center; gap: 12px; padding: 5px 12px 5px 5px; border-radius: 10px; background: #fff;
  box-shadow: 0 1px 2px #3a3a2a14; transform: translateY(calc(var(--end) * var(--row)));
}
.story-rank-row::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: 0 16px 28px -14px #3a3a2a6b; opacity: 0; pointer-events: none; }
.story-rank-row img { flex-shrink: 0; width: 86px; height: 54px; object-fit: cover; border-radius: 6px; background: #e9ebe5; }
.story-rank-row span { display: grid; min-width: 0; font-size: 15px; line-height: 1.3; }
.story-rank-row small { font-size: 13px; color: var(--muted); }
/* Final order (also the static frame): the lookout first, then breakfast, the walk, the low angle. */
.story-rank-hero { --end: 0; z-index: 2; }
.story-rank-breakfast { --end: 1; }
.story-rank-walk { --end: 2; }
.story-rank-angle { --end: 3; }
.story-rank-moth { position: absolute; z-index: 3; right: 8px; top: calc((var(--row) - 10px) / 2 - 17px); width: 34px; height: 34px; pointer-events: none; }

/* ---------- A close call: two whole photos side by side, even on a 360 px phone ---------- */
.story-compare { max-width: 440px; }
.story-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; padding-top: 24px; perspective: 1000px; }
.story-pick { position: relative; display: block; min-width: 0; padding: 0; border-radius: 4px; transform-origin: 50% 100%; -webkit-tap-highlight-color: transparent; }
.story-pick img {
  display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border: 5px solid var(--print-edge);
  border-radius: 4px; background: #e9ebe5; box-shadow: 0 1px 3px #3a3a2a24;
}
.story-pick::after { content: ""; position: absolute; inset: 10% 6% 0; z-index: -1; border-radius: 10px; box-shadow: 0 24px 30px -14px #3a3a2a66; opacity: 0; pointer-events: none; }
.story-pick:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.story-heart {
  position: absolute; z-index: 2; left: 50%; top: 0; width: 28px; height: 26px; margin: -14px 0 0 -14px; fill: #e5484d;
  filter: drop-shadow(0 2px 3px #a0303333); opacity: 0; pointer-events: none;
}
.story-touch {
  position: absolute; z-index: 2; left: 56%; top: 58%; width: 30px; height: 30px; margin: -15px 0 0 -15px; border-radius: 50%;
  background: #ffffff59; border: 1.5px solid #ffffffd9; box-shadow: 0 0 0 1px #282e2b1f, 0 2px 6px #282e2b33; opacity: 0; pointer-events: none;
}
/* The chosen photo (the low angle unless someone taps the other); static frame: lifted, heart on. */
.story-compare[data-choice="left"] .story-pick:first-child,
.story-compare[data-choice="right"] .story-pick:last-child { transform: translateY(-8px) rotateX(3deg) scale(1.02); }
.story-compare[data-choice="left"] .story-pick:first-child::after,
.story-compare[data-choice="right"] .story-pick:last-child::after,
.story-compare[data-choice="left"] .story-pick:first-child .story-heart,
.story-compare[data-choice="right"] .story-pick:last-child .story-heart { opacity: 1; }
.story-compare[data-choice="left"] .story-pick:last-child,
.story-compare[data-choice="right"] .story-pick:first-child { opacity: .72; transform: scale(.985); }

/* ---------- Ten seconds: the real film Moth made from these eight photos ---------- */
.story-highlight { max-width: 430px; display: grid; justify-items: center; }
.story-video-wrap {
  position: relative; width: 216px; aspect-ratio: 9 / 16; overflow: hidden; border-radius: 12px; background: #181e1b;
  box-shadow: 0 22px 36px -22px #3a3a2a80; isolation: isolate;
}
.story-video-wrap video, .story-video-poster { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.story-video-wrap video { opacity: 0; transition: opacity .5s ease; }
.story-video-poster { transition: opacity .5s ease; }
.story-video-wrap[data-ready="true"] video { opacity: 1; }
.story-video-wrap[data-ready="true"] .story-video-poster { opacity: 0; }
.story-video-curtain { position: absolute; inset: 0; background: #181e1b; opacity: 0; pointer-events: none; }
.story-filmstrip { width: 100%; margin-top: 22px; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 4px; }
.story-filmstrip img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border-radius: 2px; background: #e9ebe5; opacity: .5; transition: opacity .3s ease; }
.story-filmstrip img.is-current { opacity: 1; }
.story-progress { width: 100%; height: 2px; margin-top: 8px; border-radius: 1px; background: #e4e6e0; overflow: hidden; }
.story-progress span { display: block; height: 100%; background: var(--gold); transform: scaleX(0); transform-origin: left; }
.story-highlight .story-caption { display: flex; align-items: center; justify-content: center; gap: 6px; }
.story-highlight .story-caption img { width: 30px; height: 30px; }

/* ---------- The loops ---------- */
@media (prefers-reduced-motion: no-preference) {
  .story-rank-moth { animation: story-moth-breathe 10s ease-in-out infinite; }

  /* The best rise, 10 s: hold the old order, the lookout lifts and climbs past the walk, then past
     breakfast, the crown settles on it, a 2 s hold, then the rows fade out, reset unseen and return. */
  .story-rank-rows, .story-crown { animation: story-rank-fade 10s ease-in-out infinite; }
  .story-rank-breakfast { animation: story-rank-breakfast 10s ease-in-out infinite; }
  .story-rank-walk { animation: story-rank-walk 10s ease-in-out infinite; }
  .story-rank-hero { animation: story-rank-hero 10s ease-in-out infinite; }
  .story-rank-hero::after { animation: story-rank-lift 10s ease-in-out infinite; }
  .story-crown { animation-name: story-crown; }

  /* A close call, 8 s: a touch, the chosen photo lifts, the heart lands, a hold, and it settles back. */
  .story-compare[data-choice="left"] .story-pick:first-child,
  .story-compare[data-choice="right"] .story-pick:last-child { animation: story-pick-lift 8s ease-in-out infinite; }
  .story-compare[data-choice="left"] .story-pick:first-child::after,
  .story-compare[data-choice="right"] .story-pick:last-child::after { animation: story-pick-shadow 8s ease-in-out infinite; }
  .story-compare[data-choice="left"] .story-pick:first-child .story-heart,
  .story-compare[data-choice="right"] .story-pick:last-child .story-heart { animation: story-heart 8s ease-in-out infinite; }
  .story-compare[data-choice="left"] .story-pick:first-child .story-touch,
  .story-compare[data-choice="right"] .story-pick:last-child .story-touch { animation: story-touch 8s ease-in-out infinite; }
  .story-compare[data-choice="left"] .story-pick:last-child,
  .story-compare[data-choice="right"] .story-pick:first-child { animation: story-pick-other 8s ease-in-out infinite; }
}
/* Before hero-story.js runs there is no motion at all (the final frames show), except the hero's
   fallback that reveals its scene and words if hero.js never arrives (hero.css, hero-late). */
.hero-story:not(.story-enhanced) :not(.hero-enter, .hero-copy), .hero-story:not(.story-enhanced) *::after { animation: none !important; }
/* Off screen, in a hidden tab or under a dialog: every loop rests where it is (play-state isn't inherited).
   Only once hero-story.js is deciding, so the fallback reveal above never waits for it. */
.hero-story.story-enhanced [data-story-loop]:not([data-playing="true"]) *,
.hero-story.story-enhanced [data-story-loop]:not([data-playing="true"]) *::after,
.hero-story.story-suspended *, .hero-story.story-suspended *::after { animation-play-state: paused !important; }

/* 0–7% rise in, 20–66% the climb, 66–85% hold, 85–94% fade, 94–100% unseen reset. */
@keyframes story-rank-fade { 0%, 94%, 100% { opacity: 0; } 7%, 85% { opacity: 1; } }
@keyframes story-rank-breakfast { 0%, 43%, 100% { transform: translateY(0); } 58%, 94% { transform: translateY(var(--row)); } }
@keyframes story-rank-walk { 0%, 22%, 100% { transform: translateY(var(--row)); } 36%, 94% { transform: translateY(calc(2 * var(--row))); } }
@keyframes story-rank-hero {
  0%, 18%, 100% { transform: translateY(calc(2 * var(--row))); }
  25% { transform: translateY(calc(2 * var(--row))) scale(1.035); }
  36%, 43% { transform: translateY(var(--row)) scale(1.035); }
  58% { transform: translateY(0) scale(1.035); }
  67%, 94% { transform: translateY(0); }
}
@keyframes story-rank-lift { 0%, 18%, 68%, 100% { opacity: 0; } 26%, 58% { opacity: 1; } }
@keyframes story-crown {
  0%, 57% { opacity: 0; transform: translateY(-5px) scale(.8); }
  64% { opacity: 1; transform: scale(1.18) rotate(-6deg); }
  70%, 85% { opacity: 1; transform: none; }
  94%, 100% { opacity: 0; transform: none; }
}
@keyframes story-moth-breathe {
  0%, 57% { opacity: 0; transform: translateY(3px) scale(.92); }
  67% { opacity: 1; transform: none; }
  76% { opacity: 1; transform: translateY(-2px) scale(1.02); }
  85% { opacity: 1; transform: none; }
  94%, 100% { opacity: 0; transform: none; }
}

/* 0–14% rest, 14–30% the touch, 24–38% lift, 44–76% heart and hold, 76–90% settle back, 90–100% rest. */
@keyframes story-touch {
  0%, 13% { opacity: 0; transform: scale(1.25); }
  18% { opacity: .9; transform: scale(1); }
  24% { opacity: .9; transform: scale(.8); }
  32%, 100% { opacity: 0; transform: scale(1.1); }
}
@keyframes story-pick-lift {
  0%, 24%, 90%, 100% { transform: none; }
  38% { transform: translateY(-12px) rotateX(4deg) scale(1.03); }
  48%, 76% { transform: translateY(-8px) rotateX(3deg) scale(1.02); }
}
@keyframes story-pick-shadow { 0%, 24%, 90%, 100% { opacity: 0; } 38%, 76% { opacity: 1; } }
@keyframes story-pick-other { 0%, 26%, 90%, 100% { opacity: 1; transform: none; } 40%, 76% { opacity: .72; transform: scale(.985); } }
@keyframes story-heart {
  0%, 36% { opacity: 0; transform: translateY(5px) scale(.5); }
  43% { opacity: 1; transform: scale(1.12); }
  48%, 74% { opacity: 1; transform: none; }
  84%, 100% { opacity: 0; transform: translateY(-3px) scale(.9); }
}

@media (prefers-reduced-motion: reduce) {
  .hero-story *, .hero-story *::after { animation: none !important; transition: none !important; }
  .story-video-wrap video, .story-video-curtain { display: none; }
  .story-video-wrap .story-video-poster { opacity: 1; }
}

/* ---------- Small phones ---------- */
@media (max-width: 370px) {
  .story-rank { --row: 68px; }
  .story-rank-row { gap: 9px; padding-right: 8px; }
  .story-rank-row img { width: 74px; height: 48px; }
  .story-rank-row span { font-size: 14px; }
  .story-rank-moth { width: 30px; height: 30px; top: calc((var(--row) - 10px) / 2 - 15px); right: 6px; }
  .story-pair { gap: 10px; }
}

/* ---------- Desktop ---------- */
@media (min-width: 900px) {
  .story-video-wrap { width: 236px; }
}

/* ---------- v25: the reframe's sections (photos from js/landing-photos.js) ---------- */
.hero-proof-text .moment-answer { margin-top: 16px; font-family: var(--serif); font-style: italic; font-size: 21px; line-height: 1.35; color: var(--ink); }
.story-demo img[data-photo]:not([src]) { visibility: hidden; } /* a slot waiting for its photo shows its frame only */

/* Everyone took photos, nobody sent them: three phones, then one stack. Final frame: the stack. */
.story-problem { max-width: 440px; }
.problem-stage { position: relative; aspect-ratio: 10 / 7; }
.problem-phone {
  position: absolute; top: 0; width: 27%; height: 80%; border-radius: 16px; background: #f1f0ea; border: 1.5px solid #d3d5ce;
  opacity: .32;
}
.problem-phone::before { content: ""; position: absolute; left: 50%; top: 6px; width: 26%; height: 4px; margin-left: -13%; border-radius: 2px; background: #d3d5ce; }
.problem-phone-1 { left: 5%; } .problem-phone-2 { left: 36.5%; } .problem-phone-3 { left: 68%; }
.problem-who { position: absolute; left: 0; right: 0; bottom: 8px; font-size: 11.5px; line-height: 1.2; color: var(--muted); text-align: center; }
.problem-print { position: absolute; top: 29%; left: 38%; width: 24%; transform-origin: 50% 60%; }
.problem-print img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; border: 3px solid var(--print-edge); border-radius: 3px; background: #e9ebe5; box-shadow: 0 8px 18px -10px #3a3a2a73; }
/* Home: inside each phone. Final: fanned together in the middle. (translate in the print's own width) */
.problem-print-1 { transform: translate(-94%, -6%) rotate(-7deg) scale(1.3); z-index: 1; }
.problem-print-2 { transform: translate(0, -14%) scale(1.3); z-index: 3; }
.problem-print-3 { transform: translate(94%, -4%) rotate(6deg) scale(1.3); z-index: 2; }
.problem-together { position: absolute; left: 0; right: 0; top: 88%; font-size: 14px; font-weight: 550; color: var(--ink); text-align: center; }

/* Same moment, different views: four frames, each with whose it is. */
.story-views { max-width: 440px; }
.views-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.views-cell { position: relative; min-width: 0; }
.views-cell img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border: 4px solid var(--print-edge); border-radius: 4px; background: #e9ebe5; box-shadow: 0 1px 3px #3a3a2a24; }
.views-who { position: absolute; left: 10px; bottom: 10px; padding: 2px 9px; border-radius: 999px; background: #fffffff0; font-size: 12px; font-weight: 600; color: var(--ink); box-shadow: 0 1px 2px #3a3a2a24; }

/* Start a Moment: the Moment screen, and friends arriving. Final frame: all three in. */
.story-start { max-width: 440px; display: grid; justify-items: center; padding: 6px 0 4px; }
.start-phone {
  width: 214px; padding: 16px 18px 18px; border-radius: 28px; background: #fff; border: 1px solid var(--line);
  box-shadow: 0 24px 40px -26px #3a3a2a80; text-align: center;
}
.start-kicker { font-size: 10px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.start-name { margin-top: 4px; font-family: var(--serif); font-size: 22px; line-height: 1.15; letter-spacing: -.03em; }
.start-qr { display: block; width: 148px; margin: 14px auto 0; padding: 8px; border-radius: 14px; border: 1px solid var(--line); background: #fff; }
.start-qr svg { display: block; width: 100%; height: auto; fill: none; stroke: var(--ink); stroke-width: 1; shape-rendering: crispEdges; }
.start-scan { margin-top: 10px; font-size: 13px; font-weight: 600; }
.start-code { margin-top: 1px; font-family: var(--mono); font-size: 14px; font-weight: 600; letter-spacing: .12em; }
.start-joins { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 18px; max-width: 360px; }
.start-join {
  display: inline-flex; align-items: center; gap: 7px; padding: 6px 12px 6px 6px; border-radius: 999px;
  background: #fff; border: 1px solid var(--line); box-shadow: 0 10px 22px -14px #3a3a2a8c; font-size: 13px; font-weight: 550; white-space: nowrap;
}
.start-dot { display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; background: var(--mine); color: var(--accent-deep); font-size: 11.5px; font-weight: 700; }

/* The Album: the Moment's, already there. */
.story-album { max-width: 420px; }
.album-card { padding: 20px 20px 18px; border-radius: 18px; background: #fff; border: 1px solid var(--line); box-shadow: 0 24px 40px -30px #3a3a2a80; }
.album-card-name { font-family: var(--serif); font-size: 24px; line-height: 1.15; letter-spacing: -.03em; }
.album-card-count { margin-top: 2px; font-size: 13px; color: var(--muted); }
.album-card-people { margin-top: 12px; }
.album-card-people li { display: flex; align-items: center; gap: 18px; padding: 12px 0; border-top: 1px solid var(--line); }
.album-card-stack { position: relative; flex-shrink: 0; width: 76px; height: 58px; }
.album-card-stack img { position: absolute; left: 4px; top: 4px; width: 66px; height: 48px; object-fit: cover; border: 2.5px solid var(--print-edge); border-radius: 6px; background: #e9ebe5; box-shadow: 0 2px 6px #28271b29; }
.album-card-stack img:nth-child(1) { transform: rotate(-7deg) translate(-2px, 2px); }
.album-card-stack img:nth-child(2) { transform: rotate(5deg) translate(3px, 0); }
.album-card-who { display: grid; font-size: 15px; font-weight: 600; line-height: 1.3; }
.album-card-who small { font-size: 12.5px; font-weight: 400; color: var(--muted); }
.album-card-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.album-chip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 999px; background: var(--surface-soft); border: 1px solid var(--line); font-size: 13px; font-weight: 550; }
.album-chip svg { width: 15px; height: 15px; fill: var(--gold); }
.album-chip:last-child svg { width: 13px; height: 13px; fill: var(--ink); }

/* Moth fits whatever your people are doing: one everyday Moment at a time (hero-story.js). */
.moment-uses { display: grid; justify-items: center; gap: 18px; text-align: center; }
.moment-uses-title { font-family: var(--serif); font-weight: 400; font-size: clamp(27px, 7vw, 40px); line-height: 1.1; letter-spacing: -.03em; text-wrap: balance; max-width: 18ch; }
.uses-stage { position: relative; width: min(100%, 560px); aspect-ratio: 3 / 2; border-radius: 6px; overflow: hidden; background: #e9ebe5; }
.uses-photo { position: absolute; inset: 0; margin: 0; opacity: 0; transition: opacity .9s ease; }
.uses-photo.is-current { opacity: 1; }
.uses-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
.uses-label { font-size: 15px; color: var(--muted); min-height: 1.5em; }

/* The last word: start one. */
.moment-cta { display: grid; justify-items: center; gap: 14px; margin: 96px var(--gutter) 0; text-align: center; }
.moment-cta h2 { font-family: var(--serif); font-weight: 400; font-size: clamp(30px, 8vw, 48px); line-height: 1.08; letter-spacing: -.035em; text-wrap: balance; }
.moment-cta p { max-width: 30em; color: #4c534f; text-wrap: pretty; }
.moment-cta .button { margin-top: 8px; min-width: 220px; }
.hero-foot-note { width: 100%; font-size: 13px; color: var(--muted); }

@media (prefers-reduced-motion: no-preference) {
  /* Problem, 10 s: the three views sit in their phones, gather into one stack, hold, fade, start again. */
  .problem-print-1 { animation: problem-1 10s ease-in-out infinite; }
  .problem-print-2 { animation: problem-2 10s ease-in-out infinite; }
  .problem-print-3 { animation: problem-3 10s ease-in-out infinite; }
  .problem-phone { animation: problem-phone 10s ease-in-out infinite; }
  .problem-together { animation: problem-together 10s ease-in-out infinite; }
  /* Views, 8 s: each frame in turn lifts a hair, as if someone held it up. */
  .views-cell { animation: views-lift 8s ease-in-out infinite; }
  .views-cell:nth-child(2) { animation-delay: -6s; }
  .views-cell:nth-child(3) { animation-delay: -4s; }
  .views-cell:nth-child(4) { animation-delay: -2s; }
  /* Start, 9 s: Mia, Jonas, Lea join one after another; a hold; they fade together. */
  .start-join-1 { animation: start-join-1 9s var(--settle) infinite; }
  .start-join-2 { animation: start-join-2 9s var(--settle) infinite; }
  .start-join-3 { animation: start-join-3 9s var(--settle) infinite; }
  /* Album, 10 s: the stacks breathe open a little and settle. */
  .album-card-stack img:nth-child(1) { animation: album-fan-back 10s ease-in-out infinite; }
  .album-card-stack img:nth-child(2) { animation: album-fan-mid 10s ease-in-out infinite; }
}
@keyframes problem-1 {
  0% { opacity: 0; transform: translate(-130%, 0) rotate(0) scale(1); }
  7%, 25% { opacity: 1; transform: translate(-130%, 0) rotate(0) scale(1); }
  50%, 85% { opacity: 1; transform: translate(-94%, -6%) rotate(-7deg) scale(1.3); }
  94%, 100% { opacity: 0; transform: translate(-94%, -6%) rotate(-7deg) scale(1.3); }
}
@keyframes problem-2 {
  0% { opacity: 0; transform: translate(0, 0) scale(1); }
  7%, 28% { opacity: 1; transform: translate(0, 0) scale(1); }
  52%, 85% { opacity: 1; transform: translate(0, -14%) scale(1.3); }
  94%, 100% { opacity: 0; transform: translate(0, -14%) scale(1.3); }
}
@keyframes problem-3 {
  0% { opacity: 0; transform: translate(130%, 0) rotate(0) scale(1); }
  7%, 31% { opacity: 1; transform: translate(130%, 0) rotate(0) scale(1); }
  55%, 85% { opacity: 1; transform: translate(94%, -4%) rotate(6deg) scale(1.3); }
  94%, 100% { opacity: 0; transform: translate(94%, -4%) rotate(6deg) scale(1.3); }
}
@keyframes problem-phone { 0%, 28%, 94%, 100% { opacity: 1; } 50%, 85% { opacity: .32; } }
@keyframes problem-together { 0%, 52%, 90%, 100% { opacity: 0; transform: translateY(6px); } 60%, 85% { opacity: 1; transform: none; } }
@keyframes views-lift { 0%, 30%, 100% { transform: none; } 10%, 20% { transform: translateY(-4px) scale(1.015); } }
@keyframes start-join-1 { 0%, 14% { opacity: 0; transform: translateY(8px) scale(.94); } 20%, 85% { opacity: 1; transform: none; } 94%, 100% { opacity: 0; transform: none; } }
@keyframes start-join-2 { 0%, 32% { opacity: 0; transform: translateY(8px) scale(.94); } 38%, 85% { opacity: 1; transform: none; } 94%, 100% { opacity: 0; transform: none; } }
@keyframes start-join-3 { 0%, 50% { opacity: 0; transform: translateY(8px) scale(.94); } 56%, 85% { opacity: 1; transform: none; } 94%, 100% { opacity: 0; transform: none; } }
@keyframes album-fan-back { 0%, 100% { transform: rotate(-7deg) translate(-2px, 2px); } 50% { transform: rotate(-10deg) translate(-5px, 3px); } }
@keyframes album-fan-mid { 0%, 100% { transform: rotate(5deg) translate(3px, 0); } 50% { transform: rotate(8deg) translate(6px, -1px); } }

@media (min-width: 900px) {
  .moment-cta { margin-top: 140px; }
  .hero-proof-text .moment-answer { font-size: 24px; }
}

/* ---------- v26: "Your private album, live." straight under the hero ---------- */
/* One Moment as it happens (Pooja's Birthday; the same people as every section below: Saugat started it,
   Maya, Alex and Nisha are there): the photos are the conversation, nobody types. It plays inside a slim
   phone, and the screen is Moth's own chat: the app's header (the Moment's name, "7 here · Live now",
   Invite), its stream (.stream-item, .photo-head, .photo-frame, .photo-footer with the rank, the crown
   and the reaction chips) and its camera bar, all from app.css with the same classes, so the demo keeps
   looking like the app as the app changes. Only what the app scopes to its own header (.app-header) is
   repeated here. The screen is laid out at a real phone's width in CSS px (--L, about 360-440 on a phone,
   400 on desktop) and drawn at --k of that, like a picture of a phone.
   The track holds five equal views (the one before, then A-D); the newest sits where the app keeps it,
   above the camera, and the track moves up one view (20% of itself) as each arrives. Final frame
   (static, reduced motion, before hero-story.js): D at #1 with the crown and 🔥 3, C at #2 above it,
   B at #4 with ❤️ 4, the earlier views receded a hair. */
.live-album { display: grid; grid-template-areas: "text" "stream" "life"; min-width: 0; padding: 40px var(--gutter) 0; }
.live-album-text h2 { font-family: var(--serif); font-weight: 400; font-size: clamp(31px, 8.6vw, 50px); line-height: 1.05; letter-spacing: -.035em; text-wrap: balance; }
.live-album-text p { margin-top: 12px; max-width: 30em; color: #4c534f; text-wrap: pretty; }
.live-album-text .live-album-private { display: flex; align-items: center; gap: 7px; margin-top: 14px; font-size: 13.5px; color: var(--muted); }
.live-lock { flex-shrink: 0; width: 14px; height: 14px; fill: none; stroke: var(--accent); stroke-width: 1.5; }

/* The phone: a thin dark edge, no buttons. 84% of a phone's width; as tall as a phone, but never taller
   than most of the screen, so the whole of it is in view at once. */
.live-phone {
  --k: .8; --bezel: 5px; --L: calc((84vw - 10px) / .8); --LH: clamp(600px, calc((88svh - 10px) / .8), calc(var(--L) * 2.1));
  grid-area: stream; justify-self: center; position: relative; margin-top: 30px; padding: var(--bezel); border-radius: 44px;
  background: #1b1f1d; box-shadow: inset 0 0 0 1px #ffffff1c, 0 0 0 1px #1013110d, 0 36px 60px -36px #1c201d8c, 0 14px 28px -22px #1c201d5c;
}
.live-phone-screen {
  position: relative; isolation: isolate; width: calc(var(--L) * var(--k)); height: calc(var(--LH) * var(--k));
  overflow: hidden; border-radius: calc(44px - var(--bezel)); background: var(--bg);
}
.live-stream {
  --chat-w: calc(var(--L) - 32px); /* the app's phone stream: 16px each side (app.css .chat-history) */
  position: absolute; left: 0; top: 0; display: flex; flex-direction: column; width: var(--L); height: var(--LH);
  transform: scale(var(--k)); transform-origin: 0 0; pointer-events: none; user-select: none; -webkit-user-select: none;
}
/* The phone's own top: the time, the island, the battery. */
.live-status {
  position: relative; flex-shrink: 0; display: flex; align-items: center; justify-content: space-between; height: 50px;
  padding: 3px 30px 0 36px; font-size: 15px; font-weight: 600; letter-spacing: -.01em; font-variant-numeric: tabular-nums;
}
.live-island { position: absolute; left: 50%; top: 11px; width: 108px; height: 31px; margin-left: -54px; border-radius: 16px; background: #0f1110; }
.live-battery { position: relative; width: 25px; height: 12px; border: 1.2px solid #282e2b73; border-radius: 4px; }
.live-battery::before { content: ""; position: absolute; inset: 1.5px; right: 6px; border-radius: 1.5px; background: var(--ink); }
.live-battery::after { content: ""; position: absolute; right: -4px; top: 3px; width: 2px; height: 4px; border-radius: 0 1px 1px 0; background: #282e2b73; }
/* The app's header in a Moment (app.css .app-header, moments.css .app-header.in-moment, [data-moment="live"]). */
.live-head { position: relative; z-index: 2; flex-shrink: 0; padding: 0 10px 0 18px; background: var(--bg); border-bottom: 1px solid var(--line); }
.live-head .header-row { gap: 8px; }
.live-head .trip-open { margin-top: 0; font-size: 16px; font-weight: 600; line-height: 1.25; letter-spacing: -.012em; color: var(--ink); }
.live-head .moment-state { color: #557563; font-weight: 550; }
/* Invite as a small pill with its word, at every width (the app drops the word on narrow screens). */
.live-head .invite-open { width: auto; height: 32px; padding: 0 12px 0 9px; border-radius: 16px; font-size: 13.5px; }
.live-head .invite-open span { position: static; width: auto; height: auto; overflow: visible; clip-path: none; }
.live-head .invite-open svg { width: 18px; height: 18px; }

/* The stream: where the app keeps the newest photo after it scrolls to it, above the camera (app.css
   --chat-end, plus the phone's bottom edge). Each view is one .stream-item with the app's 30px gap under it. */
.live-stream-window { --foot: 156px; position: relative; flex: 1; min-height: 0; overflow: hidden; }
/* The view before slips softly under the header. */
.live-stream-window::before { content: ""; position: absolute; z-index: 1; left: 0; right: 0; top: 0; height: 26px; background: linear-gradient(var(--bg), #fafaf700); }
.live-track { position: absolute; left: 0; right: 0; top: calc(100% - var(--foot)); padding: 0 16px; transform: translateY(-100%); }
.live-item { --slide: -62px; isolation: isolate; padding-bottom: 30px; transform-origin: 0 50%; }
/* The views already there sit back a hair while the newest is on top (the final frame; the loop moves it). */
.live-z, .live-a, .live-b, .live-c { opacity: .86; transform: scale(.985); }
.live-z .live-frame img { transform: scale(1.9); transform-origin: 100% 30%; } /* the room again, closer: the other end of the table */
/* The photo at the app's chat size (.photo-frame.square: .68 of the stream), resting on a soft lifted
   shadow; a deeper one (under it, from the sender line) shows while it lands. */
.live-frame { --ar: 1.5; box-shadow: 0 1px 2px #1c201d17, 0 8px 18px -12px #1c201d47; }
.live-item .photo-head { position: relative; }
.live-item .photo-head::after {
  content: ""; position: absolute; z-index: -1; left: 0; right: 0; top: calc(100% + 8px); aspect-ratio: 1.5; border-radius: 16px;
  box-shadow: 0 18px 30px -14px #1c201d70, 0 4px 10px -4px #1c201d2e; opacity: 0;
}
/* The #1: a thin gold edge. */
.live-d .live-frame::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 2.5px var(--gold); pointer-events: none; }
/* "Finding its place…" sits where the rank will be (as the app's .placing.settling does), and is gone in
   the final frame; the loop shows it on each new view until its rank arrives. */
.live-stream .placing { position: absolute; left: 0; top: 50%; transform: translateY(-50%); }
.live-stream .placing-stage, .live-stream .placing-label { opacity: 0; }
.live-stream .rank-chip { transform-origin: 0 50%; }
.live-stream .chip { transform-origin: 30% 50%; }
.live-stream .camera-label { pointer-events: none; }
.live-stream .capture-bar { padding-bottom: 30px; }
.live-home { position: absolute; z-index: 21; left: 50%; bottom: 8px; width: 134px; height: 5px; margin-left: -67px; border-radius: 3px; background: #1c201d; }

/* The lifecycle: the same Moment tonight, and the Album it is afterwards. */
/* The app's own "Live now" (moments.css): a small green dot, a little weight. */
.live-now { display: inline-flex; align-items: center; gap: 6px; color: #557563; font-weight: 550; }
.live-dot { width: 6px; height: 6px; border-radius: 50%; background: #6f9a80; }
.live-life { grid-area: life; min-width: 0; margin-top: 40px; }
.live-life-line { font-family: var(--serif); font-style: italic; font-size: clamp(19px, 5.4vw, 21px); line-height: 1.35; color: var(--ink); }
.live-life-line span { display: block; } /* one sentence a line: the Moment, then the Album */
.live-life-steps { display: grid; gap: 16px; margin-top: 18px; max-width: 440px; }
.live-life-step {
  position: relative; display: grid; grid-template-columns: 58px minmax(0, 1fr); column-gap: 14px; align-items: center;
  padding: 12px 14px; border-radius: 16px; background: #fff; border: 1px solid var(--line);
}
.live-life-step + .live-life-step::before { content: ""; position: absolute; left: 42px; top: -17px; width: 2px; height: 16px; border-radius: 1px; background: var(--line); }
.live-life-thumb { position: relative; width: 58px; height: 40px; }
.live-life-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; border-radius: 8px; background: #e9ebe5; }
.live-life-stack img { position: absolute; inset: 0; border: 2px solid var(--print-edge); border-radius: 7px; box-shadow: 0 2px 6px #28271b29; }
.live-life-stack img:nth-child(1) { transform: rotate(-8deg) translate(-3px, 1px); }
.live-life-stack img:nth-child(2) { transform: rotate(6deg) translate(3px, -1px); }
.live-life-text { display: grid; min-width: 0; }
.live-life-name { font-size: 15.5px; font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; }
.live-life-meta { font-size: 13px; line-height: 1.4; color: var(--muted); }
.live-life-meta .live-now { gap: 5px; }
/* What the Album has, quietly: the names the app uses, each with its mark. */
.live-life-tags { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 12px; padding-top: 11px; border-top: 1px solid var(--line); }
.live-tag { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; font-weight: 550; color: #4c534f; white-space: nowrap; }
.live-tag-crown { width: 15px; height: 11px; fill: var(--gold); }
.live-tag-play { width: 11px; height: 11px; fill: var(--ink); }
.live-tag-emoji { font-size: 11px; line-height: 1; }

@media (prefers-reduced-motion: no-preference) {
  /* 12 s: A shows, Maya's candles land (the stream moves up, A sits back a hair), finding its place, a
     heart, #4; Alex's laugh lands, finds its place and takes #2; Saugat's of her face lands, a 🔥, finds
     its place and rises to #1 as the crown settles with a small lift; a hold; the views fade, go back
     unseen, and A returns. Each landing: up from below with a hair of scale and a deeper shadow, then it
     settles lighter. The header and the camera never move. */
  .live-track { animation: live-track 12s ease-in-out infinite; }
  .live-a { animation: live-a 12s ease-in-out infinite; }
  .live-b { animation: live-b 12s ease-in-out infinite; }
  .live-c { animation: live-c 12s ease-in-out infinite; }
  .live-d { animation: live-d 12s ease-in-out infinite; }
  .live-b .photo-head::after { animation: live-shadow-b 12s ease-in-out infinite; }
  .live-c .photo-head::after { animation: live-shadow-c 12s ease-in-out infinite; }
  .live-d .photo-head::after { animation: live-shadow-d 12s ease-in-out infinite; }
  .live-b .placing-label { animation: live-label-b 12s linear infinite; }
  .live-c .placing-label { animation: live-label-c 12s linear infinite; }
  .live-d .placing-label { animation: live-label-d 12s linear infinite; }
  .live-b .placing-stage { animation: live-placed-b 12s ease-out infinite; }
  .live-c .placing-stage { animation: live-placed-c 12s ease-out infinite; }
  .live-d .placing-stage { animation: live-placed-d 12s ease-out infinite; }
  .live-b .rank-speck { animation: live-speck-b 12s ease-out infinite; }
  .live-c .rank-speck { animation: live-speck-c 12s ease-out infinite; }
  .live-d .rank-speck { animation: live-speck-d 12s ease-out infinite; }
  .live-b .rank-chip { animation: live-rank-b 12s ease-out infinite; }
  .live-c .rank-chip { animation: live-rank-c 12s ease-out infinite; }
  .live-d .rank-chip { animation: live-rank-d 12s ease-out infinite; }
  .live-d .crown { animation: live-crown 12s ease-in-out infinite; }
  .live-b .chip { animation: live-chip-b 12s ease-out infinite; }
  .live-d .chip { animation: live-chip-d 12s ease-out infinite; }
  .live-b .reactor-names { animation: live-names-b 12s linear infinite; }
  .live-d .reactor-names { animation: live-names-d 12s linear infinite; }
  .live-b .react-add { animation: live-add-b 12s ease-out infinite; }
  .live-d .react-add { animation: live-add-d 12s ease-out infinite; }
  .live-d .live-frame { animation: live-rise 12s ease-in-out infinite; }
  .live-d .live-frame::after { animation: live-gold 12s ease-in-out infinite; }
}
/* 0-4% back in, 13-20% B, 37-44% C, 57-64% D, 64-93% the rest and the hold, 93-98% fade, 98-100% unseen. */
@keyframes live-track {
  0% { opacity: 0; transform: translateY(-40%); }
  4%, 13% { opacity: 1; transform: translateY(-40%); animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
  20%, 37% { transform: translateY(-60%); animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
  44%, 57% { transform: translateY(-80%); animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
  64%, 93% { opacity: 1; transform: translateY(-100%); }
  98%, 100% { opacity: 0; transform: translateY(-100%); }
}
/* A view lands (up 22px, .96 to a hair over 1, then settles), and sits back a hair as the next one lands. */
@keyframes live-a { 0%, 13% { opacity: 1; transform: none; } 21%, 100% { opacity: .86; transform: scale(.985); } }
@keyframes live-b {
  0%, 13% { opacity: 0; transform: translateY(22px) scale(.96); animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
  18% { opacity: 1; transform: translateY(-2px) scale(1.006); animation-timing-function: ease-out; }
  22%, 37% { opacity: 1; transform: none; }
  45%, 100% { opacity: .86; transform: scale(.985); }
}
@keyframes live-c {
  0%, 37% { opacity: 0; transform: translateY(22px) scale(.96); animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
  42% { opacity: 1; transform: translateY(-2px) scale(1.006); animation-timing-function: ease-out; }
  46%, 57% { opacity: 1; transform: none; }
  65%, 100% { opacity: .86; transform: scale(.985); }
}
@keyframes live-d {
  0%, 57% { opacity: 0; transform: translateY(22px) scale(.96); animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
  62% { opacity: 1; transform: translateY(-2px) scale(1.006); animation-timing-function: ease-out; }
  66%, 100% { opacity: 1; transform: none; }
}
/* The deeper shadow: in while a view lands, gone as it settles (D's comes back for the #1 lift). */
@keyframes live-shadow-b { 0%, 13%, 30%, 100% { opacity: 0; } 17% { opacity: 1; } }
@keyframes live-shadow-c { 0%, 37%, 54%, 100% { opacity: 0; } 41% { opacity: 1; } }
@keyframes live-shadow-d { 0%, 57%, 72%, 90%, 100% { opacity: 0; } 61% { opacity: 1; } 78% { opacity: .8; } }
/* Finding its place, then the app's reveal (app.js revealRank): the words go, the moth swells and fades,
   a few gold specks fly out and the rank settles in. B at 33%, C at 48%, D at 72%. */
@keyframes live-label-b { 0%, 33% { opacity: 1; } 33.5%, 100% { opacity: 0; } }
@keyframes live-label-c { 0%, 48% { opacity: 1; } 48.5%, 100% { opacity: 0; } }
@keyframes live-label-d { 0%, 72% { opacity: 1; } 72.5%, 100% { opacity: 0; } }
@keyframes live-placed-b { 0%, 33% { opacity: 1; transform: none; } 34% { opacity: 1; transform: scale(1.14); } 35.5%, 100% { opacity: 0; transform: scale(.88); } }
@keyframes live-placed-c { 0%, 48% { opacity: 1; transform: none; } 49% { opacity: 1; transform: scale(1.14); } 50.5%, 100% { opacity: 0; transform: scale(.88); } }
@keyframes live-placed-d { 0%, 72% { opacity: 1; transform: none; } 73% { opacity: 1; transform: scale(1.14); } 74.5%, 100% { opacity: 0; transform: scale(.88); } }
@keyframes live-speck-b {
  0%, 33.5% { opacity: 0; transform: translate(calc(var(--sx) * .25), calc(var(--sy) * .25)) scale(.5); }
  34% { opacity: .95; } 36.5%, 100% { opacity: 0; transform: translate(var(--sx), var(--sy)) scale(.4); }
}
@keyframes live-speck-c {
  0%, 48.5% { opacity: 0; transform: translate(calc(var(--sx) * .25), calc(var(--sy) * .25)) scale(.5); }
  49% { opacity: .95; } 51.5%, 100% { opacity: 0; transform: translate(var(--sx), var(--sy)) scale(.4); }
}
@keyframes live-speck-d {
  0%, 72.5% { opacity: 0; transform: translate(calc(var(--sx) * .25), calc(var(--sy) * .25)) scale(.5); }
  73% { opacity: .95; } 75.5%, 100% { opacity: 0; transform: translate(var(--sx), var(--sy)) scale(.4); }
}
@keyframes live-rank-b { 0%, 33.5% { opacity: 0; transform: scale(.8); } 35.5% { opacity: 1; transform: scale(1.08); } 37.5%, 100% { opacity: 1; transform: none; } }
@keyframes live-rank-c { 0%, 48.5% { opacity: 0; transform: scale(.8); } 50.5% { opacity: 1; transform: scale(1.08); } 52.5%, 100% { opacity: 1; transform: none; } }
@keyframes live-rank-d { 0%, 72.5% { opacity: 0; transform: scale(.8); } 74.5% { opacity: 1; transform: scale(1.08); } 76.5%, 100% { opacity: 1; transform: none; } }
@keyframes live-crown {
  0%, 74% { opacity: 0; transform: translateY(-6px) scale(.7); }
  79% { opacity: 1; transform: scale(1.22) rotate(-8deg); }
  84%, 100% { opacity: 1; transform: none; }
}
/* A reaction arrives as in the app (app.js celebrate): the chip springs in, the add button steps aside
   for it (--slide: the chip and its gap, 54-57px with the emoji fonts plus 6) and the names show. ❤️ on B at 26%, 🔥 on D at 67%. */
@keyframes live-chip-b { 0%, 26% { opacity: 0; transform: scale(.55); } 28.5% { opacity: 1; transform: scale(1.06); } 31%, 100% { opacity: 1; transform: none; } }
@keyframes live-chip-d { 0%, 67% { opacity: 0; transform: scale(.55); } 69.5% { opacity: 1; transform: scale(1.06); } 72%, 100% { opacity: 1; transform: none; } }
@keyframes live-names-b { 0%, 27.5% { opacity: 0; } 30%, 100% { opacity: 1; } }
@keyframes live-names-d { 0%, 68.5% { opacity: 0; } 71%, 100% { opacity: 1; } }
@keyframes live-add-b { 0%, 26% { transform: translateX(var(--slide)); } 29%, 100% { transform: none; } }
@keyframes live-add-d { 0%, 67% { transform: translateX(var(--slide)); } 70%, 100% { transform: none; } }
@keyframes live-rise { 0%, 72%, 88%, 100% { transform: none; } 78% { transform: translateY(-3px) scale(1.012); } }
@keyframes live-gold { 0%, 73% { opacity: 0; } 80%, 100% { opacity: 1; } }

/* From a big phone up, the phone is a little larger: a 400px screen drawn at .84. */
@media (min-width: 560px) {
  .live-phone { --k: .84; --L: 400px; --LH: clamp(600px, calc((86svh - 10px) / .84), 820px); margin-top: 36px; }
  .live-life { justify-self: center; width: 420px; }
}
/* Desktop: the words and the lifecycle on the left, centred on the phone at the right. */
@media (min-width: 900px) {
  .live-album {
    max-width: 1080px; margin: 0 auto; padding-top: 120px; column-gap: 72px; align-items: start;
    grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: 1fr auto auto 1fr;
    grid-template-areas: ". stream" "text stream" "life stream" ". stream";
  }
  .live-phone { grid-row: 1 / -1; margin: 0; }
  .live-life { justify-self: stretch; width: auto; margin-top: 44px; }
  .live-life-line { font-size: 24px; }
}
