/* ==========================================================================
   A2 Lumina — Bewegung

   Die Tokens dafür gibt es seit jeher: fünf Dauern, drei Beschleunigungen.
   Was fehlte, war die Schicht darüber — und deshalb hat jedes Projekt seine
   Übergänge selbst erfunden, meist mit geratenen Zahlen wie `.15s ease`.

   DREI REGELN, und sie sind nicht verhandelbar:

   1. **Bewegung erklärt, sie schmückt nicht.** Etwas bewegt sich, wenn der
      Weg eine Auskunft trägt: woher es kommt, wohin es geht, dass es
      dazugehört. Ein Element, das ohne Grund hereinfliegt, kostet
      Aufmerksamkeit und gibt nichts zurück.

   2. **Kurz.** Ankommen 260 ms, Wechseln 180 ms, Gehen 160 ms. Alles darüber
      fühlt sich zäh an, sobald man es zum zehnten Mal sieht — und eine
      Oberfläche sieht man tausendmal.

   3. **Abschaltbar, und zwar wirklich.** `prefers-reduced-motion` ist keine
      Vorliebe, sondern für manche Menschen die Bedingung, den Bildschirm
      ansehen zu können. Am Ende dieser Datei wird jede Bewegung auf einen
      Zustandswechsel ohne Weg zusammengestrichen — nicht auf `none`, denn ein
      Element, das dann gar nicht mehr erscheint, ist schlimmer als eines, das
      springt.

   Alles hier läuft über CSS. `motion/motion.js` liegt daneben für die Fälle,
   die CSS nicht kann — Federn, Gesten, unterbrechbare Abläufe —, und wird von
   keinem Bauteil dieser Bibliothek vorausgesetzt.
   ========================================================================== */

/* ── Ankommen ─────────────────────────────────────────────────────────────
   Was neu da ist, kommt von leicht unten und blendet auf. Der Weg ist kurz
   (8 px): Er soll sagen „das ist neu", nicht „sieh her". */

@keyframes a2-enter {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
@keyframes a2-enter-scale {
  from { opacity: 0; transform: scale(0.97); }
  to   { opacity: 1; transform: none; }
}
@keyframes a2-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.a2-motion-enter {
  animation: a2-enter var(--a2-duration-enter) var(--a2-ease-enter) both;
}
.a2-motion-enter-scale {
  animation: a2-enter-scale var(--a2-duration-enter) var(--a2-ease-enter) both;
}
.a2-motion-fade {
  animation: a2-fade var(--a2-duration-slow) var(--a2-ease-out) both;
}

/* Nacheinander statt gleichzeitig. Eine Liste, deren Zeilen im Abstand von
   40 ms erscheinen, liest sich als Reihenfolge; alle zugleich sind ein Blitz.
   Mehr als acht Stufen gibt es nicht: Danach wartet man auf die letzte Zeile,
   und Warten ist das Gegenteil von dem, was hier erreicht werden soll. */
.a2-motion-stagger > * { animation: a2-enter var(--a2-duration-enter) var(--a2-ease-enter) both; }
.a2-motion-stagger > *:nth-child(1) { animation-delay: 0ms; }
.a2-motion-stagger > *:nth-child(2) { animation-delay: 40ms; }
.a2-motion-stagger > *:nth-child(3) { animation-delay: 80ms; }
.a2-motion-stagger > *:nth-child(4) { animation-delay: 120ms; }
.a2-motion-stagger > *:nth-child(5) { animation-delay: 160ms; }
.a2-motion-stagger > *:nth-child(6) { animation-delay: 200ms; }
.a2-motion-stagger > *:nth-child(7) { animation-delay: 240ms; }
.a2-motion-stagger > *:nth-child(n+8) { animation-delay: 280ms; }

/* ── Laufender Zustand ────────────────────────────────────────────────────
   Für Vorgänge ohne bekanntes Ende. Ein Fortschrittsbalken, der eine Länge
   behauptet, die niemand kennt, lügt; ein Puls sagt nur „läuft noch". */

@keyframes a2-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.45; }
}
.a2-motion-pulse { animation: a2-pulse 1.6s var(--a2-ease) infinite; }

@keyframes a2-spin { to { transform: rotate(360deg); } }
.a2-motion-spin { animation: a2-spin 900ms linear infinite; }

/* Der Schimmer über einem Platzhalter. Bewusst leise: Er markiert eine
   Fläche, die gleich Inhalt bekommt, und nicht die Fläche selbst. */
@keyframes a2-shimmer { to { background-position-x: -200%; } }
.a2-motion-skeleton {
  background: linear-gradient(90deg,
    var(--a2-bg-subtle) 0%, var(--a2-state-hover) 50%, var(--a2-bg-subtle) 100%);
  background-size: 200% 100%;
  animation: a2-shimmer 1.4s linear infinite;
  border-radius: var(--a2-radius-sm);
}

/* ── Aufmerksamkeit ───────────────────────────────────────────────────────
   Genau ein Fall: Eine Eingabe wurde abgelehnt. Kurz, waagerecht, klein —
   ein Kopfschütteln, kein Erdbeben. */

@keyframes a2-nudge {
  0%, 100% { transform: translateX(0); }
  20%      { transform: translateX(-4px); }
  40%      { transform: translateX(4px); }
  60%      { transform: translateX(-2px); }
  80%      { transform: translateX(2px); }
}
.a2-motion-nudge { animation: a2-nudge 320ms var(--a2-ease); }

/* ── Höhe auffahren ───────────────────────────────────────────────────────
   `height: auto` lässt sich nicht animieren. `grid-template-rows` von 0fr auf
   1fr schon — der einzige Weg, eine unbekannte Höhe weich zu öffnen, der ohne
   Messung in JavaScript auskommt. Dafür braucht es genau EINE Zeile, also
   einen Deckel um den Inhalt herum. */
.a2-motion-collapse {
  display: grid; grid-template-rows: 1fr;
  transition: grid-template-rows var(--a2-duration-base) var(--a2-ease),
              opacity var(--a2-duration-base) var(--a2-ease);
}
.a2-motion-collapse > * { overflow: hidden; min-height: 0; }
.a2-motion-collapse[data-open="false"] { grid-template-rows: 0fr; opacity: 0; }

/* ── Ansichtswechsel ──────────────────────────────────────────────────────
   Für Browser, die `view-transition` können. Wo nicht, passiert schlicht
   nichts — deshalb steht hier kein Ersatz, sondern eine Verbesserung. */
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) { animation: a2-fade var(--a2-duration-exit) var(--a2-ease) reverse; }
  ::view-transition-new(root) { animation: a2-fade var(--a2-duration-enter) var(--a2-ease-enter); }
}

/* ── Abschalten ───────────────────────────────────────────────────────────
   Nicht `animation: none`: Ein Element, dessen Einblendung auf `none` steht,
   bleibt bei `opacity: 0` stehen und ist damit weg. Stattdessen eine Dauer,
   die unter der Wahrnehmungsschwelle liegt — der Endzustand tritt ein, der
   Weg dorthin entfällt. */
@media (prefers-reduced-motion: reduce) {
  .a2-motion-enter, .a2-motion-enter-scale, .a2-motion-fade,
  .a2-motion-stagger > *, .a2-motion-nudge {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
  }
  .a2-motion-pulse, .a2-motion-spin, .a2-motion-skeleton {
    animation: none !important;
  }
  .a2-motion-collapse { transition-duration: 1ms !important; }
}
