/* ══════════════════════════════════════════════════════════════════
   NEXETH — Animations-Presets (22.09.2026)
   ──────────────────────────────────────────────────────────────────
   Eine gemeinsame Sammlung dezenter Einblend-Animationen für die ganze
   Seite, angelehnt an die Bewegungen auf ln-design.net: Text schiebt
   sich hinter einer Kante hervor, Bilder ziehen auf, Überschriften
   laufen wortweise ein.

   Bedienung über Attribute, kein JavaScript-Aufruf nötig:

       <h2 data-nx-anim="maske">…</h2>
       <p  data-nx-anim="hoch" data-nx-delay="120">…</p>
       <img data-nx-anim="bild">
       <div data-nx-anim="hoch" data-nx-staffel>…Kinder laufen nacheinander…</div>

   Presets:
       hoch        von unten einblenden (Standard)
       ein         nur einblenden, ohne Versatz
       links       von links einblenden
       rechts      von rechts einblenden
       maske       Text schiebt sich hinter einer Kante hervor
       woerter     Überschrift läuft Wort für Wort ein
       bild        Bild zieht auf und ruht sich aus einem leichten Zoom ein
       skalieren   wächst aus 96 % heran
       unschaerfe  schärft sich ein
       linie       Linie oder Balken wächst von links

   WICHTIG — warum die Startwerte in einer Media Query stecken:
   Wird ein Element auf opacity:0 gesetzt und die Animation läuft dann
   nicht, bleibt es für immer unsichtbar. Genau davor warnt schon der
   Kommentar in js/index-app.js. Deshalb wird hier **gar nichts**
   versteckt, wenn Bewegung unerwünscht ist oder der Effekt-Schalter auf
   „aus" steht. Ohne Bewegung ist die Seite einfach sofort vollständig da.

   Das vorhandene Reveal auf der Startseite ([data-rv], .gi, .skill-item,
   GSAP) bleibt unangetastet — js/nx-reveal.js fasst diese Elemente nicht
   an, damit nichts zweimal animiert wird.

   ENTFERNEN: diese Datei und js/nx-reveal.js aus den HTML-Dateien
   austragen. Die Seite ist dann sofort sichtbar, nichts geht verloren.
══════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: no-preference) {
  html:not([data-fx="off"]) {

    /* ── Grundzustand ────────────────────────────────────────────── */
    [data-nx-anim] {
      opacity: 0;
      transition:
        opacity   var(--nxa-dauer, .9s) var(--nxa-kurve, cubic-bezier(.22, 1, .36, 1)) var(--nxa-verzug, 0ms),
        transform var(--nxa-dauer, .9s) var(--nxa-kurve, cubic-bezier(.22, 1, .36, 1)) var(--nxa-verzug, 0ms),
        filter    var(--nxa-dauer, .9s) var(--nxa-kurve, cubic-bezier(.22, 1, .36, 1)) var(--nxa-verzug, 0ms),
        clip-path var(--nxa-dauer, .9s) var(--nxa-kurve, cubic-bezier(.22, 1, .36, 1)) var(--nxa-verzug, 0ms);
      will-change: opacity, transform;
    }

    /* Nach dem Einlaufen will-change wieder abräumen — sonst behält der
       Browser für jedes Element dauerhaft eine eigene Ebene im Speicher. */
    [data-nx-anim].nxa-fertig { will-change: auto; }

    /* ── Presets: Startzustand ───────────────────────────────────── */
    /* Weg und Dauer bewusst etwas groesser als beim ersten Wurf (26px/0.8s):
       auf den grossen Bildseiten ging die Bewegung sonst neben Vollbildern
       und Parallax schlicht unter. */
    [data-nx-anim="hoch"],
    [data-nx-anim=""]            { transform: translateY(40px); }
    [data-nx-anim="ein"]         { transform: none; }
    [data-nx-anim="links"]       { transform: translateX(-46px); }
    [data-nx-anim="rechts"]      { transform: translateX(46px); }
    [data-nx-anim="skalieren"]   { transform: scale(.96); }
    [data-nx-anim="unschaerfe"]  { filter: blur(9px); transform: translateY(12px); }

    /* Maske: der Text sitzt tiefer und wird von einer Kante beschnitten,
       sodass er dahinter hervorzukommen scheint. */
    [data-nx-anim="maske"] {
      clip-path: inset(0 0 100% 0);
      transform: translateY(18px);
    }

    /* Bild: zieht von unten auf und ruht sich aus einem leichten Zoom ein.
       Der Zoom sitzt auf dem Bild selbst, der Aufzug auf dem Rahmen — so
       verzerrt nichts. */
    [data-nx-anim="bild"] {
      clip-path: inset(0 0 100% 0);
      --nxa-dauer: 1.05s;
    }
    [data-nx-anim="bild"] > img,
    img[data-nx-anim="bild"] {
      transform: scale(1.06);
      transition: transform 1.4s var(--nxa-kurve, cubic-bezier(.22, 1, .36, 1)) var(--nxa-verzug, 0ms);
    }

    /* Linie: wächst von links. transform statt width, damit kein Layout
       neu berechnet wird. */
    [data-nx-anim="linie"] {
      transform: scaleX(0);
      transform-origin: left center;
      --nxa-dauer: .7s;
    }

    /* Wörter: js/nx-reveal.js zerlegt die Überschrift in <span>. Das
       Elternteil bleibt sichtbar, nur die Wörter laufen ein. */
    [data-nx-anim="woerter"] { opacity: 1; }
    [data-nx-anim="woerter"] .nxa-wort {
      display: inline-block;
      opacity: 0;
      transform: translateY(.5em);
      transition:
        opacity   .62s cubic-bezier(.22, 1, .36, 1) var(--nxa-wortverzug, 0ms),
        transform .62s cubic-bezier(.22, 1, .36, 1) var(--nxa-wortverzug, 0ms);
    }

    /* ── Zielzustand ─────────────────────────────────────────────── */
    [data-nx-anim].nxa-an {
      opacity: 1;
      transform: none;
      filter: none;
      clip-path: inset(0 0 0 0);
    }
    [data-nx-anim="bild"].nxa-an > img,
    img[data-nx-anim="bild"].nxa-an { transform: scale(1); }
    [data-nx-anim="linie"].nxa-an  { transform: scaleX(1); }
    [data-nx-anim="woerter"].nxa-an .nxa-wort { opacity: 1; transform: none; }
  }
}

/* Ohne Bewegung: Wörter, die das Skript schon zerlegt hat, müssen sichtbar
   bleiben. Diese Regel steht bewusst ausserhalb der Media Query. */
.nxa-wort { display: inline-block; }

/* ── Umschalter für die Tiefe (nur bei ?anim= sichtbar) ─────────────
   Eigene Regeln, weil css/nx-heading-decor.css nur auf drei Seiten
   geladen wird — sonst stünde die Leiste auf allen anderen nackt da. */
.nxa-schalter {
  position: fixed; z-index: 9800; left: 50%; bottom: 18px;
  transform: translateX(-50%);
  display: flex; align-items: center; gap: 6px;
  background: #1a1a1a; border: 1px solid rgba(255, 255, 255, .16);
  border-radius: 3px; padding: 7px 9px;
  font: 500 .72rem/1 system-ui, sans-serif; color: #e8e8e8;
}
.nxa-schalter > span {
  color: #808080; letter-spacing: .2em; text-transform: uppercase;
  font-size: .6rem; margin-right: 4px;
}
.nxa-schalter button {
  background: none; border: 1px solid rgba(255, 255, 255, .2); color: #e8e8e8;
  min-height: 30px; padding: 0 12px; border-radius: 2px; cursor: pointer; font: inherit;
}
.nxa-schalter button:hover { border-color: #ff6b00; color: #ff6b00; }
.nxa-schalter button[aria-pressed="true"] { background: #ff6b00; border-color: #ff6b00; color: #141414; }
