/* Bewegung. Besitzer: Whimsy Injector.

   Diese Datei ist der EINZIGE Ort im Projekt fuer @keyframes, animation und
   den reduzierte-Bewegung-Block. Sie legt KEINE eigenen Klassen an — sie
   gestaltet ausschliesslich Haken, die leiste.js, ansicht-support.js,
   ansicht-anrufer.js und lobby.js setzen (Spec §5.4). Kein Konfetti, keine
   Cartoon-Physik: der Witz liegt in der Beobachtung, Bewegung ist hier
   Information ueber Zustandswechsel, nicht Dekoration (Spec §2.5).

   Alle Keyframe-Namen beginnen mit bw- (genau die acht aus Plan Aufgabe 9,
   Schritt 2 — mehrfach verwendet statt vermehrt, siehe unten).
   stil-schnitt.test.js prueft den Schnitt.

   Speziallage Warteschlange: leiste.js schreibt data-wartet-s/data-geduld-s
   auf JEDE Anrufzeile, dauerhaft — auch auf einer, die gerade erst
   .anrufzeile--neu traegt oder gleich .anrufzeile--geht bekommt. Der
   Alterungsselektor .anrufzeile[data-wartet-s] ist dadurch IMMER genauso
   oder hoeher spezifisch als --neu/--geht allein. Bei einer Kollision der
   animation-Kurzschreibweise gewinnt die hoehere Spezifitaet die GESAMTE
   Eigenschaft, nicht nur die Differenz — der Eintritts-/Austrittseffekt
   wuerde sonst lautlos verschluckt. Deshalb unten Langform (animation-name
   etc. als Kommaliste) auf zusammengesetzten Selektoren, die beide
   Animationen explizit nebeneinander benennen. */

/* --- Schichtstart -------------------------------------------------------
   Haken body[data-phase="laeuft"] (Plan Aufgabe 9). leiste.js/lobby.js
   schalten .leiste und #spiel im selben Moment von [hidden] auf sichtbar —
   das ist der einzige Moment, in dem beide ueberhaupt neu in den Renderbaum
   kommen, also der natuerliche, einmalige Ausloeser. --rolle-schimmer
   (grund.css) traegt schon die Rollenfarbe je nach data-rolle — genau dafuer
   gebaut. #spiel bekommt nur die Farbwaesche (kein eigener Versatz, sonst
   verdoppelt sich die Distanz fuer .leiste als Kind von #spiel);
   .leiste bekommt zusaetzlich das Einfahren. .rollenband braucht keinen
   eigenen Eintrag: es liegt als Kind in #spiel und blendet mit dessen
   Deckkraft von selbst mit ein — pro Anruf neu gezeichnet, aber die
   Schichtstart-Animation auf #spiel laeuft ohnehin nur dieses eine Mal. */
@keyframes bw-schichtstart{
  from{transform:translateY(-10px);opacity:0;background-color:var(--bw-wash,transparent);}
  to{transform:translateY(0);opacity:1;background-color:transparent;}
}
body[data-phase="laeuft"] #spiel{
  --bw-wash:var(--rolle-schimmer);
  animation:bw-schichtstart var(--t-szene) var(--ease-rein);
}
body[data-phase="laeuft"] .leiste{
  animation:bw-schichtstart var(--t-szene) var(--ease-rein);
}

/* --- Warteschlange: Eintritt, Austritt, Alterung ------------------------ */

/* "Hoehe waechst" aus Spec §2.5 wird bewusst NICHT ueber height animiert
   (Layout-Eigenschaft, Randbedingung verbietet das auf Schulrechnern) —
   scaleY() taeuscht das Wachsen rein optisch vor, ohne Reflow auszuloesen.
   .7 statt 0 als Startwert, damit der Text im Zeilentext waehrend der
   kurzen Skalierung nicht sichtbar gestaucht wirkt. */
@keyframes bw-eintritt{
  from{transform:scaleY(.7);opacity:0;}
  to{transform:scaleY(1);opacity:1;}
}
/* Reiner Ortswechsel nach rechts — kein zusaetzliches Anheben, das waere
   fuer eine Zeile, die ohnehin gleich verschwindet, zu viel Geste. */
@keyframes bw-austritt{
  to{transform:translateX(32px);opacity:0;}
}
/* Der Alterungs-Trick aus Plan Aufgabe 9, Schritt 1: eine lange lineare
   Animation mit negativem animation-delay aus data-wartet-s, damit sie
   nach einem DOM-Neuaufbau oder Reconnect an der richtigen Stelle
   weiterlaeuft statt neu zu beginnen. "1 both" haelt die Endfarbe fuer
   Anrufe, die laenger als geduld_s warten, dauerhaft fest.

   Die Endfarbe ist bewusst auf rueckmeldung.css abgestimmt: .rueck-alterung
   dort faerbt ueber --wartet-anteil (0..1) stufenlos bis 55% --schlecht.
   Diese Animation gewinnt waehrend des Laufens ueber jede normale
   Deklaration (auch hoehere Spezifitaet schlaegt das nicht) — sie ist der
   "kriechende" Aufsatz auf die JS-getaktete Basis, kein Ersatz dafuer, und
   soll an ihrem Zielpunkt (--wartet-s == --geduld-s) exakt dieselbe
   Intensitaet erreichen, sonst gibt es beim Wechsel in reduzierte Bewegung
   (wo diese Animation weicht und .rueck-alterung wieder durchscheint) einen
   sichtbaren Farbsprung. */
@keyframes bw-altern{
  from{background-color:var(--surface);border-color:var(--line);}
  to{background-color:color-mix(in srgb,var(--schlecht) 55%,var(--surface));
     border-color:color-mix(in srgb,var(--schlecht) 42%,transparent);}
}

.anrufzeile--neu{transform-origin:top;}

/* Basisfall: nur Alterung. Gilt praktisch fuer jede Zeile (siehe oben). */
.anrufzeile[data-wartet-s]{
  animation-name:bw-altern;
  animation-duration:calc(var(--geduld-s,180) * 1s);
  animation-timing-function:linear;
  animation-delay:calc(var(--wartet-s,0) * -1s);
  animation-fill-mode:both;
}
/* Defensiv fuer den unwahrscheinlichen Fall, dass --neu einmal ohne
   data-wartet-s vorkommt — dann greift wenigstens der Eintritt. */
.anrufzeile--neu{animation:bw-eintritt .32s var(--ease-rein);}
.anrufzeile--geht{animation:bw-austritt .4s var(--ease-aus);}

/* Der Normalfall: --neu bzw. --geht UND data-wartet-s gemeinsam (siehe
   Kopfkommentar). Drei Klassen/Attribute zusammen schlagen die Alterung
   allein an Spezifitaet, darum gewinnt diese Regel vollstaendig — aber nur,
   weil sie BEIDE Animationen per Langform explizit mitfuehrt. Der warme
   Puls aus Spec §2.5 ("Neuer Anruf") laeuft hier als bw-treffer mit auf
   --accent umgefaerbtem Leuchten mit, siehe unten. */
.anrufzeile.anrufzeile--neu[data-wartet-s]{
  --bw-glow:var(--accent);
  animation-name:bw-altern,bw-eintritt,bw-treffer;
  animation-duration:calc(var(--geduld-s,180) * 1s),.32s,.32s;
  animation-timing-function:linear,var(--ease-rein),var(--ease-ui);
  animation-delay:calc(var(--wartet-s,0) * -1s),0s,0s;
  animation-fill-mode:both,both,both;
}
.anrufzeile.anrufzeile--geht[data-wartet-s]{
  animation-name:bw-altern,bw-austritt;
  animation-duration:calc(var(--geduld-s,180) * 1s),.4s;
  animation-timing-function:linear,var(--ease-aus);
  animation-delay:calc(var(--wartet-s,0) * -1s),0s;
  animation-fill-mode:both,both;
}

/* Nachtraeglich hinzugekommener Haken (leiste.js/rueckmeldung.css, waehrend
   dieser Datei schon in Arbeit war — geteilter Ordner, siehe Kommentare
   dort): "Das einmalige Aufblitzen beim Hochzaehlen ... fuer bewegung.css".
   --schlecht statt --ok/--accent: ein aufgelegter Anruf ist kein Erfolg. */
.rueck-verloren--neu{--bw-glow:var(--schlecht);animation:bw-treffer .5s var(--ease-ui);}

/* --- Bewertung: Treffer und Fehler --------------------------------------
   Bewusste Asymmetrie: ein Treffer bekommt einen kurzen Zusatzglanz
   (bw-treffer obendrauf), ein Fehler bekommt nur das nuechterne Einfahren.
   Passt zum Ton — Fehler werden knapp vermerkt, nicht bestraft; Erfolg wird
   knapp anerkannt, nicht gefeiert. Kein Rot-Blitz auf der Flaeche (Spec
   §2.5), kein Konfetti. */
.bewertung--gut,.bewertung--schlecht{transform-origin:top;}
.bewertung--gut{animation:bw-eintritt .5s var(--ease-rein),bw-treffer .5s var(--ease-ui);}
.bewertung--schlecht{animation:bw-eintritt .24s var(--ease-rein);}

/* Glueh-Ring, der zu vollstaendiger Transparenz ausklingt — dadurch ist er
   gefahrlos auf jedem Untergrund wiederverwendbar (Anrufzeile UND
   Bewertungskasten haben unterschiedliche Ruhefarben; ein Farbverlauf, der
   an einer HARTEN Zielfarbe endet, wuerde beim Abschluss der Animation auf
   die jeweilige Ruhefarbe zurueckspringen — endet er stattdessen bei
   Deckkraft 0, ist der Uebergang so oder so unsichtbar). */
@keyframes bw-treffer{
  from{box-shadow:0 0 0 0 color-mix(in srgb,var(--bw-glow,var(--ok)) 60%,transparent);}
  to{box-shadow:0 0 0 9px color-mix(in srgb,var(--bw-glow,var(--ok)) 0%,transparent);}
}

/* "Kurzes, trockenes Zittern (±3px, 2 Ausschlaege)" — zwei Ausschlaege
   heisst zwei Umkehrpunkte, nicht mehr. Bleibt absichtlich unter der
   4px-Schwelle des reduzierte-Bewegung-Blocks, siehe dort. */
@keyframes bw-zittern{
  0%,100%{transform:translateX(0);}
  25%{transform:translateX(-3px);}
  75%{transform:translateX(3px);}
}
.massnahme--falsch{animation:bw-zittern .24s var(--ease-ui);}

/* --- Puls: Uhr knapp, Fang-hier-an-Spot ----------------------------------
   Reine Deckkraft statt scale(): .uhr ist ein <b>, also ein Inline-Element
   ohne garantierte transform-Unterstuetzung — opacity funktioniert
   unabhaengig vom display-Typ. Beide Zustaende haben schon eine
   bewegungsfreie Kennzeichnung (uhr--knapp: Farbe in buehne.css;
   spot--start: Randfarbe direkt unten), der Puls ist nur die Verstaerkung. */
@keyframes bw-puls{
  0%,100%{opacity:1;}
  50%{opacity:.6;}
}
.uhr--knapp{animation:bw-puls 1s var(--ease-ui) infinite;}
.spot--start{
  border-color:var(--rolle-kante);
  animation:bw-puls 2.4s var(--ease-ui) infinite;
}

/* --- Chatzeile und Beobachtung: Einschreiben ----------------------------- */
@keyframes bw-einschreiben{
  from{opacity:0;transform:translateY(6px);}
  to{opacity:1;transform:translateY(0);}
}
.chatzeile--neu,.beobachtung--neu{animation:bw-einschreiben .2s var(--ease-rein);}

/* --- Reduzierte Bewegung -------------------------------------------------
   Pflicht, nicht Kuer (Randbedingung). Schulrechner, und ein Teil der
   Spieler reagiert empfindlich auf Bewegung. Regel: alles, was sich mehr
   als 4px bewegt oder skaliert, wird auf eine reine Deckkraftaenderung oder
   auf nichts zurueckgefuehrt — Information darf nie ausschliesslich ueber
   Bewegung transportiert werden. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
  }
  /* Das Zittern bleibt: ±3px unterschreitet die 4px-Schwelle aus Spec §2.5
     bewusst (siehe oben) und darf deshalb auch hier weiterlaufen — sonst
     verschwindet die einzige Fehlerrueckmeldung auf der Massnahme komplett,
     obwohl die Regel sie ausdruecklich zulaesst. */
  .massnahme--falsch{animation-duration:.24s !important;}
  /* Die Alterung traegt Information (wie dringend ein Anruf ist) und darf
     nicht verschwinden — sie wird zur STATISCHEN Farbstufe statt zur
     kriechenden Animation. leiste.js setzt --alt-1/2/3 ohnehin schon
     (Aufgabe 3), genau fuer diesen Pfad. --alt-1 bleibt unmarkiert: das ist
     der unauffaellige Ausgangszustand, dort scheint .rueck-alterung
     (rueckmeldung.css, bis zu 27.5% bei anteil<.5) durch. Die Stufen hier
     schliessen daran an, statt darunter zu bleiben — sonst wuerde die Farbe
     ausgerechnet beim Ueberschreiten der 50%-Schwelle sichtbar SCHWAECHER. */
  .anrufzeile[data-wartet-s]{animation:none !important;}
  .anrufzeile--alt-2{
    background:color-mix(in srgb,var(--schlecht) 30%,var(--surface));}
  .anrufzeile--alt-3{
    background:color-mix(in srgb,var(--schlecht) 45%,var(--surface));
    border-color:color-mix(in srgb,var(--schlecht) 38%,transparent);}
}
