/* motion.css — Bewegungssprache der Website.
   Quelle: design-system/MOTION.md (Kurven, Zeiten, Regeln). Werte hier sind
   1:1 daraus: Feder statt Gleiten, einer nach dem anderen, ein Element
   dominiert, nach gut einer Sekunde steht die Seite und atmet nur noch.
   Geladen von allen Seiten; Bausteine sind mit `mo-`/`mm` präfixiert, damit
   nichts mit den seiteneigenen Klassen (z. B. .after auf /c) kollidiert.

   Federkurven als CSS-linear(), abgetastet aus 1 − e^(−d·k)·cos(f·π·k):
   --sp   f 3,2  d 5   Standard (Figuren, Karten)
   --spw  f 2,4  d 6   Wörter (kinetische Zeile)
   --bo   backOut c 1,9  Stempel, X, Ziffern */

:root{
  --sp:linear(0,.145,.318,.499,.675,.835,.970,1.078,1.157,1.207,1.232,1.235,1.221,1.195,1.162,1.124,1.086,1.051,1.020,.994,.975,.961,.953,.951,.952,.956,.962,.970,.978,.986,.993,.999,1.003,1.007,1.009,1.010,1.010,1.010,1.009,1.007,1.005,1);
  --spw:linear(0,.155,.311,.462,.600,.722,.827,.913,.981,1.032,1.069,1.093,1.105,1.110,1.107,1.100,1.090,1.078,1.065,1.052,1.040,1.029,1.020,1.012,1.005,1.000,.996,.994,.992,.991,.991,.991,.992,.993,.994,.995,.996,.997,.998,.999,1);
  --bo:linear(0,.156,.297,.425,.539,.641,.731,.810,.878,.936,.985,1.025,1.058,1.082,1.101,1.112,1.119,1.121,1.118,1.112,1.104,1.093,1.080,1.067,1.053,1.039,1.027,1.016,1.008,1.002,1);
  --ease-out:cubic-bezier(.2,.7,.3,1);
}

/* ---------- Luftblasen: der Grund jedes Lobby-Screens ----------
   26 weiße Kreise, 10 % Deckkraft, steigen langsam auf und setzen unten
   wieder ein. Position, Größe, Tempo je Blase fest aus einem Hash (motion.js),
   nie Zufall. Nur transform, kein Layout. */
.bubbles{position:fixed; inset:0; z-index:0; pointer-events:none; overflow:hidden}
.bubbles i{
  position:absolute; bottom:0; left:var(--x);
  width:var(--d); height:var(--d); border-radius:50%;
  background:#fff; opacity:.1;
  animation:mo-rise var(--t) linear var(--dl) infinite;
  will-change:transform;
}
@keyframes mo-rise{
  from{transform:translate3d(0,var(--d),0)}
  50%{transform:translate3d(var(--sw),calc(-50vh - var(--d)),0)}
  to{transform:translate3d(0,calc(-100vh - var(--d) * 2),0)}
}

/* ---------- Auftritt: einer nach dem anderen ---------- */
/* Alles, was `data-rise` trägt, fliegt mit Feder ein. Staffel über --i. */
[data-rise]{
  animation:mo-rise-in .55s var(--sp) backwards;
  animation-delay:calc(var(--d0,0s) + var(--i,0) * var(--st,.1s));
}
@keyframes mo-rise-in{
  from{opacity:0; transform:translateY(var(--dy,22px)) scale(var(--s0,.96))}
  to{opacity:1; transform:none}
}
/* Karten und Blöcke, die erst beim Scrollen ins Bild kommen. */
.mo [data-in]{opacity:0}
.mo [data-in].in{opacity:1; animation:mo-rise-in .6s var(--sp) backwards; animation-delay:calc(var(--i,0) * .1s)}
.mo [data-in].in[data-rise]{animation-delay:calc(var(--i,0) * .1s)}

/* ---------- Kinetische Zeile ----------
   Wort für Wort, 0,08 s Staffel. Jedes Wort fällt aus 52 pt, wächst von
   20 % auf 100 % und dreht sich aus bis zu ±0,45 rad in eine kleine
   Ruhelage. Schlüsselwort (.key, Sonnengelb) pulst, wenn die Zeile steht.
   In Ruhe schwebt jedes Wort minimal und kippelt. */
.mo [data-kin],.mo [data-kin-in]{visibility:hidden}
.mo [data-kin].ready,.mo [data-kin-in].ready{visibility:visible}
/* data-kin-in: dieselbe Zeile, spielt aber erst, wenn sie ins Bild scrollt. */
.mo [data-kin-in] .mo-w{animation-play-state:paused}
.mo [data-kin-in].in .mo-w{animation-play-state:running}
.mo-w{
  display:inline-block; --rest:0deg;
  rotate:var(--rest);
  animation:
    mo-word .55s var(--spw) backwards,
    mo-float 5.2s ease-in-out calc(var(--kd,.15s) + var(--i) * .08s + 1.1s) infinite;
  animation-delay:calc(var(--kd,.15s) + var(--i) * .08s), calc(var(--kd,.15s) + var(--i) * .08s + 1.1s);
}
.mo-w.key{
  color:var(--sun);
  animation:
    mo-word .55s var(--spw) backwards,
    mo-pulse .6s ease-in-out calc(var(--kd,.15s) + var(--i) * .08s + .75s),
    mo-float 5.2s ease-in-out calc(var(--kd,.15s) + var(--i) * .08s + 1.5s) infinite;
  animation-delay:calc(var(--kd,.15s) + var(--i) * .08s), calc(var(--kd,.15s) + var(--i) * .08s + .75s), calc(var(--kd,.15s) + var(--i) * .08s + 1.5s);
}
@keyframes mo-word{
  from{opacity:0; transform:translateY(-52px) scale(.2) rotate(var(--r0,.3rad))}
  to{opacity:1; transform:none}
}
@keyframes mo-float{
  0%,100%{translate:0 0; rotate:var(--rest)}
  50%{translate:0 -3px; rotate:calc(var(--rest) + .7deg)}
}
@keyframes mo-pulse{50%{scale:1.12}}

/* ---------- Figur (MimicFigureView im Web) ----------
   Pose + Gesicht als Overlay, damit die Augen blinzeln können.
   Auftritt: von unten mit Feder, landet mit kurzem Stauchen (110 %/90 %,
   0,15 s). Leerlauf: atmen (Höhe ±2 %, ~2,4 s), alle 3 bis 5 s blinzeln.
   Mehrere Figuren nie im Gleichtakt: --bd (Blinzelperiode) und --bo
   (Versatz) je Figur. */
.mm{
  position:relative; display:inline-block; width:var(--w,52px); flex:none;
  transform-origin:50% 100%;
  animation:
    mo-land .65s var(--sp) var(--md,0s) backwards,
    mo-squash .2s ease-out calc(var(--md,0s) + .5s);
}
.mm-in{
  position:relative; display:block; transform-origin:50% 100%;
  animation:mo-breathe 2.4s ease-in-out calc(var(--md,0s) + 1.2s + var(--bo,0s)) infinite;
}
.mm-in>img.mm-body{display:block; width:100%; height:auto}
.mm-face{
  position:absolute; left:50%; top:30.8%; transform:translate(-50%,-50%);
  display:flex; flex-direction:column; align-items:center;
  gap:calc(var(--w,52px) * .392 * .12); pointer-events:none;
}
.mm-face img{display:block; height:auto; max-width:none}
.mm-eyes{
  width:calc(var(--w,52px) * .392 * 1.16);
  animation:mo-blink var(--bd,4.2s) ease-in-out calc(var(--md,0s) + 2s + var(--bo,0s)) infinite;
}
.mm-mouth{width:calc(var(--w,52px) * .392 * .72)}
@keyframes mo-land{from{opacity:0; transform:translateY(90px)} to{opacity:1; transform:none}}
@keyframes mo-squash{50%{scale:1.1 .9}}
@keyframes mo-breathe{50%{transform:scaleY(1.02)}}
@keyframes mo-blink{0%,94%,100%{scale:1 1} 97%{scale:1 .1}}
/* Hüpfer beim Antippen (motion.js setzt .hop) */
.mm.hop{animation:mo-hop .5s var(--sp)}
@keyframes mo-hop{from{transform:translateY(0)} 30%{transform:translateY(-18px) scale(.94,1.08)} to{transform:none}}

/* ---------- Truppe (nur Desktop): landet, atmet, nie im Gleichtakt ----------
   Die Positionen der Figuren stehen in `transform` (drehen, spiegeln); die
   Bewegung läuft deshalb über die einzelnen Eigenschaften translate/scale. */
.troupe img{
  transform-origin:50% 100%;
  animation:
    mo-troupe-in .75s var(--sp) calc(.35s + var(--i,0) * .12s) backwards,
    mo-squash .2s ease-out calc(.9s + var(--i,0) * .12s),
    mo-breathe-s 2.6s ease-in-out calc(1.6s + var(--i,0) * .37s) infinite;
}
@keyframes mo-troupe-in{from{opacity:0; translate:0 110px} to{opacity:.92; translate:0 0}}
@keyframes mo-breathe-s{50%{scale:1 1.03}}
.t1{--i:0} .t2{--i:1} .t3{--i:2} .t4{--i:3} .t5{--i:4} .t6{--i:5}
.t2{animation-duration:.75s,.2s,2.9s} .t4{animation-duration:.75s,.2s,2.3s} .t6{animation-duration:.75s,.2s,3.1s}

/* ---------- Knöpfe ----------
   Chunky: Drücken senkt um die Unterkante ab (steht in den Seiten), Loslassen
   federt. Der Hauptknopf glänzt alle paar Sekunden EINMAL (Lichtstreif).
   Apples App-Store-Badge bleibt unverändert (Marketing Guidelines): keine
   Overlays auf dem Bild, stattdessen pulsiert ein Ring HINTER ihm. */
.mo-shine,.is-android .wl-btn{position:relative; overflow:hidden}
.mo-shine::after,.is-android .wl-btn::after{
  content:''; position:absolute; top:0; bottom:0; width:38%; left:-60%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.55),transparent);
  transform:skewX(-20deg); pointer-events:none;
  animation:mo-shine 4.2s ease-in-out 2.4s infinite;
}
@keyframes mo-shine{0%,58%{left:-60%} 88%,100%{left:135%}}

.mo-halo{position:relative; isolation:isolate}
.mo-halo::before{
  content:''; position:absolute; inset:0; border-radius:12px; z-index:-1;
  box-shadow:0 0 0 0 rgba(255,197,49,.55);
  animation:mo-halo 3.6s ease-out 2.6s infinite;
}
@keyframes mo-halo{0%{box-shadow:0 0 0 0 rgba(255,197,49,.6)} 45%,100%{box-shadow:0 0 0 16px rgba(255,197,49,0)}}
.store-badge{transition:transform .35s var(--sp)}
.store-badge:hover{transform:translateY(-3px) scale(1.03)}
.store-badge:active{transform:translateY(2px) scale(.98); transition-duration:.06s}
.social a{transition-timing-function:var(--sp); transition-duration:.35s}
.social a:active{transform:translateY(2px) scale(.94); transition-duration:.06s}

/* ---------- Wie es läuft: Ziffern rasten ein ---------- */
.mo .steps li[data-in].in::before{animation:mo-stamp .5s var(--bo) calc(var(--i,0) * .1s + .25s) backwards}
@keyframes mo-stamp{from{opacity:0; transform:scale(2.4) rotate(-12deg)} to{opacity:1; transform:none}}
.steps li{transition:transform .4s var(--sp)}
.steps li:hover{transform:translateY(-4px) rotate(-.5deg)}
.steps li:nth-child(2):hover{transform:translateY(-4px) rotate(.5deg)}

/* ---------- Unterseiten: Bühne kommt herein ---------- */
.sheet{animation:mo-rise-in .6s var(--sp) .2s backwards; --dy:28px}
.bar .mark{animation:mo-rise-in .55s var(--sp) .25s backwards; --dy:-10px}
.mo-stagger>*{animation:mo-rise-in .55s var(--sp) backwards; animation-delay:calc(.45s + var(--i,0) * .1s)}

/* ---------- Mini-Spiel auf der Startseite ---------- */
/* Tipp: Punkt plus Ring, der aufgeht und ausblendet (0,6 s). */
.fx-tap{position:absolute; z-index:4; width:0; height:0; pointer-events:none}
.fx-tap::before{
  content:''; position:absolute; left:-5px; top:-5px; width:10px; height:10px; border-radius:50%;
  background:#fff; box-shadow:0 0 0 2px var(--outline);
  animation:mo-dot .4s ease-out forwards;
}
.fx-tap::after{
  content:''; position:absolute; left:-14px; top:-14px; width:28px; height:28px; border-radius:50%;
  border:4px solid var(--primary); box-shadow:0 0 0 2px var(--outline);
  animation:mo-ring .6s var(--ease-out) forwards;
}
@keyframes mo-dot{to{opacity:0; transform:scale(.4)}}
@keyframes mo-ring{from{opacity:1; transform:scale(.35)} to{opacity:0; transform:scale(2.6)}}

/* Fehlklick: rotes X mit Kontur, rastet mit backOut ein, wackelt, fällt nach 1 s weg. */
:is(.shot,.ch .stage) .miss{
  position:absolute; z-index:4; width:30px; height:30px; margin:-15px 0 0 -15px;
  pointer-events:none; animation:mo-x 1s ease-out forwards;
}
:is(.shot,.ch .stage) .miss::before,:is(.shot,.ch .stage) .miss::after{
  content:''; position:absolute; left:50%; top:50%; width:28px; height:6px;
  margin:-3px 0 0 -14px; border-radius:3px; background:#FF5A5A;
  box-shadow:0 0 0 2.5px var(--outline);
}
:is(.shot,.ch .stage) .miss::before{rotate:45deg}
:is(.shot,.ch .stage) .miss::after{rotate:-45deg}
@keyframes mo-x{
  0%{opacity:0; transform:scale(0) rotate(0deg); animation-timing-function:var(--bo)}
  25%{opacity:1; transform:scale(1) rotate(10deg)}
  40%{transform:scale(1) rotate(-8deg)}
  70%{opacity:1; transform:scale(1) rotate(0deg)}
  100%{opacity:0; transform:translateY(22px) scale(.2)}
}

/* Blitz: weißes Aufleuchten bis 55 %, 0,25 s. */
.fx-flash{position:absolute; inset:0; z-index:6; background:#fff; pointer-events:none; opacity:0}

/* Spotlight: Bild dunkelt auf 72 % Tiefsee ab, ein Kreis bleibt frei, Ring in Sonnengelb.
   Der Abdunkler ist der Box-Shadow eines riesigen Rings; Skalieren des Rings
   zieht das Licht auf die Figur zu. */
.fx-spot{
  position:absolute; z-index:2; pointer-events:none; aspect-ratio:1; border-radius:50%;
  width:var(--sw,54%); left:var(--sx); top:var(--sy); translate:-50% -50%;
  box-shadow:0 0 0 4px var(--sun), 0 0 0 200vmax rgba(6,53,64,.72);
  opacity:0;
}

/* Funken und Konfetti (motion.js erzeugt sie). */
.fx-spark{
  position:absolute; z-index:5; width:var(--z,16px); height:var(--z,16px); margin:calc(var(--z,16px) / -2) 0 0 calc(var(--z,16px) / -2);
  background:var(--c,#fff); pointer-events:none;
  clip-path:polygon(50% 0,60% 40%,100% 50%,60% 60%,50% 100%,40% 60%,0 50%,40% 40%);
}
.fx-conf{position:absolute; z-index:5; top:-14px; width:9px; height:14px; pointer-events:none; border-radius:2px}
.fx-wipe{
  position:absolute; z-index:7; top:-10%; bottom:-10%; left:-40%; width:60%; pointer-events:none;
  background:linear-gradient(90deg,var(--primary),var(--primary-deep)); transform:skewX(-14deg); opacity:0;
}

/* Startschild schwebt, damit klar ist: hier antippen. */
:is(.shot,.ch .stage).idle .prompt b{animation:mo-float 3.4s ease-in-out infinite}
:is(.shot,.ch .stage){animation:mo-shot-in .75s var(--sp) .3s backwards}
@keyframes mo-shot-in{from{opacity:0; transform:translateY(70px) scale(.94)} to{opacity:1; transform:none}}

/* Endkarte: Stempel fliegt aus 240 % ein, danach Zeile, dann Knopf als Letztes. */
:is(.shot,.ch .stage).found .end :is(h2,h3),:is(.shot,.ch .stage).lost .end :is(h2,h3){animation:mo-stamp-h .7s var(--bo) .05s backwards; transform-origin:50% 60%}
:is(.shot,.ch .stage).found .end :is(h2,h3){rotate:-4deg}
:is(.shot,.ch .stage).lost .end :is(h2,h3){rotate:3deg}
:is(.shot,.ch .stage).found .end p,:is(.shot,.ch .stage).lost .end p{animation:mo-rise-in .55s var(--sp) .45s backwards}
:is(.shot,.ch .stage).found .end .store-badge,:is(.shot,.ch .stage).lost .end .store-badge{animation:mo-rise-in .55s var(--sp) .75s backwards}
@keyframes mo-stamp-h{from{opacity:0; transform:scale(2.4)} 35%{opacity:1} to{opacity:1; transform:none}}
:is(.shot,.ch .stage) .hud .clock{display:inline-block; min-width:1.4em; text-align:right}
:is(.shot,.ch .stage) .hud.late .clock{color:var(--sun)}
:is(.shot,.ch .stage) .hud.late.pop .clock{animation:mo-tick .3s var(--bo)}
@keyframes mo-tick{from{transform:scale(1.35)} to{transform:none}}
:is(.shot,.ch .stage) .end .score{display:inline-block}
:is(.shot,.ch .stage) .score b{display:inline-block; font-weight:inherit}
:is(.shot,.ch .stage) .score.hop{animation:mo-tick .35s var(--bo)}

/* ---------- Weniger Bewegung ----------
   Federn, Schweben, Wackeln, Blitz, Blasen entfallen. Elemente blenden in
   0,2 s ein, Zahlen stehen sofort, Figuren atmen nicht. Die Information
   bleibt vollständig. (Ersetzt die alte Pauschalregel der Seiten: Sie hätte
   die Dauerschleifen auf 0,01 ms gedrückt, also flackern lassen.) */
@media(prefers-reduced-motion:reduce){
  .bubbles{display:none}
  [data-rise],.wordmark,.mo [data-in].in,.mo-w,.mo-w.key,.mm,.troupe img,.sheet,.bar .mark,.mo-stagger>*,:is(.shot,.ch .stage),
  :is(.shot,.ch .stage).found .end :is(h2,h3),:is(.shot,.ch .stage).lost .end :is(h2,h3),:is(.shot,.ch .stage).found .end p,:is(.shot,.ch .stage).lost .end p,
  :is(.shot,.ch .stage).found .end .store-badge,:is(.shot,.ch .stage).lost .end .store-badge{
    animation:mo-fade .2s ease-out backwards !important; animation-delay:0s !important;
  }
  .mm-in,.mm-eyes,.mo-shine::after,.is-android .wl-btn::after,.mo-halo::before,:is(.shot,.ch .stage).idle .prompt b,
  .mo .steps li[data-in].in::before{animation:none !important}
  .mm-in{transform:none}
  .steps li,.steps li:hover,.store-badge,.store-badge:hover,.store-badge:active{transition:none; transform:none}
  html{scroll-behavior:auto}
}
@keyframes mo-fade{from{opacity:0} to{opacity:1}}
