/* ==========================================================================
   ARI/WE/SO — animations.css
   Reveal-Zustände, Keyframes, Bewegungs-Sicherheitsnetze

   GRUNDREGEL
   Inhalte werden ausschließlich dann vorab versteckt, wenn *alle* drei
   Bedingungen erfüllt sind:
     1. JavaScript läuft            -> html.js          (Inline-Snippet im <head>)
     2. Die Animationen sind scharf -> html.anim-armed  (animations.js, nur mit GSAP)
     3. Der Nutzer wünscht Bewegung -> prefers-reduced-motion: no-preference

   Fällt eine davon weg, ist der Inhalt sichtbar. Ein leerer Bildschirm wegen
   fehlender Bibliothek ist damit strukturell ausgeschlossen.
   ========================================================================== */

@media (prefers-reduced-motion: no-preference) {

    html.js.anim-armed [data-anim] {
        opacity: 0;
        will-change: opacity, transform;
    }

    html.js.anim-armed [data-anim="fade-up"],
    html.js.anim-armed [data-anim=""],
    html.js.anim-armed [data-anim="stagger"] > * { transform: translate3d(0, 28px, 0); }

    html.js.anim-armed [data-anim="fade-down"]  { transform: translate3d(0, -24px, 0); }
    html.js.anim-armed [data-anim="fade-left"]  { transform: translate3d(-40px, 0, 0); }
    html.js.anim-armed [data-anim="fade-right"] { transform: translate3d(40px, 0, 0); }
    html.js.anim-armed [data-anim="scale"]      { transform: scale(0.94); }
    html.js.anim-armed [data-anim="fade"]       { transform: none; }

    /* Kinder einer Stagger-Gruppe werden einzeln versteckt, der Container nicht */
    html.js.anim-armed [data-anim="stagger"] { opacity: 1; }
    html.js.anim-armed [data-anim="stagger"] > * { opacity: 0; will-change: opacity, transform; }

    /* Wort-für-Wort-Enthüllung der Hero-Überschrift */
    html.js.anim-armed [data-anim-words] .word-mask { overflow: hidden; display: inline-block; vertical-align: bottom; }
    html.js.anim-armed [data-anim-words] .word { display: inline-block; transform: translate3d(0, 105%, 0); }
}

/* Nach Abschluss der Animation entfernt animations.js will-change wieder —
   ein dauerhaft gesetztes will-change kostet unnötig Compositor-Speicher. */
.anim-done { will-change: auto !important; }

/* --- Dekorative Dauer-Animationen ---------------------------------------- */

@keyframes float-slow {
    0%, 100% { transform: translate3d(0, 0, 0); }
    50%      { transform: translate3d(0, -14px, 0); }
}

@keyframes drift {
    0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
    50%      { transform: translate3d(18px, -22px, 0) scale(1.06); }
}

@keyframes dash-flow {
    to { stroke-dashoffset: -160; }
}

@keyframes sheen {
    0%   { transform: translateX(-120%); }
    60%, 100% { transform: translateX(220%); }
}

@media (prefers-reduced-motion: no-preference) {
    .hero-glow--green  { animation: drift 17s ease-in-out infinite; }
    .hero-glow--purple { animation: drift 21s ease-in-out infinite reverse; }
    .float-slow        { animation: float-slow 6s ease-in-out infinite; }
    .dash-flow         { animation: dash-flow 3.5s linear infinite; }
}

/* --- Globales Sicherheitsnetz für Bewegungsempfindlichkeit --------------- */

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }

    html { scroll-behavior: auto; }

    /* Alles sichtbar, nichts verschoben */
    [data-anim],
    [data-anim="stagger"] > *,
    [data-anim-words] .word {
        opacity: 1 !important;
        transform: none !important;
    }
}

/* --- Mobil: Bewegung reduzieren ------------------------------------------ */

@media (max-width: 767px) {
    /* Parallax und weite Wege wirken auf kleinen Displays unruhig
       und kosten auf schwächeren Geräten unnötig Rechenzeit. */
    [data-anim-parallax] { transform: none !important; }

    .hero-glow--green,
    .hero-glow--purple { animation: none; }
}
