/* ==========================================================================
   Bewegung
   Grundregel: Inhalt ist per Default sichtbar. Der versteckte Ausgangs-
   zustand greift NUR, wenn JS die Klasse .js am <html> gesetzt hat. Ohne JS,
   bei JS-Fehler oder im headless-Renderer ist die Seite vollstaendig lesbar.
   ========================================================================== */

/* --- Scroll-Reveal -------------------------------------------------------- */
html.js .zeig {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--dauer-lang) var(--ease-aus),
              transform var(--dauer-lang) var(--ease-aus);
  will-change: opacity, transform;
}
html.js .zeig.sichtbar { opacity: 1; transform: none; }

/* Staffelung innerhalb EINER Gruppe (nicht als Reflex ueber jede Sektion) */
html.js .staffel > * {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--dauer) var(--ease-aus),
              transform var(--dauer) var(--ease-aus);
  transition-delay: calc(var(--i, 0) * 70ms);
}
html.js .staffel.sichtbar > * { opacity: 1; transform: none; }

/* --- Hero: Zeilen steigen einzeln aus ihrer Maske ------------------------- */
html.js .hero__zeile { display: block; overflow: hidden; }
html.js .hero__zeile > span {
  display: block;
  transform: translateY(105%);
  transition: transform 900ms var(--ease-aus);
  transition-delay: calc(var(--i, 0) * 110ms);
}
html.js .hero.geladen .hero__zeile > span { transform: none; }

html.js .hero__nach {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dauer-lang) var(--ease-aus) 480ms,
              transform var(--dauer-lang) var(--ease-aus) 480ms;
}
html.js .hero.geladen .hero__nach { opacity: 1; transform: none; }

/* --- Balken-Wipe ---------------------------------------------------------
   Bewusst rein transform-basiert: ein schraeg beschnittenes Pseudo-Element
   faehrt durch. Kein clip-path- oder width-Keyframing (das wuerde bei jedem
   Frame neu rastern).
   ------------------------------------------------------------------------- */
.wipe { position: relative; overflow: hidden; }
html.js .wipe::before {
  content: "";
  position: absolute; inset: -2px -60% -2px -60%;
  background: color-mix(in oklab, var(--cd-weiss) 22%, var(--cd-blau));
  clip-path: polygon(0 0, 100% 0, calc(100% - 12vh) 100%, 0 100%);
  transform: translateX(-140%);
  transition: transform 820ms var(--ease-aus), visibility 0s linear 820ms;
  z-index: 3;
  pointer-events: none;
  visibility: visible;
}
/* Nach dem Durchlauf komplett aus dem Weg — sonst bleibt am Rand ein Rest
   stehen, der wie ein Layout-Fehler aussieht. */
html.js .wipe.sichtbar::before { transform: translateX(140%); visibility: hidden; }

/* --- Zaehler: reserviert Platz, damit beim Hochzaehlen nichts springt ----- */
.zahl { font-variant-numeric: tabular-nums; }

/* --- Bewegungsreduzierung ------------------------------------------------
   Nicht „weniger Bewegung", sondern keine: Endzustand sofort.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html.js .zeig,
  html.js .staffel > *,
  html.js .hero__nach {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  html.js .hero__zeile > span { transform: none !important; transition: none !important; }
  html.js .wipe::before { display: none; }
  .bild--zoom img { transition: none; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- Innenseiten-Hero: Textgruppe faehrt beim Laden ein --------------------
   Bewusst eine Animation, kein Klassen-Toggle: eine Transition, die auf eine
   per JS gesetzte Klasse wartet, laesst den Text stehen, wenn das Skript
   fehlt, spaet kommt oder der Tab im Hintergrund liegt. Die Animation laeuft
   von selbst und endet garantiert sichtbar (both). Ohne JS ist --i gleich 0,
   dann startet alles gemeinsam statt versetzt.
   Kein Zeilen-Stagger wie auf der Startseite: die Innen-H1 sind lange
   Komposita, die je nach Breite anders umbrechen.                          */
@keyframes seitenkopf-ein {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
html.js .seitenkopf__innen > .krumen,
html.js .seitenkopf__text > * {
  animation: seitenkopf-ein var(--dauer-lang) var(--ease-aus) both;
  animation-delay: calc(var(--i, 0) * 70ms);
}
@media (prefers-reduced-motion: reduce) {
  html.js .seitenkopf__innen > .krumen,
  html.js .seitenkopf__text > * { animation: none; }
}
