/*
 * Genossame Wangen: Bewegung.
 *
 * Ruhig und zurückhaltend: ein orchestrierter Auftritt je Seite, Karten und
 * Titel tauchen beim Scrollen gestaffelt auf, Seitenwechsel blenden über.
 * Ohne Bibliothek — CSS-Keyframes, scroll-getriebene Animationen, View
 * Transitions zwischen Dokumenten und für Kleinigkeiten bewegung.js.
 *
 * Grundsätze
 *   - Bewegt werden nur transform-Eigenschaften (translate, scale, rotate),
 *     opacity und clip-path. Kein Mass, keine Position im Fluss ändert sich.
 *   - Der Endzustand jeder Animation ist der statische Zustand aus den übrigen
 *     Stylesheets: Animationen füllen nur rückwärts (backwards), nie vorwärts.
 *   - Startzustände stehen hier im CSS. bewegung.js versteckt nur Elemente, die
 *     beim Laden unterhalb des Sichtfelds liegen — ohne JavaScript ist alles da.
 *   - Das Hero-Bild bzw. -Video (LCP) ist ab dem ersten Bild sichtbar; es
 *     «setzt sich» nur über scale.
 *   - Was den Tastaturfokus bekommt, ist sofort ganz da (bewegung.js).
 *   - «Bewegung reduzieren»: keine Bewegung, keine Parallaxe, keine Drehung,
 *     keine Seitenübergänge, nichts versteckt. Zustände wechseln sofort (kit-base
 *     setzt alle Dauern auf 0.01 ms); nur der Dialog-Hintergrund blendet 120 ms,
 *     und das Menü-Overlay blendet kurz über (bewegung.js).
 *     Alle Positionen sofort im Endzustand.
 *
 * Lädt nach projekt.css und allen Block-Stylesheets (functions.php, gw_assets).
 */

:root {
  /* Auslaufend (expo out): Auftritte, Hover */
  --gw-aus: cubic-bezier(0.16, 1, 0.3, 1);
  /* Beschleunigend: Abgänge */
  --gw-ein: cubic-bezier(0.5, 0, 0.75, 0);
  /* Leichtes Überschwingen: Plakette */
  --gw-feder: cubic-bezier(0.34, 1.45, 0.64, 1);
}

/* ================================================================== Keyframes */

/* Medium setzt sich: scale von leicht vergrössert auf 1 */
@keyframes gw-setzen {
  from { scale: var(--gw-setzen-von, 1.06); }
}

/*
 * Text steigt auf: leicht angehoben, blendet ein. Ohne clip-path-Maske: die
 * deckte mehrzeilige Titel von unten nach oben auf (letzte Zeile zuerst) und
 * läuft in Firefox und WebKit auf dem Hauptthread.
 */
@keyframes gw-auftauchen {
  from {
    opacity: 0;
    translate: 0 0.5em;
  }
}

/* Block hebt sich in den Platz */
@keyframes gw-heben {
  from {
    opacity: 0;
    translate: 0 var(--gw-weg, 28px);
  }
}

/* Störer dreht sich ins Bild (rotate addiert sich zum statischen rotate(7deg)) */
@keyframes gw-stoerer-rein {
  from {
    opacity: 0;
    rotate: -67deg;
    scale: 0.85;
  }
}

@keyframes gw-drehen {
  to { rotate: 1turn; }
}

@keyframes gw-plakette-rein {
  from {
    opacity: 0;
    scale: 0.6;
  }
}

@keyframes gw-linie {
  from { scale: 0 1; }
}

@keyframes gw-parallaxe {
  to { translate: 0 12%; }
}

@keyframes gw-menue-punkt {
  from {
    opacity: 0;
    translate: 0 -0.75rem;
  }
}

@keyframes gw-unter {
  from {
    opacity: 0;
    translate: 0 -0.5rem;
  }
}

@keyframes gw-blenden {
  from { opacity: 0; }
}

@keyframes gw-vt-aus {
  to { opacity: 0; }
}

@keyframes gw-vt-rein {
  from {
    opacity: 0;
    translate: 0 12px;
  }
}

/* ================================================================== Volle Bewegung */

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

  /* ---------------------------------------------------- 1 Seitenauftritt */

  /*
   * Seitenkopf. Startseite: Video setzt sich in 1.6 s, Kicker und Titel steigen
   * gemeinsam auf, der Störer dreht sich ins Bild. Unterseiten: Foto setzt sich
   * in 1.2 s, danach von oben nach unten Plakette, Titel und Text der Einleitung.
   */
  .kit-inhalt > .gw-hero:first-child {
    --gw-setzen-von: 1.05;
    --gw-setzen-dauer: 1.2s;
  }
  .kit-inhalt > .gw-hero--gross:first-child {
    --gw-setzen-von: 1.06;
    --gw-setzen-dauer: 1.6s;
  }

  .kit-inhalt > .gw-hero:first-child :is(.gw-hero__video, .gw-hero__bild) {
    animation: gw-setzen var(--gw-setzen-dauer) var(--gw-aus) backwards;
  }

  /*
   * Kicker und Titel als ein Block: der Textblock trägt einen drop-shadow-Filter.
   * Bewegen sich Zeilen darin einzeln, muss der Filter jedes Bild neu gerechnet
   * werden; Firefox ohne GPU verlor dabei rund ein Viertel der Bilder (gemessen).
   */
  .kit-inhalt > .gw-hero:first-child .gw-hero__text {
    animation: gw-auftauchen 0.8s var(--gw-aus) 0.15s backwards;
  }

  .kit-inhalt > .gw-hero:first-child .gw-stoerer {
    animation: gw-stoerer-rein 0.9s var(--gw-aus) 0.4s backwards;
  }

  /*
   * Der Ring dreht sich nur, solange man auf den Störer zeigt oder ihn fokussiert.
   * Dauernde Bewegung ohne Pause-Möglichkeit verletzt WCAG 2.2.2.
   */
  .gw-stoerer__ring {
    animation: gw-drehen 12s linear infinite paused;
  }
  .gw-stoerer:is(:hover, :focus-visible) .gw-stoerer__ring {
    animation-play-state: running;
  }

  /* Einleitung direkt unter dem Seitenkopf einer Unterseite: von oben nach unten, 100 ms Raster */
  body:not(.home) .kit-inhalt > .gw-hero:first-child + .gw-intro .gw-intro__plakette {
    animation: gw-plakette-rein 0.6s var(--gw-feder) 0.15s backwards;
  }
  body:not(.home) .kit-inhalt > .gw-hero:first-child + .gw-intro .gw-intro__titel {
    animation: gw-auftauchen 0.75s var(--gw-aus) 0.25s backwards;
  }
  body:not(.home) .kit-inhalt > .gw-hero:first-child + .gw-intro .gw-intro__rechts {
    --gw-weg: 16px;
    animation: gw-heben 0.75s var(--gw-aus) 0.35s backwards;
  }

  /*
   * Nach einem Seitenübergang ist die Überblendung der Auftritt (das Inline-Skript
   * im Kopf setzt die Klasse beim pagereveal, bevor das erste Bild entsteht). Sonst liefen zwei
   * Auftritte übereinander, und der Inhalt stünde erst nach rund 1 s.
   */
  :root.gw-mit-uebergang .kit-inhalt > .gw-hero:first-child :is(.gw-hero__text, .gw-stoerer),
  :root.gw-mit-uebergang .kit-inhalt > .gw-hero:first-child + .gw-intro :is(.gw-intro__plakette, .gw-intro__titel, .gw-intro__rechts) {
    animation: none;
  }

  /* ---------------------------------------------------- 2 Beim Scrollen */

  /*
   * bewegung.js markiert Titel und Karten, die beim Laden unterhalb des
   * Sichtfelds liegen, mit data-gw-zeigen="wartet", schaltet sie beim
   * Hereinscrollen auf «kommt» und nach dem Auftritt (oder sobald etwas darin
   * den Fokus bekommt) auf «da». Für «da» gibt es keine Regel: so startet keine
   * Animation neu. --i ist der Index innerhalb einer Gruppe, die gemeinsam ins
   * Bild kommt (Stagger 70 ms).
   *
   * Zeitgesteuert statt scroll-gekoppelt: eine an den Scroll gekoppelte
   * Einblendung bleibt halb durchsichtig stehen, wo der Scroll stoppt — an der
   * Falzkante beim Laden und am Seitenende sichtbar. So läuft sie einmal ganz
   * durch, in allen drei Engines gleich.
   */
  @media screen {
    [data-gw-zeigen="wartet"] { opacity: 0; }

    [data-gw-zeigen="kommt"] {
      animation: gw-heben 0.8s var(--gw-aus) calc(var(--i, 0) * 70ms) backwards;
    }

    /* Sicherung, falls der Fokus vor dem Skript-Handler gezeichnet wird */
    [data-gw-zeigen="wartet"]:focus-within { opacity: 1; }

    /* Zwischentitel: die auslaufende Linie wächst von links nach */
    .gw-gruppe__titel[data-gw-zeigen="kommt"]::after {
      transform-origin: left center;
      animation: gw-linie 1.1s var(--gw-aus) calc(var(--i, 0) * 70ms + 0.2s) backwards;
    }
  }

  /*
   * Parallaxe: das Hero-Medium bleibt beim Herausscrollen leicht zurück
   * (bis 12 %). Erst ab «exit», darum öffnet sich oben nie eine Lücke im
   * Sichtfeld. Ohne Unterstützung (Firefox) steht das Bild still.
   */
  @supports (animation-timeline: view()) {
    .kit-inhalt > .gw-hero:first-child { view-timeline: --gw-hero block; }

    .kit-inhalt > .gw-hero:first-child :is(.gw-hero__video, .gw-hero__bild) {
      animation:
        gw-setzen var(--gw-setzen-dauer) var(--gw-aus) backwards,
        gw-parallaxe linear both;
      animation-timeline: auto, --gw-hero;
      animation-range: normal, exit 0% exit 100%;
    }
  }

  /* ---------------------------------------------------- 3 Seitenwechsel */

  /*
   * Die Zusage @view-transition { navigation: auto; } steht inline im Kopf
   * (functions.php, wp_add_inline_style): aus dieser Datei hat Chromium sie im
   * Test nicht verlässlich gesehen, wenn das Stylesheet als letztes ankam.
   */

  /* Kopf bleibt stehen; Hero-Medium geht in den nächsten Seitenkopf über. */
  .gw-kopf { view-transition-name: gw-kopf; }
  .kit-inhalt > .gw-hero:first-child .gw-hero__medium { view-transition-name: gw-hero; }
  .kit-inhalt > .gw-hero:first-child .gw-hero__text { view-transition-name: gw-hero-text; }
  .kit-inhalt > .gw-hero:first-child .gw-stoerer { view-transition-name: gw-stoerer; }
  .kit-inhalt > .gw-hero:first-child + .gw-intro .gw-intro__plakette { view-transition-name: gw-plakette; }

  /* Aus dem offenen Menü heraus liegt alles darunter: dann nur die Überblendung. */
  body.gw-menue-offen :is(.gw-kopf, .gw-hero__medium, .gw-hero__text, .gw-stoerer, .gw-intro__plakette) {
    view-transition-name: none;
  }

  /* Inhalt: alt blendet rasch aus, neu blendet mit leichtem Versatz ein */
  ::view-transition-old(root) { animation: gw-vt-aus 0.22s var(--gw-ein) both; }
  ::view-transition-new(root) { animation: gw-vt-rein 0.45s var(--gw-aus) 0.08s both; }

  /*
   * Kopf: steht still. Kein Grössenwechsel, keine Überblendung — der neue Kopf
   * ist sofort da (gleicher Kopf = kein sichtbarer Wechsel). Ohne Überblendung
   * braucht es auch kein plus-lighter-Mischen, das nicht jede Engine kann.
   */
  ::view-transition-group(gw-kopf) {
    animation: none;
    /* Immer zuoberst: ein nur neu benannter Seitenkopf käme sonst darüber zu liegen */
    z-index: 1;
  }
  ::view-transition-old(gw-kopf) { animation: none; opacity: 0; }
  ::view-transition-new(gw-kopf) { animation: none; }

  /*
   * Sieht der Kopf anders aus (kompakt ↔ ausgeklappt, gescrollte Leiste, aus dem
   * Menü), blendet er mit der Seite: alt geht mit dem Inhalt, neu kommt kurz
   * danach. Das Inline-Skript im Kopf (gw_assets) vergleicht beim pagereveal.
   */
  :root.gw-kopf-wechsel::view-transition-old(gw-kopf) {
    opacity: 1;
    animation: gw-vt-aus 0.22s var(--gw-ein) both;
  }
  :root.gw-kopf-wechsel::view-transition-new(gw-kopf) {
    animation: gw-blenden 0.35s var(--gw-aus) 0.12s both;
  }

  /* Seitenkopf: Rahmen gleitet in die neue Höhe, Bilder gefüllt statt verzerrt */
  ::view-transition-group(gw-hero),
  ::view-transition-group(gw-hero-text),
  ::view-transition-group(gw-stoerer),
  ::view-transition-group(gw-plakette) {
    animation-duration: 0.55s;
    animation-timing-function: var(--gw-aus);
  }
  ::view-transition-image-pair(gw-hero) { overflow: clip; }
  ::view-transition-old(gw-hero),
  ::view-transition-new(gw-hero) {
    height: 100%;
    object-fit: cover;
  }
  /* Neues Bild blendet über dem stehenden alten ein (ohne plus-lighter) */
  ::view-transition-old(gw-hero) { animation: none; }
  ::view-transition-new(gw-hero) { animation: gw-blenden 0.55s var(--gw-aus) both; }
  /* Text an der Unterkante verankert, unverzerrt */
  ::view-transition-old(gw-hero-text),
  ::view-transition-new(gw-hero-text) {
    height: 100%;
    object-fit: none;
    object-position: left bottom;
  }

  /*
   * Alter Text, Störer und eine Plakette ohne Nachfolger gehen sofort: der grösste
   * Teil der Ausblendung liegt in den ersten 60 ms, sonst schweben sie über dem
   * schrumpfenden Bild bzw. der neuen Seite.
   */
  ::view-transition-old(gw-hero-text),
  ::view-transition-old(gw-stoerer) {
    animation: gw-vt-aus 0.12s ease-out both;
  }
  /* Eigene Regel: kennt eine Engine :only-child hier nicht, fiele sonst die ganze Liste weg */
  ::view-transition-old(gw-plakette):only-child {
    animation: gw-vt-aus 0.12s ease-out both;
  }
  ::view-transition-new(gw-hero-text) { animation: gw-blenden 0.45s var(--gw-aus) 0.1s both; }

  /*
   * Während des Übergangs ohne die dunkelgrüne Fläche des Seitenkopfs: wo das
   * Bild beim Übergang kleiner wird, bliebe sonst ein grünes Band stehen.
   */
  :root:active-view-transition .kit-inhalt > .gw-hero:first-child { background: transparent; }

  /* ---------------------------------------------------- 4 Mikro-Interaktionen */

  /* Buttons: Hintergrund und Pfeil weicher */
  .gw-button {
    transition-duration: 0.3s;
    transition-timing-function: var(--gw-aus);
  }
  .gw-button .gw-icon { transition: transform 0.3s var(--gw-aus); }

  /* Textlinks: Farbe weich, Unterstreichung wächst von links (Zustand in «Immer») */
  .gw-textlink { transition: color 0.2s ease; }
  .gw-textlink::before { transition: scale 0.4s var(--gw-aus); }

  /* Gescrollte Kopfleiste: dieselbe Animation aus projekt.css, weicher */
  .gw-kopf.ist-gescrollt {
    animation-duration: 0.45s;
    animation-timing-function: var(--gw-aus);
  }

  /* ---------------------------------------------------- 5 Navigation */

  /*
   * Das Overlay gleitet von oben herein und nach oben hinaus (bewegung.js, Web
   * Animations: so gilt auch bei «Bewegung reduzieren» die kurze Überblendung).
   * Die Einträge sinken gestaffelt nach, während es ankommt.
   * :where hält die Grundregel schwach, damit die Verzögerungen darunter greifen */
  .gw-menue:not([hidden]) :where(.gw-menue__service, .gw-menue__haupt .gw-nav > li, .gw-menue__kontakt) {
    animation: gw-menue-punkt 0.5s var(--gw-aus) 0.1s backwards;
  }
  .gw-menue:not([hidden]) .gw-nav--overlay:not(.gw-nav--konto) > li:nth-child(1) { animation-delay: 0.14s; }
  .gw-menue:not([hidden]) .gw-nav--overlay:not(.gw-nav--konto) > li:nth-child(2) { animation-delay: 0.18s; }
  .gw-menue:not([hidden]) .gw-nav--overlay:not(.gw-nav--konto) > li:nth-child(3) { animation-delay: 0.22s; }
  .gw-menue:not([hidden]) .gw-nav--overlay:not(.gw-nav--konto) > li:nth-child(4) { animation-delay: 0.26s; }
  .gw-menue:not([hidden]) .gw-nav--overlay:not(.gw-nav--konto) > li:nth-child(n + 5) { animation-delay: 0.3s; }
  .gw-menue:not([hidden]) .gw-nav--konto > li { animation-delay: 0.32s; }
  .gw-menue:not([hidden]) .gw-menue__kontakt { animation-delay: 0.36s; }

  /* Untermenüs: Einträge gleiten gestaffelt herein (Höhe springt, ohne Layout-Animation) */
  .gw-nav .sub-menu.ist-offen > li { animation: gw-unter 0.22s var(--gw-aus) backwards; }
  .gw-nav .sub-menu.ist-offen > li:nth-child(2) { animation-delay: 0.02s; }
  .gw-nav .sub-menu.ist-offen > li:nth-child(3) { animation-delay: 0.04s; }
  .gw-nav .sub-menu.ist-offen > li:nth-child(4) { animation-delay: 0.06s; }
  .gw-nav .sub-menu.ist-offen > li:nth-child(5) { animation-delay: 0.08s; }
  .gw-nav .sub-menu.ist-offen > li:nth-child(n + 6) { animation-delay: 0.1s; }
  /* Beim Schliessen (hidden, nur noch inline sichtbar) nicht nochmals einlaufen */
  .gw-menue[hidden] .gw-nav .sub-menu > li { animation: none; }

  /* ---------------------------------------------------- 6 Video-Dialog */

  .gw-videodialog,
  .gw-videodialog::backdrop {
    transition: opacity 0.2s var(--gw-ein), scale 0.2s var(--gw-ein);
    transition:
      opacity 0.2s var(--gw-ein),
      scale 0.2s var(--gw-ein),
      overlay 0.2s var(--gw-ein) allow-discrete,
      display 0.2s var(--gw-ein) allow-discrete;
  }
  .gw-videodialog:not([open]),
  .gw-videodialog:not([open])::backdrop { opacity: 0; }
  .gw-videodialog:not([open]) { scale: 0.96; }

  .gw-videodialog[open],
  .gw-videodialog[open]::backdrop {
    transition-duration: 0.45s;
    transition-timing-function: var(--gw-aus);
  }

  @starting-style {
    .gw-videodialog[open],
    .gw-videodialog[open]::backdrop { opacity: 0; }
    .gw-videodialog[open] { scale: 0.96; }
  }

  /*
   * Ohne die Eigenschaft overlay (Firefox, Safari) verlässt der Dialog beim
   * Schliessen sofort die oberste Ebene. Dort blendet bewegung.js ihn vorher
   * 200 ms lang über diese Klasse aus und schliesst ihn erst danach.
   */
  .gw-videodialog[open].gw-schliesst,
  .gw-videodialog[open].gw-schliesst::backdrop {
    opacity: 0;
    transition-duration: 0.2s;
    transition-timing-function: var(--gw-ein);
  }
  .gw-videodialog[open].gw-schliesst { scale: 0.96; }
}

/* ================================================================== Hover mit Maus */

/*
 * Eine Karte reagiert auf ihr Ziel, nicht auf ihre Fläche: zeigt der Zeiger auf
 * einen Link darin (Play, Knopf, Bild, «E-Mail senden») oder hat er den
 * Tastaturfokus, blendet ein Schatten über ein Pseudo-Element ein (opacity statt
 * box-shadow animieren) und das Bild zoomt 1.04 in seinem Rahmen. Die Karte
 * selbst ist kein Link und soll nicht so wirken. Ohne Hebung: eine bewegte Karte
 * zöge ihren Link unter dem Zeiger weg und zitterte an der Unterkante.
 */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .gw-karte:has(a[href]) { position: relative; }

  :is(.gw-kachel, .gw-karte):has(a[href])::after {
    content: "";
    position: absolute;
    inset: 0;
    box-shadow: 0 24px 40px -18px rgba(12, 12, 13, 0.28), 0 8px 16px -10px rgba(12, 12, 13, 0.12);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.5s var(--gw-aus);
  }
  :is(.gw-kachel, .gw-karte):has(a[href]:is(:hover, :focus-visible))::after { opacity: 1; }

  /* Bildrahmen schneiden den Zoom ab; clip ändert die Masse nicht (kein Scrollcontainer) */
  .gw-kachel__bild,
  .gw-karte__bild { overflow: clip; }

  .gw-kachel__bild > img,
  .gw-karte:not(.gw-karte--einpassen) .gw-karte__bild img,
  .gw-film__bild {
    transition: scale 0.9s var(--gw-aus);
  }
  .gw-kachel:has(a[href]:is(:hover, :focus-visible)) .gw-kachel__bild > img,
  .gw-karte:not(.gw-karte--einpassen):has(a[href]:is(:hover, :focus-visible)) .gw-karte__bild img,
  .gw-film__vorschau:has(a[href]:is(:hover, :focus-visible)) .gw-film__bild { scale: 1.04; }
}

/* ================================================================== Immer */

/*
 * Textlinks: Unterstreichung wächst von links bis vor den Pfeil (Pfeil 20 +
 * Abstand 8; in Karten 24 + 10, Polster 16). Eine Linie auf ::before, die über
 * scale wächst (::after ist der Pfeil). Hover nur mit Maus: auf Touch bliebe sie
 * nach dem Antippen stehen.
 */
.gw-textlink { position: relative; }
.gw-textlink::before {
  content: "";
  position: absolute;
  left: 0;
  right: var(--gw-strich-ab, 28px);
  bottom: var(--gw-strich-unten, 0px);
  height: 2px;
  background: currentColor;
  scale: 0 1;
  transform-origin: left center;
  pointer-events: none;
}
.gw-textlink:focus-visible::before { scale: 1 1; }
@media (hover: hover) and (pointer: fine) {
  .gw-textlink:hover::before { scale: 1 1; }
}
.gw-karte__inhalt > .gw-textlink {
  --gw-strich-ab: 34px;
  --gw-strich-unten: 16px;
}

/*
 * Der Verlauf des Seitenkopfs (z-index 1, multiply) bleibt im Medium. Sonst lag
 * er über der oberen Hälfte der Intro-Plakette — mit voller Bewegung nicht, weil
 * view-transition-name dort ohnehin einen Stapelkontext bildet. So sieht die
 * Plakette in jeder Einstellung gleich aus. Gehört nach hero.css.
 */
.gw-hero__medium { isolation: isolate; }

/* ================================================================== Reduziert */

/*
 * Bei «Bewegung reduzieren» steht oben alles ausserhalb dieser Datei: keine
 * Keyframes, keine Parallaxe, kein Seitenübergang, nichts versteckt. kit-base.css
 * setzt dort ohnehin jede Animations- und Übergangsdauer auf 0.01 ms (!important),
 * Zustände wechseln also sofort. Einzig der Hintergrund des Video-Dialogs
 * (::backdrop, von kit-base nicht erfasst) blendet kurz über.
 */
@media (prefers-reduced-motion: reduce) {
  .gw-videodialog::backdrop {
    transition: opacity 0.12s linear;
    transition: opacity 0.12s linear, overlay 0.12s linear allow-discrete, display 0.12s linear allow-discrete;
  }
  .gw-videodialog:not([open])::backdrop { opacity: 0; }

  @starting-style {
    .gw-videodialog[open]::backdrop { opacity: 0; }
  }
}

/* ================================================================== Druck */

@media print {
  [data-gw-zeigen] {
    opacity: 1 !important;
    animation: none !important;
  }
}
