/* Bewegungsebene. Diese Zustände gelten nur, wenn GSAP läuft und Bewegung
   nicht reduziert ist (html.motion). Ohne JavaScript oder mit
   prefers-reduced-motion bleibt alles statisch sichtbar. */
.scroll-progress{position:fixed;z-index:70;inset:0 0 auto;height:3px;background:var(--blue);transform:scaleX(0);transform-origin:left;pointer-events:none}
html:not(.motion) .scroll-progress{display:none}

@keyframes caret{50%{opacity:0}}
@keyframes dot{0%,70%,100%{transform:translateY(0);opacity:.35}35%{transform:translateY(-4px);opacity:1}}
.type-caret,.chapter-caret{animation:caret 1s steps(1,end) infinite}
.chapter-caret{display:inline-block;width:2px;height:.95em;margin-left:2px;border-radius:1px;background:var(--blue);vertical-align:-.1em}
.chat-dots i{animation:dot 1.1s ease-in-out infinite}
.chat-dots i:nth-child(2){animation-delay:.15s}
.chat-dots i:nth-child(3){animation-delay:.3s}

/* Bis GSAP übernimmt, bleiben die Start-Elemente verborgen, damit nichts aufblitzt. */
.motion:not(.motion-ready) .code-title .code-line>span:last-child,
.motion:not(.motion-ready) .portrait-note,
.motion:not(.motion-ready) .hero-intro,
.motion:not(.motion-ready) .hero-sculpture,
.motion:not(.motion-ready) .hero-caption,
.motion:not(.motion-ready) .hero-foot{visibility:hidden}
.motion .hero-sculpture{animation:none}
.motion-ready .hero-title-wrap,.motion-ready .hero-sculpture,.motion-ready .portrait-note,.motion-ready .about-photo{will-change:transform}

/* Northline: Karten stapeln sich beim Scrollen. Nur auf großen, hohen Ansichten. */
.deck.is-stacked{display:block}
.deck.is-stacked .deck-item{position:sticky;top:calc(var(--deck-top,96px) + var(--i,0)*12px);margin-bottom:26svh}
.deck.is-stacked .deck-item:last-child{margin-bottom:0}
.deck.is-stacked .product-card{transform-origin:50% 0;box-shadow:0 -18px 44px #05060d85;will-change:transform,filter}

/* Schrittweise hervorgehobene Elemente */
.motion-ready .reader-machine .jl[data-pair]{opacity:.42}
.motion-ready .reader-machine .jl[data-pair].is-lit{opacity:1}
.motion-ready .phone-notes li{opacity:.45}
.motion-ready .phone-notes li.is-lit{opacity:1}

/* Ruhige Dauerbewegung im Start: das Leuchten atmet, der Pfeil nickt. */
@keyframes glow{from{transform:translate3d(-3%,0,0) scale(1);opacity:.6}to{transform:translate3d(5%,0,0) scale(1.08);opacity:.9}}
@keyframes nudge{0%,60%,100%{transform:translateY(0)}30%{transform:translateY(4px)}}
.motion.ambient .hero:before{animation:glow 9s ease-in-out infinite alternate}
.motion.ambient .scroll-cue>span{animation:nudge 2.2s ease-in-out infinite}

/* Cue-Demo: Wellenform, Statuspunkt, Logo und Platzhalter bewegen sich nur, solange etwas passiert. */
@keyframes cue-wave{from{transform:scaleY(.16)}to{transform:scaleY(1)}}
@keyframes cue-ping{from{box-shadow:0 0 0 0 #ff6b8b99}to{box-shadow:0 0 0 9px #ff6b8b00}}
@keyframes cue-spin{to{transform:rotate(1turn)}}
@keyframes cue-shimmer{to{background-position:-200% 0}}
.cue-app[data-state=listening] .cue-wave i{animation:cue-wave var(--d,.8s) ease-in-out var(--o,0s) infinite alternate}
.cue-app[data-state=answering] .cue-wave i{animation:cue-wave 1.6s ease-in-out var(--o,0s) infinite alternate;opacity:.5}
.cue-app[data-state=listening] .cue-status>i{animation:cue-ping 1.2s ease-out infinite}
.cue-app[data-state=listening] .cue-logo i,.cue-app[data-state=thinking] .cue-logo i,.cue-app[data-state=answering] .cue-logo i{animation:cue-spin 2.4s linear infinite}
.cue-card.is-thinking .cue-answer{animation:cue-shimmer 1.1s linear infinite}
.cue-caret{animation:caret 1s steps(1,end) infinite}
@keyframes cue-border{to{--cue-angle:360deg}}
.cue-app[data-state=thinking] .cue-card:before,.cue-app[data-state=answering] .cue-card:before{animation:cue-border 2.2s linear infinite}
.cue-app[data-state=listening] .cue-hint i{animation:dot 1.1s ease-in-out infinite}
.cue-hint i:nth-of-type(2){animation-delay:.15s!important}.cue-hint i:nth-of-type(3){animation-delay:.3s!important}
