/* ==========================================================================
   05-ANIMATIONEN
   --------------------------------------------------------------------------
   Regeln, die diese Datei durchhält:
   • Reveals arbeiten mit clip-path und Verschiebung, NICHT mit reinem
     opacity-Fade. Fades allein sind das Erkennungszeichen von
     Vorlagen-Seiten; ein Vorhang, der aufzieht, wirkt gestaltet.
   • Nichts wackelt dauerhaft. Bewegung hat immer einen Anlass.
   • Alles hier wird von prefers-reduced-motion in 02-base.css abgeschaltet.
   ========================================================================== */


/* ==========================================================================
   SCROLL-REVEALS
   Startzustand hier, Freigabe per [data-reveal="sichtbar"] durch den
   IntersectionObserver in js/reveal.js.
   ========================================================================== */

[data-reveal] {
  --reveal-verzug: 0ms;
  transition:
    opacity var(--d-reveal) var(--e-out) var(--reveal-verzug),
    transform var(--d-reveal) var(--e-out) var(--reveal-verzug),
    clip-path var(--d-reveal) var(--e-out) var(--reveal-verzug);
  will-change: transform, opacity;
}

/* Standard: Vorhang von unten */
[data-reveal="bereit"] {
  opacity: 0;
  transform: translateY(2.5rem);
  clip-path: inset(0 0 100% 0);
}
[data-reveal="sichtbar"] {
  opacity: 1;
  transform: none;
  clip-path: inset(0 0 0 0);
}

/* Varianten über data-reveal-art */
[data-reveal-art="links"][data-reveal="bereit"] {
  transform: translateX(-3rem);
  clip-path: inset(0 100% 0 0);
}
[data-reveal-art="rechts"][data-reveal="bereit"] {
  transform: translateX(3rem);
  clip-path: inset(0 0 0 100%);
}
[data-reveal-art="vorhang"][data-reveal="bereit"] {
  opacity: 1;
  transform: none;
  clip-path: inset(0 100% 0 0);   /* Bild wird freigewischt */
}
[data-reveal-art="skalieren"][data-reveal="bereit"] {
  opacity: 0;
  transform: scale(1.06);
  clip-path: none;
}
[data-reveal-art="skalieren"][data-reveal="sichtbar"] {
  transform: scale(1);
}
/* Nur Verschiebung, kein Clip — für Textabsätze */
[data-reveal-art="sanft"][data-reveal="bereit"] {
  opacity: 0;
  transform: translateY(1.25rem);
  clip-path: none;
}

/* Gestaffelte Kinder: Container bekommt data-reveal-staffel,
   reveal.js setzt --i auf jedem Kind. */
[data-reveal-staffel] > * {
  transition:
    opacity var(--d-slow) var(--e-out),
    transform var(--d-slow) var(--e-out);
  transition-delay: calc(var(--i, 0) * 90ms);
}
[data-reveal-staffel][data-reveal="bereit"] > * {
  opacity: 0;
  transform: translateY(2rem);
}
[data-reveal-staffel][data-reveal="sichtbar"] > * {
  opacity: 1;
  transform: none;
}


/* ==========================================================================
   HEADLINE-ZEILEN-REVEAL
   Jede Zeile sitzt in einem Maskenrahmen und fährt von unten herein.
   Das ist der wirkungsvollste Effekt im ganzen System — sparsam einsetzen,
   nur bei Hero- und Sektionsheadlines.
   Markup:  <h1 class="zeilen"><span><i>Zeile eins</i></span>…</h1>
   ========================================================================== */

.zeilen span {
  display: block;
  overflow: hidden;
}
.zeilen i {
  display: block;
  font-style: inherit;
  transform: translateY(105%);
  transition: transform 1s var(--e-out);
  transition-delay: calc(var(--i, 0) * 110ms);
}
.zeilen[data-reveal="sichtbar"] i,
.ist-geladen .hero .zeilen i { transform: translateY(0); }

/* ACHTUNG, hier lag ein Fehler (gefunden 11.08.2026 bei Brühne):
   Die Regeln oben verstecken jede Zeile mit translateY(105%) und holen sie
   erst zurück, wenn site.js entweder data-reveal="sichtbar" oder die Klasse
   .ist-geladen gesetzt hat. Ist JavaScript deaktiviert oder site.js
   fehlerhaft, bleibt die H1 der Startseite dauerhaft unsichtbar — die Seite
   hat dann sichtbar keine Überschrift.

   Die Klasse "js" wird ganz oben im <head> per Inline-Script gesetzt und
   fehlt ohne JavaScript. Genau daran hängt der Rückfall: Ohne JavaScript
   stehen die Zeilen einfach da, ohne Animation. */
html:not(.js) .zeilen i {
  transform: none;
  transition: none;
}


/* ==========================================================================
   TEXT-LAUFBAND (großes Wortband, z. B. LEISTUNGEN)
   Zwei identische Spuren nebeneinander → nahtlose Schleife.
   ========================================================================== */

.wortband {
  --tempo: 70s;
  position: relative;
  display: flex;
  overflow: hidden;
  padding-block: var(--s-4);
  border-block: var(--b-bold);
  background: var(--c-accent);
  color: var(--c-accent-ink);
  user-select: none;
}
.wortband--ruhig { background: var(--c-paper-warm); color: var(--c-ink); }

.wortband__spur {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--s-6);
  padding-right: var(--s-6);
  white-space: nowrap;
  animation: wortband-lauf var(--tempo) linear infinite;
}
.wortband--rueckwaerts .wortband__spur { animation-direction: reverse; }
/* Läuft durch, auch beim Überfahren — siehe Begründung beim Laufband. */

.wortband__spur > span {
  display: inline-flex;
  align-items: center;
  gap: var(--s-6);
  font-family: var(--f-display);
  font-size: clamp(0.8125rem, 1.15vw, 1.0625rem);
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
}
/* Trennzeichen zwischen den Begriffen */
.wortband__spur > span::after {
  content: "";
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.45;
}

@keyframes wortband-lauf {
  from { transform: translateX(0); }
  to   { transform: translateX(-100%); }
}


/* ==========================================================================
   ZÄHLER
   Zahl läuft beim Sichtbarwerden hoch (js/zaehler.js).
   Tabellenziffern verhindern das nervöse Zappeln der Breite.
   ========================================================================== */

[data-zaehler] {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}


/* ==========================================================================
   BILD-HOVER: Farbwischer
   Beim Überfahren zieht ein Akzentbalken diagonal über das Bild —
   passende Metapher für einen Malerbetrieb.
   ========================================================================== */

.wischer {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.wischer::after {
  content: "";
  position: absolute;
  inset: -20%;
  z-index: 1;
  background: var(--c-accent);
  mix-blend-mode: multiply;
  transform: translateX(-115%) skewX(-12deg);
  transition: transform var(--d-slow) var(--e-io);
  pointer-events: none;
}
.wischer:hover::after { transform: translateX(115%) skewX(-12deg); }


/* ==========================================================================
   SEITENEINSTIEG
   Kurzer Vorhang beim ersten Laden. Bewusst schnell (450 ms) —
   lange Intros nerven Kunden und kosten Ladezeit-Wahrnehmung.
   Wird entfernt, sobald <html> die Klasse ist-geladen bekommt.
   ========================================================================== */

.einstieg {
  position: fixed;
  inset: 0;
  z-index: 999;
  display: grid;
  place-items: center;
  background: var(--c-ink);
  clip-path: inset(0 0 0 0);
  transition: clip-path 620ms var(--e-io) 120ms;
  pointer-events: none;
}
.ist-geladen .einstieg { clip-path: inset(0 0 100% 0); }

.einstieg__marke {
  font-family: var(--f-label);
  font-size: var(--t-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-paper);
  opacity: 1;
  transition: opacity 260ms var(--e-out);
}
.ist-geladen .einstieg__marke { opacity: 0; }

/* Ohne JS darf der Vorhang die Seite nicht blockieren */
html:not(.js) .einstieg { display: none; }


/* ==========================================================================
   KLEINE DETAILS
   ========================================================================== */

/* Pulsierender Punkt für "Jetzt erreichbar" — der einzige Dauerloop im
   System, weil er eine Statusinformation trägt. */
.status-punkt {
  display: inline-block;
  width: 8px;
  height: 8px;
  background: var(--c-success);
  animation: status-puls 2.4s var(--e-io) infinite;
}
@keyframes status-puls {
  0%, 100% { opacity: 1;   transform: scale(1); }
  50%      { opacity: 0.45; transform: scale(0.75); }
}

/* Scroll-Hinweis im Hero */
.scroll-hinweis {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  font-family: var(--f-label);
  font-size: var(--t-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}
.scroll-hinweis__linie {
  position: relative;
  width: 2.5rem;
  height: 1.5px;
  background: rgba(246,242,235,0.35);
  overflow: hidden;
}
.scroll-hinweis__linie::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--c-accent);
  animation: linie-lauf 2.2s var(--e-io) infinite;
}
@keyframes linie-lauf {
  0%   { transform: translateX(-100%); }
  55%  { transform: translateX(0); }
  100% { transform: translateX(100%); }
}

/* Fortschrittsbalken am oberen Rand (Leseposition) */
.lesefortschritt {
  position: fixed;
  top: 0; left: 0;
  z-index: calc(var(--z-nav) + 1);
  height: 3px;
  width: 100%;
  transform: scaleX(var(--fortschritt, 0));
  transform-origin: left;
  background: var(--c-accent);
  pointer-events: none;
}
