/* Scroll scenes. Everything here is scoped to html.motion, which motion.js sets only when
   motion is allowed. motion.js writes --p (0..1 scroll progress) on each [data-scene],
   data-active on step scenes, and --lit on [data-lit]. Only transform/opacity animate. */

/* Pinned stages clip their own overflow: fanned cards and swiped screens must never widen the page. */
.motion :is(.hero-scene, .story, .burst) .stage { overflow: clip; }

/* ---------- Hero: big type, phone rises into place, the burst fans out ---------- */
.motion .hero-scene { height: 230vh; --peek: 58svh; }
@media (min-width: 768px) { .motion .hero-scene { --peek: 56svh; } }
.motion .hero-scene .stage {
  position: sticky; top: 0; height: 100svh;
  display: block; padding: 0;
  --f: clamp(0, calc((var(--p, 0) - 0.4) * 2.5), 1);
}
.motion .hero-copy {
  position: absolute; inset: 9svh 0 auto; text-align: center;
  transform: translateY(calc(var(--p, 0) * -90px)) scale(calc(1 - var(--p, 0) * 0.1));
  opacity: clamp(0, calc(1 - var(--p, 0) * 2.4), 1);
}
.motion .hero-copy h1 { font-size: clamp(34px, 7vw, 84px); line-height: 1.12; }
.motion .hero-copy .lead { margin-inline: auto; max-width: 26em; }
.motion .hero-copy { z-index: 1; }
.motion .hero-device {
  position: absolute; left: 50%; top: 50%;
  width: min(var(--phone-max), calc((100svh - 96px) * 0.44));
  translate: -50% -50%;
  transform: translateY(calc((1 - var(--p, 0)) * var(--peek)));
}
.motion .hero-device :is(.stack, .phone) { max-width: none; }
.motion .hero-scene .stack::before {
  transform: translate(calc(var(--f) * 18px), calc(var(--f) * -6px)) rotate(calc(var(--f) * 5deg));
}
.motion .hero-scene .stack::after {
  transform: translate(calc(var(--f) * 36px), calc(var(--f) * -12px)) rotate(calc(var(--f) * 10deg));
}

@keyframes rise { from { opacity: 0; transform: translateY(var(--rise)); } }
@keyframes rise-far { from { opacity: 0; transform: translateY(160px); } }
.motion .hero-copy > * { animation: rise var(--dur-hero) var(--ease-smooth) both; }
.motion .hero-copy > :nth-child(2) { animation-delay: 120ms; }
.motion .hero-copy > :nth-child(3) { animation-delay: 240ms; }
.motion .hero-device .stack { animation: rise-far var(--dur-hero) var(--ease-smooth) 200ms both; }

@keyframes ping {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent-bright) 55%, transparent); }
  70%, 100% { box-shadow: 0 0 0 8px transparent; }
}
.motion .soon::before { animation: ping 2.4s var(--ease-smooth) 1.4s infinite; }

/* ---------- Story: phone pinned, steps change, screens swipe away inside the device ---------- */
.motion .story { height: 360vh; }
.motion .story .stage {
  position: sticky; top: 0; height: 100svh;
  padding: var(--s5) 0; border-top: 0;
  grid-template-rows: minmax(0, 1fr) auto; gap: var(--s5);
}
.motion .story-device { order: -1; align-self: center; display: grid; justify-items: center; gap: var(--s4); }
.motion .story .phone { width: min(var(--phone-max), calc((100svh - 340px) * 0.44)); }
.motion .story-steps { gap: 0; }
.motion .step {
  grid-area: 1 / 1;
  opacity: 0; transform: translateY(24px);
  transition: opacity var(--dur-normal) var(--ease-smooth), transform var(--dur-slow) var(--ease-smooth);
}
.motion .story[data-active="0"] .step:nth-child(1),
.motion .story[data-active="1"] .step:nth-child(2),
.motion .story[data-active="2"] .step:nth-child(3) { opacity: 1; transform: none; transition-delay: 150ms; }

.motion .screen + .screen { display: block; position: absolute; inset: 0; }
.motion .screen {
  transform: translateX(110%);
  transform-origin: 50% 120%;
  transition: transform var(--dur-slow) var(--ease-smooth), opacity var(--dur-slow) var(--ease-smooth);
}
.motion .story[data-active="0"] .screen:nth-child(1),
.motion .story[data-active="1"] .screen:nth-child(2),
.motion .story[data-active="2"] .screen:nth-child(3) { transform: none; }
/* A decided screen leaves the way a swiped photo does. */
.motion .story[data-active="1"] .screen:nth-child(1),
.motion .story[data-active="2"] .screen:nth-child(-n+2) { transform: translateX(-115%) rotate(-14deg); opacity: 0; }

.motion .story-dots { display: flex; gap: var(--s2); }
.motion .story-dots span {
  width: 6px; height: 6px; border-radius: 50%; background: var(--hairline);
  transition: transform var(--dur-normal) var(--ease-settle), background-color var(--dur-normal);
}
.motion .story[data-active="0"] .story-dots span:nth-child(1),
.motion .story[data-active="1"] .story-dots span:nth-child(2),
.motion .story[data-active="2"] .story-dots span:nth-child(3) { background: var(--accent); transform: scale(1.4); }

/* ---------- Burst: 23 scattered photos collapse into one pile, one dialog appears ---------- */
.motion .burst { height: 280vh; }
.motion .burst .stage {
  position: sticky; top: 0; height: 100svh;
  display: block; padding: 0; border-top: 0;
  --c: clamp(0, calc((var(--p, 0) - 0.12) * 2), 1);
  --o: clamp(0, calc((var(--p, 0) - 0.62) * 5), 1);
  --t: clamp(44px, 11vw, 96px);
  --gap: calc(var(--t) * 1.18);
}
.motion .burst-caption { display: block; position: absolute; left: 0; right: 0; top: 10svh; }
.motion .burst-caption.before { opacity: calc(1 - var(--o)); transform: translateY(calc(var(--o) * -16px)); }
.motion .burst-caption.after { opacity: var(--o); transform: translateY(calc((1 - var(--o)) * 16px)); }
.motion .pile { display: block; position: absolute; inset: 8svh 0 0; transform: translateY(calc(var(--o) * -8svh)); }
.motion .tile {
  position: absolute; left: 50%; top: 50%;
  width: var(--t); height: var(--t);
  margin: calc(var(--t) / -2) 0 0 calc(var(--t) / -2);
  border-radius: 10px; object-fit: cover;
  box-shadow: 0 0 0 1px rgb(0 0 0 / 0.06), 0 10px 24px -12px rgb(0 0 0 / 0.45);
  --ci: clamp(0, calc(var(--c) * 1.6 - var(--d) * 0.6), 1);
  transform:
    translate(calc(var(--x) * var(--gap) * (1 - var(--ci))), calc(var(--y) * var(--gap) * (1 - var(--ci))))
    rotate(calc(var(--r) * 1deg * var(--ci)))
    scale(calc(1 - var(--ci) * 0.1));
  opacity: calc(1 - var(--o) * 0.75);
}
.motion .dialog {
  position: absolute; left: 50%; top: 70%;
  width: min(320px, calc(100% - 2 * var(--s4)));
  translate: -50% -50%;
  opacity: var(--o);
  transform: translateY(calc((1 - var(--o)) * 24px)) scale(calc(0.94 + var(--o) * 0.06));
}

/* ---------- Facts light up as they cross the viewport ---------- */
.motion [data-lit] {
  opacity: calc(0.16 + var(--lit, 0) * 0.84);
  transform: translateY(calc((1 - var(--lit, 0)) * 20px));
}

/* ---------- Pricing: reveal once ---------- */
.motion .section[data-reveal] :where(h2, .intro, .plan, .fine) {
  transition: opacity var(--dur-slow) var(--ease-smooth), transform var(--dur-slow) var(--ease-smooth);
}
.motion .section[data-reveal]:not(.in) :is(h2, .intro, .plan, .fine) { opacity: 0; transform: translateY(var(--rise)); }
.motion .section[data-reveal] .intro { transition-delay: calc(var(--stagger) * 1); }
.motion .section[data-reveal] .plan:nth-child(1) { transition-delay: calc(var(--stagger) * 2); }
.motion .section[data-reveal] .plan:nth-child(2) { transition-delay: calc(var(--stagger) * 3); }
.motion .section[data-reveal] .plan:nth-child(3) { transition-delay: calc(var(--stagger) * 4); }
.motion .section[data-reveal] .fine { transition-delay: calc(var(--stagger) * 5); }

@media (min-width: 768px) {
  .motion .story .stage { grid-template-columns: 1fr 1fr; grid-template-rows: none; gap: var(--s8); }
  .motion .story-device { order: 0; }
  .motion .story .phone { width: min(var(--phone-max), calc((100svh - 120px) * 0.44)); }
}
