/* Motion layer. Everything here only applies once motion.js adds html.motion
   (skipped for prefers-reduced-motion and when JS is off). */
html.lenis { scroll-behavior: auto; }

:root { --ease: cubic-bezier(.16, 1, .3, 1); }

/* ── Scroll reveals ── */
.motion [data-reveal] {
  transition: opacity 1s var(--ease), transform 1.1s var(--ease), clip-path 1.4s var(--ease);
  transition-delay: var(--d, 0ms);
}
.motion [data-reveal="up"]:not(.in)    { opacity: 0; transform: translateY(28px); }
.motion [data-reveal="left"]:not(.in)  { opacity: 0; transform: translateX(48px); }
.motion [data-reveal="fade"]:not(.in)  { opacity: 0; }
.motion [data-reveal="rise"]:not(.in)  { transform: translateY(80px); }
.motion [data-reveal="scale"]:not(.in) { opacity: 0; transform: scale(.88); }

/* Image frames open from a slightly inset window while the photo settles */
.motion [data-reveal="clip"] { clip-path: inset(0 round var(--r, 8px)); }
.motion [data-reveal="clip"]:not(.in) { clip-path: inset(var(--ci, 7%) round var(--r, 8px)); }
.motion .hw[data-reveal="clip"].in { clip-path: inset(0 0 -240px 0); }   /* leave room for the bottom fade */
/* Scroll smoothness (11 Nov): drop the mask once a reveal has finished (motion.js adds .done);
   a lingering clip-path makes every scrolled frame repaint the section */
.motion [data-reveal="clip"].done:not(.hw) { clip-path: none; }
/* Parallax layers move on the GPU instead of repainting their big images every frame */
.motion .hero__bg, .motion .how__img > img, .motion .voice__bg, .motion .shop__photo > img, .motion .guide__feed,
.motion .privacy__img > img, .motion .dinner__tara, .motion .hw__cards, .motion .mom__photo img { will-change: translate; }
.motion [data-reveal="clip"] > img { transition: transform 1.6s var(--ease); transition-delay: var(--d, 0ms); }
.motion [data-reveal="clip"]:not(.in) > img { transform: scale(1.12); }

/* Parallax layers are slightly oversized so their edges never show */
.motion .how__img > img,
.motion .privacy__img > img,
.motion .voice__bg,
.motion .shop__photo > img { scale: 1.1; }

/* ── Hero entrance ── */
@keyframes m-settle { from { transform: scale(1.08); } to { transform: none; } }
@keyframes m-fade   { from { opacity: 0; } to { opacity: 1; } }
@keyframes m-rise   { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: none; } }
.motion .hero__bg { animation: m-settle 2.6s var(--ease) both; }
.motion .hero__logo,
.motion .hero__nav,
.motion .hero__cta { animation: m-fade 1s .35s var(--ease) both; }
.motion .hero__title   { animation: m-rise 1.1s .55s var(--ease) both; }
.motion .hero__actions { animation: m-rise 1.1s .75s var(--ease) both; }

/* ── Voice: waveform breathes while the scene is on screen ── */
@keyframes m-wave { from { transform: scaleY(.6); } to { transform: scaleY(1); } }
.motion .voice__wave i {
  animation: m-wave 1.4s ease-in-out infinite alternate;
  animation-delay: calc(var(--i, 0) * -0.17s);
  animation-play-state: paused;
}
.motion .voice__scene.wave-on .voice__wave i { animation-play-state: running; }

/* ── Watch · Active guidance: copy rises, the progress bar fills to "Garlic",
   each step lights as the bar reaches it, then the marker finds the onions ── */
@keyframes m-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
@keyframes m-ring  { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.18); opacity: .55; } }
@keyframes m-glow  { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
.motion .guide__feed { scale: 1.1; }
.motion .guide__cam img { animation: m-pulse 2.2s ease-in-out infinite; }

.motion .guide__copy > *,
.motion .guide__marker > *,
.motion .guide .step img,
.motion .guide .step span,
.motion .guide__done { transition: opacity .9s var(--ease), transform 1s var(--ease); }

.motion .guide:not(.play) .guide__copy > * { opacity: 0; transform: translateY(24px); }
.motion .guide__who  { transition-delay: .1s; }
.motion .guide__say  { transition-delay: .22s; }
.motion .guide__desc { transition-delay: .4s; }

.motion .guide__done { transition: transform 2s cubic-bezier(.45, 0, .2, 1) .5s; }
.motion .guide:not(.play) .guide__done { transform: scaleX(0); }

.motion .guide .step span { transition-delay: calc(.3s + var(--n) * .08s); }
.motion .guide:not(.play) .step span { opacity: 0; transform: translate(-50%, 8px); }
.motion .guide:not(.play) .step:first-child span { transform: translateY(8px); }
.motion .guide:not(.play) .step:last-child span { transform: translate(-100%, 8px); }

.motion .guide .step img { transition-delay: calc(.5s + var(--n) * .92s); }
.motion .guide .step:not(.step--done):not(.step--now) img { transition-delay: calc(.3s + var(--n) * .08s); }
.motion .guide:not(.play) .step img { opacity: 0; transform: translate(-50%, -50%) scale(.2); }
.motion .guide.play .step--now img { animation: m-glow 2.4s ease-in-out 3.2s infinite; }

.motion .guide__ring { transition-delay: 1.3s; }
.motion .guide__dot  { transition-delay: 1.15s; }
.motion .guide__marker span { transition-delay: 1.6s; }
.motion .guide:not(.play) .guide__ring { opacity: 0; transform: scale(1.8); }
.motion .guide:not(.play) .guide__dot  { opacity: 0; transform: scale(0); }
.motion .guide:not(.play) .guide__marker span { opacity: 0; transform: translateX(-8px); }
.motion .guide.play .guide__ring { animation: m-ring 2.6s ease-in-out 2.6s infinite; }

/* ── Watch · While you wait: camera dots blink like a live feed ── */
.motion .wcard__cam img { animation: m-pulse 2.2s ease-in-out infinite; }
.motion .wcard + .wcard .wcard__cam img { animation-delay: -1.1s; }

/* ── Shop: the phone's rows tick in after it rises, then the Instacart button ── */
.motion .app__row,
.motion .app__cta { transition: opacity .6s var(--ease), transform .7s var(--ease); }
.motion .app__row { transition-delay: calc(.75s + var(--n) * .08s); }
.motion .app__cta { transition-delay: 1.45s; }
.motion .phone:not(.in) .app__row { opacity: 0; transform: translateX(-10px); }
.motion .phone:not(.in) .app__cta { opacity: 0; transform: translateY(12px); }
