/* ═══════════════════════════════════════════════════════════════
   Finone AI — motion layer
   Loaded after style.css on every page. Motion here explains the
   product (say it → saved in a second) and answers the hand; it
   never carries information of its own.

   Rules
   • Compositor-only where it matters: transform / translate / scale /
     rotate / opacity. Paint-heavy effects stay small (borders, chips).
   • Two clocks: one-shot reveals (IntersectionObserver, every browser)
     and scroll-linked showcase effects (CSS scroll-driven animations,
     only where supported — elsewhere the final state shows).
   • Loops run only while their section is on screen (.in-view, set by
     motion.js), and stop with the pause button or "reduce motion".
   • Without JavaScript nothing is hidden: hidden start states need the
     .js / .motion classes the scripts add themselves.
   ═══════════════════════════════════════════════════════════════ */

/* ─── Tokens ─── */
:root{
  /* Springs sampled from a damped oscillator (ζ .78 / .55):
     2% and 13% overshoot. */
  --m-spring:linear(0, 0.0141, 0.0513, 0.1051, 0.1701, 0.2418, 0.3167, 0.3921, 0.4658, 0.5361, 0.6021, 0.663, 0.7184, 0.768, 0.8121, 0.8506, 0.8839, 0.9123, 0.9363, 0.9563, 0.9726, 0.9858, 0.9962, 1.0042, 1.0102, 1.0145, 1.0173, 1.019, 1.0198, 1.0199, 1.0194, 1.0185, 1.0173, 1.016, 1.0145, 1.013, 1.0115, 1.0101, 1.0087, 1.0074, 1.0063, 1.0052, 1.0043, 1.0034, 1.0027, 1.0021, 1.0015, 1);
  --m-bounce:linear(0, 0.0314, 0.1128, 0.2268, 0.3584, 0.4953, 0.628, 0.7496, 0.8555, 0.9435, 1.0128, 1.0638, 1.0982, 1.1181, 1.1259, 1.1243, 1.1156, 1.1021, 1.086, 1.0688, 1.0517, 1.0359, 1.0219, 1.0101, 1.0007, 0.9936, 0.9886, 0.9856, 0.9842, 0.9841, 0.985, 0.9866, 0.9885, 0.9907, 0.9929, 0.9949, 0.9967, 0.9983, 0.9996, 1.0006, 1.0013, 1.0017, 1.002, 1.002, 1.0019, 1.0018, 1.0015, 1);
  --m-out:cubic-bezier(.16,1,.3,1);
  --m-in-out:cubic-bezier(.65,0,.35,1);
  --m-d1:140ms;--m-d2:240ms;--m-d3:420ms;--m-d4:700ms;--m-d5:1000ms;
  --m-rise:26px;
  /* Lets <details> animate to height:auto (Chromium); harmless elsewhere. */
  interpolate-size:allow-keywords;
}
@supports not (transition-timing-function:linear(0, 1)){
  :root{--m-spring:cubic-bezier(.34,1.25,.64,1);--m-bounce:cubic-bezier(.34,1.56,.64,1)}
}

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ═══ Page transitions (cross-document View Transitions) ═══
   Same-origin page changes cross-fade with a short rise while the header
   stays put. Browsers without support just navigate. */
@view-transition{navigation:auto}
.header{view-transition-name:site-header}
::view-transition-old(root){animation:m-vt-out .22s var(--m-in-out) both}
::view-transition-new(root){animation:m-vt-in .5s var(--m-out) both}
@keyframes m-vt-out{to{opacity:0;transform:translateY(-6px)}}
@keyframes m-vt-in{from{opacity:0;transform:translateY(14px)}}

/* Theme switch: the new theme grows as a circle from the button.
   app.js sets --vt-x/--vt-y/--vt-r and .vt-theme for this one. */
.vt-theme::view-transition-old(root){animation:none}
.vt-theme::view-transition-new(root){animation:m-vt-circle .62s var(--m-in-out) both}
.vt-theme .header{view-transition-name:none}
@keyframes m-vt-circle{
  from{clip-path:circle(0 at var(--vt-x,50%) var(--vt-y,0))}
  to{clip-path:circle(var(--vt-r,150vmax) at var(--vt-x,50%) var(--vt-y,0))}}
/* Language switch: a quick cross-fade of the texts. */
.vt-lang::view-transition-old(root){animation:m-fade-out .18s ease both}
.vt-lang::view-transition-new(root){animation:m-fade-in .32s var(--m-out) both}
.vt-lang .header{view-transition-name:none}
@keyframes m-fade-out{to{opacity:0}}
@keyframes m-fade-in{from{opacity:0}}

/* ═══ Header ═══ */
/* Lifting off into the floating bar: the insets and the radius are typed
   (@property), so they spring like any length. Untyped browsers jump. */
@property --hx{syntax:'<length>';inherits:true;initial-value:0px}
@property --hy{syntax:'<length>';inherits:true;initial-value:0px}
@property --hr{syntax:'<length>';inherits:true;initial-value:0px}
.header{transition:--hx .75s var(--m-spring),--hy .75s var(--m-spring),--hr .75s var(--m-spring)}

/* Reading progress: a hairline that fills with the page (scroll-driven),
   riding the bottom edge of the bar in either shape. */
.scroll-progress{position:absolute;left:calc(var(--hx) + var(--hr));right:calc(var(--hx) + var(--hr));
  bottom:calc(var(--hy) * -1);height:2px;border-radius:2px;pointer-events:none;
  transform-origin:0 50%;scale:0 1;opacity:0;
  background:linear-gradient(90deg,var(--primary-dark),var(--primary),var(--primary-light))}
@supports (animation-timeline:scroll()){
  .scroll-progress{opacity:1;animation:m-grow-x linear both;animation-timeline:scroll(root block)}
}
@keyframes m-grow-x{from{scale:0 1}to{scale:1 1}}

/* Active section pill under the links (motion.js places it). */
.nav-indicator{position:absolute;left:0;top:50%;height:34px;border-radius:var(--radius-sm);
  background:var(--bg-alt);pointer-events:none;z-index:-1;opacity:0;
  width:var(--ni-w,0);translate:var(--ni-x,0) -50%;
  transition:translate .5s var(--m-spring),width .5s var(--m-spring),opacity .25s ease}
.nav-indicator.on{opacity:1}
.header:not(.hdr-menu) .nav{position:relative}
.motion .header:not(.hdr-menu) .nav a.active{background:transparent}
.hdr-menu .nav-indicator{display:none}
@media (max-width:768px){.nav-indicator{display:none}}

/* The menu panel opens on a spring and its links follow in a cascade. */
.hdr-menu .nav{transition:opacity .18s ease,translate .5s var(--m-spring),scale .5s var(--m-spring),visibility 0s linear .5s}
.hdr-menu .nav.open{transition-delay:0s}
.hdr-menu .nav a{opacity:0;translate:0 -4px;transition:opacity .25s ease,translate .45s var(--m-spring),background-color .15s ease,color .15s ease}
.hdr-menu .nav.open a{opacity:1;translate:0 0}
.hdr-menu .nav.open a:nth-child(2){transition-delay:20ms,20ms,0s,0s}
.hdr-menu .nav.open a:nth-child(3){transition-delay:45ms,45ms,0s,0s}
.hdr-menu .nav.open a:nth-child(4){transition-delay:70ms,70ms,0s,0s}
.hdr-menu .nav.open a:nth-child(5){transition-delay:95ms,95ms,0s,0s}
.hdr-menu .nav.open a:nth-child(6){transition-delay:120ms,120ms,0s,0s}

/* Buttons: a light sweep on hover, a spring on press. */
.btn-primary,.btn-header:not(.btn-header-ghost),.store-btn{position:relative;overflow:hidden;isolation:isolate}
.btn-primary::after,.btn-header:not(.btn-header-ghost)::after,.store-btn::after{content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(110deg,transparent 30%,rgba(255,255,255,.28) 50%,transparent 70%);
  translate:-120% 0;transition:translate .7s var(--m-out)}
.btn-primary:hover::after,.btn-header:not(.btn-header-ghost):hover::after,.store-btn:hover::after{translate:120% 0}
/* Magnetic pull (pointer: fine, set by motion.js). */
.magnetic{translate:var(--mg-x,0) var(--mg-y,0);transition:translate .5s var(--m-spring)}

/* ═══ Hero ═══ */
.hero{position:relative;isolation:isolate;overflow:hidden}
/* Aurora: soft blobs drifting on the compositor (transform only). */
.hero-aurora{position:absolute;inset:0;z-index:-1;pointer-events:none;overflow:hidden}
.hero-aurora i{position:absolute;display:block;border-radius:50%;will-change:transform}
.hero-aurora .b1{width:62vw;height:62vw;max-width:900px;max-height:900px;right:-14vw;top:-30vw;
  background:radial-gradient(closest-side,var(--primary-glow),transparent);opacity:.9}
.hero-aurora .b2{width:40vw;height:40vw;max-width:620px;max-height:620px;left:-12vw;bottom:-22vw;
  background:radial-gradient(closest-side,var(--primary-soft-strong),transparent)}
.hero-aurora .b3{width:30vw;height:30vw;max-width:460px;max-height:460px;left:38%;top:12%;
  background:radial-gradient(closest-side,rgba(255,107,103,.12),transparent)}
[data-theme="dark"] .hero-aurora .b3{background:radial-gradient(closest-side,rgba(255,107,103,.10),transparent)}
/* The pointer's own light (desktop). */
.hero-aurora .bp{width:520px;height:520px;left:0;top:0;opacity:0;
  background:radial-gradient(closest-side,var(--primary-soft),transparent);
  translate:calc(var(--px,50vw) - 260px) calc(var(--py,40vh) - 260px);
  transition:opacity .6s ease,translate .9s var(--m-out)}
.hero.pointer .hero-aurora .bp{opacity:1}
/* Film grain — keeps the gradients from banding, adds a printed feel. */
.hero-aurora::after{content:'';position:absolute;inset:0;opacity:.05;mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}
[data-theme="dark"] .hero-aurora::after{mix-blend-mode:screen;opacity:.035}
.hero.in-view .hero-aurora .b1{animation:m-drift1 22s ease-in-out infinite alternate}
.hero.in-view .hero-aurora .b2{animation:m-drift2 26s ease-in-out infinite alternate}
.hero.in-view .hero-aurora .b3{animation:m-drift3 18s ease-in-out infinite alternate}
@keyframes m-drift1{to{transform:translate(-9vw,7vw) scale(1.12)}}
@keyframes m-drift2{to{transform:translate(10vw,-6vw) scale(1.18)}}
@keyframes m-drift3{to{transform:translate(-12vw,9vw) scale(.86)}}

/* The GPU light (motion.js + hero-gl.worker.js) takes over from the
   blobs once its first frame is up; .gl-only stops them for good. */
.hero-gl{position:absolute;inset:0;width:100%;height:100%;opacity:0;transition:opacity 1.6s var(--m-out)}
.hero.gl .hero-gl{opacity:1}
.hero-aurora .b1,.hero-aurora .b2,.hero-aurora .b3{transition:opacity 1.4s ease}
.hero.gl .hero-aurora i,.hero.gl.pointer .hero-aurora .bp{opacity:0}
.hero.gl-only.in-view .hero-aurora i{animation:none}

/* Entrance choreography (runs at first paint; no JS needed). */
.hero .fade-up{animation:m-rise .9s var(--m-out) .2s both}
.hero .hero-badge.fade-up{animation:m-badge .8s var(--m-bounce) 0s both}
.hero h1.fade-up{animation:m-title 1.1s var(--m-out) .08s both}
.hero h1.fade-up span{animation:m-wipe 1s var(--m-in-out) .45s both,shine 1.6s var(--m-out) 1.05s 1 both}
.hero-buttons.fade-up{animation:none}
.hero-buttons.fade-up>*{animation:m-pop .8s var(--m-bounce) both}
.hero-buttons.fade-up>:nth-child(1){animation-delay:.34s}
.hero-buttons.fade-up>:nth-child(2){animation-delay:.42s}
.hero-buttons.fade-up>:nth-child(3){animation-delay:.5s}
.trust-row.fade-up{animation:none}
.trust-row.fade-up>*{animation:m-pop .7s var(--m-bounce) both}
.trust-row.fade-up>:nth-child(1){animation-delay:.6s}
.trust-row.fade-up>:nth-child(2){animation-delay:.67s}
.trust-row.fade-up>:nth-child(3){animation-delay:.74s}
.hero-image.fade-up{animation:m-phone 1.4s var(--m-out) .28s both}
@keyframes m-rise{from{opacity:0;transform:translateY(18px);filter:blur(6px)}to{opacity:1;transform:none;filter:none}}
@keyframes m-badge{from{opacity:0;transform:translateY(-8px) scale(.9)}to{opacity:1;transform:none}}
@keyframes m-title{from{opacity:0;transform:translateY(.32em);filter:blur(14px)}to{opacity:1;transform:none;filter:none}}
@keyframes m-wipe{from{clip-path:inset(-20% 100% -35% 0)}to{clip-path:inset(-20% -5% -35% 0)}}
@keyframes m-pop{from{opacity:0;transform:translateY(10px) scale(.92)}to{opacity:1;transform:none}}
@keyframes m-phone{from{opacity:0;transform:perspective(1400px) translateY(70px) rotateX(22deg) scale(.9)}to{opacity:1;transform:none}}

/* Phone: idle float on `translate`, pointer tilt on `rotate`, scroll
   depth on `scale` — separate properties, so they never fight. */
.phone-float{perspective:1100px;animation:none}
.hero.in-view .phone-float{animation:m-float 6.5s ease-in-out infinite}
@media (max-width:768px){.hero.in-view .phone-float{animation:none}}
@keyframes m-float{0%,100%{translate:0 0}50%{translate:0 -10px}}
.phone-mockup-pro{rotate:var(--tilt-x,0) var(--tilt-y,1) 0 var(--tilt-a,0deg);
  transition:rotate .9s var(--m-spring),box-shadow .6s ease}
.hero.pointer .phone-mockup-pro{box-shadow:calc(var(--sh-x,0) * -22px) calc(30px + var(--sh-y,0) * -18px) 80px rgba(0,0,0,.16),0 0 0 1px rgba(0,0,0,.05)}
[data-theme="dark"] .hero.pointer .phone-mockup-pro{box-shadow:calc(var(--sh-x,0) * -22px) calc(30px + var(--sh-y,0) * -18px) 80px rgba(0,0,0,.5),inset 0 0 0 1px rgba(255,255,255,.06)}

/* Leaving the hero: text eases back, the phone sinks into depth. */
@supports (animation-timeline:view()){
  .hero{view-timeline:--hero block}
  .hero-content{animation:m-hero-text linear both;animation-timeline:--hero;animation-range:exit 0% exit 80%}
  .phone-mockup-pro{animation:m-hero-phone linear both;animation-timeline:--hero;animation-range:exit 0% exit 90%}
  .phone-glow{animation:m-hero-glow linear both;animation-timeline:--hero;animation-range:exit 0% exit 70%}
}
@keyframes m-hero-text{to{translate:0 -48px;opacity:.25}}
@keyframes m-hero-phone{to{scale:.9}}
@keyframes m-hero-glow{to{opacity:0}}

/* Pause control for everything that loops (WCAG 2.2.2). */
.motion-toggle{position:absolute;right:20px;bottom:20px;z-index:3;width:36px;height:36px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;color:var(--text-secondary);
  background:var(--bg-card);border:1px solid var(--border-subtle);box-shadow:var(--shadow-sm);
  opacity:.75;transition:opacity .2s ease,color .2s ease,scale .3s var(--m-spring)}
.motion-toggle:hover,.motion-toggle:focus-visible{opacity:1;color:var(--text)}
.motion-toggle:active{scale:.92}
.motion-toggle svg{width:15px;height:15px}
.motion-toggle[hidden],.app-caret[hidden]{display:none}
.motion-toggle .i-play,.motion-toggle[aria-pressed="true"] .i-pause{display:none}
.motion-toggle[aria-pressed="true"] .i-play{display:block}

/* ═══ Live demo inside the phone (built by motion.js) ═══ */
.phone-screen-pro{isolation:isolate;text-align:left}
.odo{display:inline-flex;align-items:flex-start;line-height:1.1;font-variant-numeric:tabular-nums}
.odo-d{display:inline-block;height:1.1em;overflow:hidden;line-height:1.1}
.odo-s{display:flex;flex-direction:column;translate:0 calc(var(--v,0) * -1.1em);
  transition:translate var(--odo-dur,.9s) var(--m-spring) var(--odo-delay,0s)}
.odo-s>span{height:1.1em}
.odo-sep{display:inline-block;height:1.1em;line-height:1.1;white-space:pre}

/* The list takes the room that is left and older rows slip away under a
   fade, so new entries never push the input bar off a small phone. */
.phone-screen-pro .app-tx{flex:1 1 auto;min-height:0;overflow:hidden;
  -webkit-mask-image:linear-gradient(#000 calc(100% - 22px),transparent);mask-image:linear-gradient(#000 calc(100% - 22px),transparent)}
.phone-screen-pro .app-input{flex-shrink:0}
.phone-screen-pro .app-tx-row,.phone-screen-pro .app-saved{flex-shrink:0}
.app-balance{position:relative}
.app-delta{position:absolute;right:14px;top:10px;padding:2px 8px;border-radius:999px;
  font-size:.6rem;font-weight:800;font-variant-numeric:tabular-nums;color:#fff;background:rgba(0,0,0,.22);
  opacity:0;pointer-events:none}
.app-input{position:relative;transition:box-shadow .3s ease,border-color .3s ease}
.app-input.typing{border-color:rgba(230,51,54,.55);box-shadow:0 0 0 3px rgba(230,51,54,.14)}
.app-typed{font-size:.66rem;font-weight:500;color:#f5f5f7;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.app-caret{display:inline-block;width:1.5px;height:12px;margin-left:1px;background:#f87171;vertical-align:middle;
  animation:m-caret 1s steps(1) infinite}
@keyframes m-caret{50%{opacity:0}}
.app-input-text{min-width:0;overflow:hidden}
.app-input-text.has-text .app-line{display:none}
.app-input-mic{position:relative}
.app-input-mic.listening::before,.app-input-mic.listening::after{content:'';position:absolute;inset:0;border-radius:50%;
  border:2px solid rgba(230,51,54,.6);animation:m-ripple 1.4s var(--m-out) infinite}
.app-input-mic.listening::after{animation-delay:.7s}
@keyframes m-ripple{from{transform:scale(1);opacity:.9}to{transform:scale(2.1);opacity:0}}
.app-mini-wave{display:none;align-items:center;gap:2px;height:14px;margin-right:6px}
.app-input.voice .app-mini-wave{display:inline-flex}
.app-mini-wave i{width:2px;height:100%;border-radius:2px;background:#f87171;transform-origin:50% 50%;
  animation:m-bar .7s ease-in-out infinite alternate}
.app-mini-wave i:nth-child(2){animation-delay:-.2s}.app-mini-wave i:nth-child(3){animation-delay:-.45s}
.app-mini-wave i:nth-child(4){animation-delay:-.1s}.app-mini-wave i:nth-child(5){animation-delay:-.35s}

/* What the AI read, popping above the input bar. */
.app-chips{position:absolute;left:13px;right:13px;bottom:62px;z-index:6;display:flex;flex-wrap:wrap;gap:5px;
  justify-content:flex-end;pointer-events:none}
.app-chip{display:inline-flex;align-items:center;gap:4px;padding:4px 8px;border-radius:999px;
  font-size:.56rem;font-weight:700;white-space:nowrap;color:#f5f5f7;
  background:rgba(23,23,26,.92);border:1px solid #2e2e33;box-shadow:0 6px 18px rgba(0,0,0,.35)}
.app-chip.ai{color:#fff;background:linear-gradient(135deg,#e63336,#8f1d1f);border-color:transparent}
.app-chip.exp{color:#fca5a5}.app-chip.inc{color:#86efac}.app-chip.debt{color:#fcd34d}
.app-chip svg{width:9px;height:9px}

.app-tx-title{display:block;font-size:.6rem;font-weight:650;color:#ececf1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.2}
.app-tx-sub{display:block;font-size:.5rem;color:#8b8b93;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.3}
.app-tx-lines{min-width:0}
.app-tx-avatar.exp{background:linear-gradient(135deg,rgba(230,51,54,.55),rgba(143,29,31,.55))}
.app-tx-avatar.inc{background:linear-gradient(135deg,rgba(34,197,94,.55),rgba(21,128,61,.5))}
.app-tx-avatar.debt{background:linear-gradient(135deg,rgba(245,158,11,.6),rgba(180,83,9,.5))}
.app-saved-check svg path{stroke-dasharray:30;stroke-dashoffset:0}
.app-saved.saving .app-saved-check svg path{animation:m-draw .5s var(--m-out) .15s both}
@keyframes m-draw{from{stroke-dashoffset:30}}
.app-chart i{transform-origin:50% 100%;transition:height .9s var(--m-spring)}
/* Saved: a burst from the check (motion.js). */
.app-spark{position:absolute;z-index:7;width:5px;height:5px;border-radius:50%;pointer-events:none;
  background:currentColor;box-shadow:0 0 8px 1px currentColor}

/* ═══ Reveals (one-shot, every browser) ═══
   app.js adds .visible / .revealed and the --i stagger index. */
.motion .reveal:not(.revealed){
  transition:opacity .7s var(--m-out),transform .95s var(--m-spring),filter .7s var(--m-out);
  transition-delay:calc(min(var(--i,0),7) * 65ms)}
.motion .reveal:not(.visible){opacity:0;transform:translateY(var(--m-rise)) scale(.985)}

/* Section titles: the words rise one after another, swinging forward
   from their baseline (motion.js wraps them in .kw). */
.kinetic .kw{display:inline-block;transform-origin:50% 100%}
.motion .reveal .kinetic .kw{transition:opacity .55s var(--m-out),transform 1s var(--m-spring),filter .6s var(--m-out);
  transition-delay:calc(min(var(--w,0),14) * 55ms + 120ms)}
.motion .reveal:not(.visible) .kinetic .kw{opacity:0;filter:blur(6px);transform:perspective(520px) translateY(.4em) rotateX(-72deg)}

/* Children of a revealed block follow in a cascade. */
.motion .spotlight-text.reveal .spotlight-list li,
.motion .plan-card.reveal .check-list li{opacity:0;translate:0 10px;
  transition:opacity .5s var(--m-out),translate .7s var(--m-spring)}
.motion .spotlight-text.reveal.visible .spotlight-list li,
.motion .plan-card.reveal.visible .check-list li{opacity:1;translate:0 0}
.motion .reveal.visible :is(.spotlight-list,.check-list) li:nth-child(1){transition-delay:.25s}
.motion .reveal.visible :is(.spotlight-list,.check-list) li:nth-child(2){transition-delay:.33s}
.motion .reveal.visible :is(.spotlight-list,.check-list) li:nth-child(3){transition-delay:.41s}
.motion .reveal.visible :is(.spotlight-list,.check-list) li:nth-child(4){transition-delay:.49s}
.motion .reveal.visible :is(.spotlight-list,.check-list) li:nth-child(5){transition-delay:.57s}
.motion .plan-card.reveal .check-list li::after{scale:0;transition:scale .5s var(--m-bounce)}
.motion .plan-card.reveal.visible .check-list li::after{scale:1;transition-delay:inherit}

/* ═══ Stats: rolling digits ═══ */
.stat-number .odo-d{height:1.1em}
.stat-number .odo-s{--odo-dur:1.6s}

/* ═══ How it works ═══ */
/* A line runs from step to step and the numbers light up in turn as the
   steps come in from below — all done once the section is on screen. */
.how-steps{position:relative}
.how-step{position:relative}
.how-step:not(:last-child)::after{content:'';position:absolute;left:38px;top:58px;width:2px;
  height:calc(100% - 28px);border-radius:2px;z-index:1;pointer-events:none;
  background:linear-gradient(var(--primary),var(--primary-light));transform-origin:50% 0}
@supports (animation-timeline:view()){
  .how-step:not(:last-child)::after{animation:m-grow-y linear both;animation-timeline:view();animation-range:entry 20% entry 100%}
  .how-num{animation:m-num-fill linear both;animation-timeline:view();animation-range:entry 40% entry 100%}
}
@keyframes m-grow-y{from{scale:1 0}to{scale:1 1}}
@keyframes m-num-fill{
  from{background:var(--bg-alt);color:var(--primary-ink);box-shadow:inset 0 0 0 2px var(--primary-border)}
  to{background:var(--primary);color:var(--on-primary);box-shadow:inset 0 0 0 2px transparent}}
@media (max-width:768px){.how-step:not(:last-child)::after{left:32px;top:54px;height:calc(100% - 28px)}}

/* The examples write themselves on screen: motion.js (Web Animations). */

/* ═══ Features: light that follows the hand ═══ */
.feature-card,.legacy-card{--sx:50%;--sy:50%}
.feature-card::before,.legacy-card::before{content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  opacity:0;transition:opacity .35s ease;
  background:radial-gradient(420px circle at var(--sx) var(--sy),var(--primary-soft),transparent 45%)}
.feature-card::after{content:'';position:absolute;inset:-1px;border-radius:inherit;pointer-events:none;
  padding:1px;opacity:0;transition:opacity .35s ease;
  background:radial-gradient(260px circle at var(--sx) var(--sy),var(--primary-border),transparent 60%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;
  mask:linear-gradient(#000 0 0) content-box exclude,linear-gradient(#000 0 0)}
.spotlit .feature-card:hover::before,.spotlit .feature-card:hover::after,
.spotlit .legacy-card:hover::before{opacity:1}
.legacy-card>*{position:relative}
.feature-card>*{position:relative}
.feature-card .pill-corner{position:absolute}
.feature-icon{transition:transform .5s var(--m-bounce)}
.feature-card:hover .feature-icon{transform:translateY(-2px) rotate(-6deg) scale(1.08)}

/* Cards lean towards the pointer in 3D; motion.js springs --rx/--ry/--lift
   and the icon and visual stand a little off the surface. */
.spotlit .tilting{transform:perspective(1000px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg)) translateY(calc(var(--lift,0) * -4px));
  transform-style:preserve-3d;transition-property:box-shadow,border-color,background-color}
.spotlit .tilting :is(.feature-icon,.legacy-icon,.card-visual){translate:0 0 calc(var(--lift,0) * 26px)}
.spotlit .tilting :is(h3,.check-list){translate:0 0 calc(var(--lift,0) * 12px)}

/* Card visuals come alive on screen. */
.features.in-view .wave i{transform-origin:50% 50%;animation:m-bar 1.1s ease-in-out infinite alternate}
.wave i:nth-child(4n+1){animation-delay:-.2s!important}.wave i:nth-child(4n+2){animation-delay:-.55s!important}
.wave i:nth-child(4n+3){animation-delay:-.85s!important}.wave i:nth-child(4n){animation-delay:-.35s!important}
.wave i:nth-child(3n){animation-duration:.8s!important}.wave i:nth-child(5n){animation-duration:1.35s!important}
@keyframes m-bar{from{transform:scaleY(.35)}to{transform:scaleY(1)}}
.mini-chart i,.app-chart i{transform-origin:50% 100%}
@supports (animation-timeline:view()){
  .mini-chart i{animation:m-bar-grow linear both;animation-timeline:view();
    animation-range:entry calc(20% + var(--n,0) * 4%) cover calc(30% + var(--n,0) * 3%)}
}
@keyframes m-bar-grow{from{transform:scaleY(.05)}to{transform:scaleY(1)}}
.mini-chart i:nth-child(2){--n:1}.mini-chart i:nth-child(3){--n:2}.mini-chart i:nth-child(4){--n:3}
.mini-chart i:nth-child(5){--n:4}.mini-chart i:nth-child(6){--n:5}.mini-chart i:nth-child(7){--n:6}
.mini-chart i:nth-child(8){--n:7}.mini-chart i:nth-child(9){--n:8}.mini-chart i:nth-child(10){--n:9}
.mini-chart i:nth-child(11){--n:10}.mini-chart i:nth-child(12){--n:11}
.features.in-view .plan-row.hot .dot{animation:m-alarm 2.4s ease-out infinite}
.features.in-view .plan-row.hot b{animation:m-ring 2.4s ease-in-out infinite}
@keyframes m-alarm{0%{box-shadow:0 0 0 0 var(--primary-glow)}60%,100%{box-shadow:0 0 0 9px transparent}}
@keyframes m-ring{0%,70%,100%{rotate:0deg}74%{rotate:-8deg}78%{rotate:8deg}82%{rotate:-6deg}86%{rotate:5deg}90%{rotate:0deg}}
.plan-row b{display:inline-block}

/* ═══ Voice spotlight ═══ */
.voice-orb{position:relative}
.spotlight.in-view .voice-orb{animation:orbPulse 3.2s ease-in-out infinite}
.spotlight .voice-orb{animation:none}
.voice-orb::before,.voice-orb::after{content:'';position:absolute;inset:0;border-radius:50%;
  border:1.5px solid rgba(240,81,78,.55);opacity:0;pointer-events:none}
.spotlight.in-view .voice-orb::before{animation:m-listen 2.6s var(--m-out) infinite}
.spotlight.in-view .voice-orb::after{animation:m-listen 2.6s var(--m-out) 1.3s infinite}
@keyframes m-listen{from{transform:scale(1);opacity:.75}to{transform:scale(1.9);opacity:0}}
.spotlight.in-view .voice-orb span{animation:m-breath 1.6s ease-in-out infinite alternate}
@keyframes m-breath{from{transform:scale(.9)}to{transform:scale(1.12)}}
.spotlight.in-view .wave-sm i{transform-origin:50% 50%;animation:m-bar .9s ease-in-out infinite alternate}
.wave-sm i:nth-child(2n){animation-duration:.65s!important}.wave-sm i:nth-child(3n){animation-duration:1.15s!important}
.wave-sm i:nth-child(2){animation-delay:-.3s!important}.wave-sm i:nth-child(4){animation-delay:-.6s!important}
.wave-sm i:nth-child(6){animation-delay:-.15s!important}.wave-sm i:nth-child(8){animation-delay:-.45s!important}
/* Female ⇄ male: a sliding pill (motion.js flips .male). */
.voice-switch{position:relative;isolation:isolate}
.motion .voice-switch span.on{background:transparent;color:#fff}
.motion .voice-switch span{position:relative;transition:color .35s ease}
.motion .voice-switch::before{content:'';position:absolute;z-index:-1;top:4px;bottom:4px;left:4px;border-radius:999px;background:#D3312F;
  width:var(--vs-w,50%);translate:var(--vs-x,0) 0;transition:translate .55s var(--m-spring),width .55s var(--m-spring)}
.voice-cards .voice-card{transition:opacity .4s ease,translate .7s var(--m-bounce),scale .7s var(--m-bounce)}
.voice-cards.cycling .voice-card{opacity:0;translate:0 12px;scale:.96}
.voice-cards.cycling .voice-card.shown{opacity:1;translate:0 0;scale:1}

/* ═══ Legacy band: the check-in pulse ═══ */
/* Runs along the foot of the band, under the call to action. */
.legacy-pulse{position:absolute;left:0;right:0;bottom:8px;width:100%;height:96px;pointer-events:none;opacity:.6}
.legacy-pulse path{fill:none;stroke-width:1.5;stroke-linejoin:round;stroke-linecap:round;vector-effect:non-scaling-stroke}
.legacy-pulse .base{stroke:rgba(240,81,78,.35);stroke-dasharray:1;stroke-dashoffset:0}
.legacy-pulse .comet{stroke:#FF6B67;stroke-width:2.5;stroke-dasharray:.07 .93;stroke-dashoffset:1;opacity:0;
  filter:drop-shadow(0 0 6px rgba(255,107,103,.9))}
.legacy.in-view .legacy-pulse .comet{opacity:1;animation:m-comet 3.8s linear infinite}
@keyframes m-comet{from{stroke-dashoffset:1}to{stroke-dashoffset:0}}
@supports (animation-timeline:view()){
  .legacy-pulse .base{animation:m-draw-line linear both;animation-timeline:view();animation-range:entry 0% entry 50%}
  .legacy-card:not(:last-child)::after{transform-origin:0 50%;animation:m-grow-x linear both;animation-timeline:view();animation-range:entry 50% entry 100%}
}
@keyframes m-draw-line{from{stroke-dashoffset:1}to{stroke-dashoffset:0}}
/* The dark band arrives as a rounded panel and opens to full width as it
   rises into view, like a curtain drawn aside. */
@supports (animation-timeline:view()){
  .legacy{animation:m-curtain linear both;animation-timeline:view();animation-range:entry 0% entry 70%}
}
@keyframes m-curtain{from{clip-path:inset(0 5% round 44px)}to{clip-path:inset(0 0 round 0)}}
.legacy .section-inner{z-index:1}
@media (max-width:768px){.legacy-pulse{height:64px;bottom:4px;opacity:.45}}

/* ═══ Plans: the premium card's border catches the light ═══ */
@property --m-angle{syntax:'<angle>';inherits:false;initial-value:0deg}
.plan-premium{position:relative;isolation:isolate}
.plan-premium::before{content:'';position:absolute;inset:-1px;border-radius:inherit;padding:1.5px;pointer-events:none;z-index:1;
  background:conic-gradient(from var(--m-angle),transparent 0 62%,var(--primary-light) 76%,var(--primary) 84%,transparent 96%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;
  mask:linear-gradient(#000 0 0) content-box exclude,linear-gradient(#000 0 0);opacity:0;transition:opacity .6s ease}
.plans.in-view .plan-premium::before{opacity:1;animation:m-spin 6s linear infinite}
@keyframes m-spin{to{--m-angle:360deg}}

/* ═══ FAQ: answers unfold (Chromium: ::details-content + height:auto) ═══ */
.faq-item::details-content{block-size:0;overflow:clip;
  transition:block-size .45s var(--m-out),content-visibility .45s allow-discrete}
.faq-item[open]::details-content{block-size:auto}
.faq-item p{transition:opacity .4s ease .08s,translate .5s var(--m-out) .08s}
.faq-item:not([open]) p{opacity:0;translate:0 -6px}
.faq-item summary::after{transition:transform .5s var(--m-spring)}

/* ═══ Download panel ═══ */
.download-inner{transform-origin:50% 100%}
.download-inner::after{content:'';position:absolute;inset:-40%;pointer-events:none;z-index:0;
  background:linear-gradient(105deg,transparent 42%,rgba(255,255,255,.16) 50%,transparent 58%);translate:-60% 0}
.download.in-view .download-inner::after{animation:m-sheen 7s var(--m-in-out) 1.2s infinite}
@keyframes m-sheen{0%{translate:-60% 0}35%,100%{translate:60% 0}}
@supports (animation-timeline:view()){
  .download-inner{animation:m-panel linear both;animation-timeline:view();animation-range:entry 0% entry 90%}
}
@keyframes m-panel{from{scale:.92;border-radius:48px}to{scale:1}}

/* ═══ Pause / reduced motion ═══ */
.motion-paused .hero-aurora .bp{opacity:0}

@media (prefers-reduced-motion:reduce){
  @view-transition{navigation:none}
  .hero .fade-up,.hero-buttons.fade-up>*,.trust-row.fade-up>*,.hero h1.fade-up span,.hero-image.fade-up{animation:none;clip-path:none}
  .hero-aurora i,.phone-float,.phone-mockup-pro,.hero-content,.phone-glow,.scroll-progress,
  .how-step::after,.how-num,.mini-chart i,.legacy-pulse .base,.download-inner,.voice-orb,.voice-orb span{animation:none!important}
  .scroll-progress{display:none}
  .phone-mockup-pro{rotate:none}
  .motion .reveal,.motion .reveal:not(.visible){opacity:1;transform:none;filter:none;transition:none}
  .motion .reveal :is(.spotlight-list,.check-list) li,.motion .plan-card.reveal .check-list li::after{opacity:1;translate:none;scale:1;transition:none}
  .legacy-pulse .comet,.voice-orb::before,.voice-orb::after,.plan-premium::before,.download-inner::after{display:none}
  .wave i,.wave-sm i,.plan-row .dot,.plan-row b,.legacy-card::after,.app-caret{animation:none!important}
  .faq-item::details-content{transition:none}
  .faq-item:not([open]) p{opacity:1;translate:none}
  .motion-toggle{display:none}
  .magnetic{translate:none}
  .header{transition:none}
  .hdr-menu .nav,.hdr-menu .nav a{translate:none;scale:none}
  .motion .reveal .kinetic .kw,.motion .reveal:not(.visible) .kinetic .kw{opacity:1;filter:none;transform:none;transition:none}
  .spotlit .tilting{transform:none}
  .spotlit .tilting *{translate:none}
  .legacy{animation:none!important;clip-path:none}
}
