/* Carbo-AI motion layer. Loaded after site.css. Everything here is switched off under prefers-reduced-motion (last block). */

/* 1. Headline rise-in — site.js wraps each word of .hero h1 in <span class="w" style="--i:n"> */
html.js .hero h1 .w { display: inline-block; opacity: 0; transform: translateY(.6em); animation: rise .55s cubic-bezier(.2,.8,.2,1) forwards; animation-delay: calc(var(--i, 0) * 45ms); }
html.js .hero .lede, html.js .hero__cta { opacity: 0; animation: fade-up .5s ease forwards; }
html.js .hero .lede { animation-delay: 260ms; }
html.js .hero__cta { animation-delay: 380ms; }
@keyframes rise { to { opacity: 1; transform: none; } }
@keyframes fade-up { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* 2. Carbo stage — breathing lives in site.css; the bubble pops in 1 s into Carbo's wave (carbo-rive.mjs adds .is-in) and in any case 3 s after site.js runs, even before the wave */
html.js .stage .bubble { opacity: 0; transform: scale(.92) translateY(6px); transform-origin: 20% 100%; transition: opacity .35s ease, transform .35s cubic-bezier(.2,.8,.2,1); }
html.js .stage .bubble.is-in { opacity: 1; transform: none; }

/* 3. Reveal stagger — site.js sets --i on each .reveal from its index among sibling .reveal elements */
html.js .reveal { transition-delay: calc(var(--i, 0) * 80ms); }

/* 4. Cards lift on hover (pointer devices only) */
@media (hover: hover) {
  .card { transition: transform .22s ease, box-shadow .22s ease; }
  .card:hover { transform: translateY(-3px); box-shadow: 0 28px 52px -24px rgba(17, 24, 39, .3), 0 4px 10px rgba(17, 24, 39, .07); }
}

/* 5. Week dots pop in when their .reveal parent becomes visible; "today" also pulses once (the ring itself is in site.css) */
html.js .week__dot { transform: scale(0); }
html.js .is-visible .week__dot { animation: pop .45s cubic-bezier(.2,.9,.3,1.3) forwards; animation-delay: calc(var(--i, 0) * 70ms); }
html.js .is-visible .week__dot--today { animation-name: pop, pulse; animation-duration: .45s, 1.2s; animation-timing-function: cubic-bezier(.2,.9,.3,1.3), ease; animation-fill-mode: forwards, none; animation-iteration-count: 1, 1; animation-delay: calc(var(--i, 0) * 70ms), calc(var(--i, 0) * 70ms + 1.1s); }
@keyframes pop { to { transform: scale(1); } }
@keyframes pulse { 0%, 100% { outline: 0 solid rgba(63, 127, 127, 0); } 50% { outline: 10px solid rgba(63, 127, 127, .25); } }

/* 6. Step 1 only (.step--scan): the scan bracket settles in, then one sweep */
html.js .step--scan .scan { opacity: 0; }
html.js .step--scan.is-visible .scan { animation: bracket .5s ease .2s forwards; }
html.js .step--scan.is-visible .step__art::after { content: ""; position: absolute; left: 14%; right: 14%; top: 14%; height: 2px; background: #fff; box-shadow: 0 0 12px #fff; opacity: 0; animation: sweep 1.6s linear .7s 1 forwards; }
@keyframes bracket { from { opacity: 0; transform: scale(1.06); } to { opacity: 1; transform: none; } }
@keyframes sweep { 0% { opacity: 1; top: 14%; } 95% { opacity: 1; } 100% { opacity: 0; top: 86%; } }

/* 7. Emotion strip — the Counting tile's frames are swapped by site.js; the other tiles are Rive canvases (carbo-rive.mjs) */

/* 8. Kinetic type band — two counter-scrolling lines; structure in site.css, the HTML repeats each line's content twice for a seamless loop */
.marquee__track { animation: marquee 28s linear infinite; }
.marquee__track--reverse { animation-direction: reverse; }
@keyframes marquee { to { transform: translateX(-50%); } }

/* 9. Closing band headline rises when the band is observed (site.js observes [data-observe]) */
html.js .band h2 { opacity: 0; transform: translateY(12px); transition: opacity .5s ease, transform .5s ease; }
html.js .band.is-visible h2 { opacity: 1; transform: none; }

/* 10. Reduced motion: everything static, everything visible */
@media (prefers-reduced-motion: reduce) {
  html.js .hero h1 .w, html.js .hero .lede, html.js .hero__cta { animation: none; opacity: 1; transform: none; }
  html.js .stage .bubble { opacity: 1; transform: none; transition: none; }
  html.js .reveal { transition-delay: 0s; }
  .card, .card:hover { transform: none; transition: none; box-shadow: var(--shadow-lg); }
  html.js .week__dot, html.js .is-visible .week__dot, html.js .is-visible .week__dot--today { transform: none; animation: none; }
  html.js .step--scan .scan, html.js .step--scan.is-visible .scan { opacity: 1; animation: none; }
  html.js .step--scan.is-visible .step__art::after { display: none; }
  .marquee__track { animation: none; padding-left: 24px; } /* at rest the first glyph would sit flush against the edge */
  html.js .band h2, html.js .band.is-visible h2 { opacity: 1; transform: none; transition: none; }
}
