/**
 * AOB Motion Kit — Startzustände
 * ------------------------------------------------------------------------------
 * AdrianOnBoard · MIT
 *
 * WARUM DIESE DATEI ÜBERHAUPT EXISTIERT:
 * Ein Element, das "von unten einfliegen" soll, muss VOR der Animation schon
 * unsichtbar und verschoben sein. Würden wir das erst im JavaScript setzen,
 * sähe der Besucher das Element kurz an der Endposition — und dann würde es
 * wegspringen. Dieses Flackern heisst FOUC (Flash of Unstyled Content).
 *
 * WARUM ALLES UNTER html.aob-ready HÄNGT:
 * Wenn JavaScript nicht lädt (Fehler, Blocker, altes Gerät), darf die Seite
 * NICHT leer bleiben. Die Klasse `aob-ready` wird von einem winzigen Inline-
 * Script im <head> gesetzt (siehe aob-motion-init.php).
 * Kein JS → keine Klasse → dieses CSS greift nicht → alles normal sichtbar.
 * Das ist dasselbe Muster wie die klassische `no-js`-Klasse von Modernizr.
 *
 * WARUM ÜBERALL :not(.aob-stagger):
 * Trägt ein Element `aob-stagger`, beschreibt seine Effekt-Klasse die KINDER,
 * nicht das Element selbst. Das JavaScript animiert dann auch nur die Kinder.
 * Ohne diesen Ausschluss bekäme der Container einen Startzustand, den niemand
 * je wieder auflöst — er bliebe dauerhaft auf opacity 0, und der ganze
 * Abschnitt wäre unsichtbar. Genau dieser Fehler ist am 14.08.2026 live
 * aufgetreten.
 */

/* --- Startzustand: unsichtbar --------------------------------------------- */
html.aob-ready .aob-fade:not(.aob-stagger),
html.aob-ready .aob-fade-up:not(.aob-stagger),
html.aob-ready .aob-fade-down:not(.aob-stagger),
html.aob-ready .aob-fade-left:not(.aob-stagger),
html.aob-ready .aob-fade-right:not(.aob-stagger),
html.aob-ready .aob-zoom-in:not(.aob-stagger),
html.aob-ready .aob-zoom-out:not(.aob-stagger),
html.aob-ready .aob-stagger > * {
  opacity: 0;
}

/* --- Startzustand: Position/Skalierung ------------------------------------
   Muss exakt zu den Keyframes in aob-motion.js passen. Wenn du dort einen Wert
   änderst, hier mitziehen — sonst springt das Element im ersten Frame. */
html.aob-ready .aob-fade-up:not(.aob-stagger),
html.aob-ready .aob-stagger > *              { transform: translateY(24px); }
html.aob-ready .aob-fade-down:not(.aob-stagger)  { transform: translateY(-24px); }
html.aob-ready .aob-fade-left:not(.aob-stagger)  { transform: translateX(-32px); }
html.aob-ready .aob-fade-right:not(.aob-stagger) { transform: translateX(32px); }
html.aob-ready .aob-zoom-in:not(.aob-stagger)    { transform: scale(0.94); }
html.aob-ready .aob-zoom-out:not(.aob-stagger)   { transform: scale(1.06); }

/* --- LCP-sichere Varianten: NUR verschoben, NICHT unsichtbar ---------------
   Diese Klassen stehen bewusst NICHT im opacity-0-Block weiter oben.

   Grund: Ein Element mit opacity 0 gilt für den Browser als nicht gemalt und
   kann kein LCP-Element sein (Largest Contentful Paint). Fadet man die
   Hero-Überschrift ein, misst Google die Ladezeit erst nach der Animation.
   Mit reinem transform ist das Element sofort sichtbar, zählt für LCP und
   bewegt sich nur noch an seinen Platz. Layout-Shift entsteht nicht, weil
   transform den Platzbedarf nicht verändert.

   Faustregel: oberhalb der Falz `slide`, darunter `fade`. */
html.aob-ready .aob-slide-up:not(.aob-stagger)    { transform: translateY(24px); }
html.aob-ready .aob-slide-down:not(.aob-stagger)  { transform: translateY(-24px); }
html.aob-ready .aob-slide-left:not(.aob-stagger)  { transform: translateX(-32px); }
html.aob-ready .aob-slide-right:not(.aob-stagger) { transform: translateX(32px); }

/* --- Stagger: Startzustand der Kinder folgt dem Effekt am Container --------
   Ohne diese Regeln kämen die Kinder immer von unten (der Standard), auch
   wenn am Container z. B. aob-zoom-in steht. Das Element spränge dann im
   ersten Frame von translateY(24px) auf scale(0.94) — sichtbares Ruckeln.

   Die Regeln stehen NACH dem Standard-Block, gewinnen also bei gleicher
   Spezifität. */
html.aob-ready .aob-stagger.aob-fade > *       { transform: none; }
html.aob-ready .aob-stagger.aob-fade-down > *  { transform: translateY(-24px); }
html.aob-ready .aob-stagger.aob-fade-left > *  { transform: translateX(-32px); }
html.aob-ready .aob-stagger.aob-fade-right > * { transform: translateX(32px); }
html.aob-ready .aob-stagger.aob-zoom-in > *    { transform: scale(0.94); }
html.aob-ready .aob-stagger.aob-zoom-out > *   { transform: scale(1.06); }

/* slide-Varianten am Stagger-Container: Kinder nur verschieben, nicht
   ausblenden — damit bleibt auch ein gestaffelter Hero LCP-tauglich. */
html.aob-ready .aob-stagger.aob-slide-up > *    { opacity: 1; }
html.aob-ready .aob-stagger.aob-slide-down > *  { opacity: 1; transform: translateY(-24px); }
html.aob-ready .aob-stagger.aob-slide-left > *  { opacity: 1; transform: translateX(-32px); }
html.aob-ready .aob-stagger.aob-slide-right > * { opacity: 1; transform: translateX(32px); }

/* --- Layout-Schutz --------------------------------------------------------
   `transform` und `opacity` verändern den Platzbedarf eines Elements nicht.
   Das ist kein Zufall, sondern der Grund, warum wir ausschliesslich diese
   beiden Eigenschaften animieren: Der Platz ist von Anfang an reserviert,
   es gibt keinen Layout-Shift (CLS = 0). */

/* --- Accessibility --------------------------------------------------------
   Doppelte Absicherung: das JS bricht bei reduzierter Bewegung ab, aber falls
   es gar nicht erst lädt, sorgt diese Regel dafür, dass nichts versteckt
   bleibt. Betrifft Menschen mit vestibulären Störungen — für die sind
   fliegende Elemente nicht "hübsch", sondern lösen Schwindel aus. */
@media (prefers-reduced-motion: reduce) {
  html.aob-ready [class*="aob-fade"],
  html.aob-ready [class*="aob-zoom"],
  html.aob-ready [class*="aob-slide"],
  html.aob-ready .aob-stagger > * {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* --- Notbremse ------------------------------------------------------------
   Falls ein Element hängen bleibt (z. B. weil ein Slider es aus dem DOM
   nimmt): .aob-off auf dem Element schaltet das Kit dort ab, ohne dass du die
   Effekt-Klasse suchen musst. */
html.aob-ready .aob-off,
html.aob-ready .aob-off > * {
  opacity: 1 !important;
  transform: none !important;
}
