/*
 * Bewegung. Getrieben von der Taktuhr in public/js/motion.js: die setzt
 * --beat-pulse (1 auf dem Schlag, abklingend bis 0) und data-beat (0..3) auf
 * :root. Was hier steht, liest diese beiden Werte — es gibt keine zweite
 * Zeitquelle und keine frei erfundenen Dauern.
 *
 * Ohne JavaScript passiert nichts davon, und die Seite bleibt vollstaendig
 * lesbar: alle Ausgangszustaende sind sichtbar, nicht unsichtbar.
 */

:root {
  --beat-pulse: 0;
  --beat-accent: 0; /* wie --beat-pulse, aber nur auf der Eins voll */
  --takt: 517ms; /* 60000 / 116 bpm */
}

/* Die Buehne atmet auf der Eins. Sechs Promille sind wenig genug, um nicht als
   Wackeln zu lesen, und genug, damit die ganze Flaeche im Takt lebt — das ist
   der Unterschied zwischen einem Standbild mit Effekten und einer Seite, die
   mitgeht. */
.js-motion .stage-hero__sky {
  transform: scale(calc(1 + var(--beat-accent) * 0.006));
  transform-origin: 50% 44%;
  will-change: transform;
}
.js-motion .stage-hero__veil {
  opacity: calc(1 - var(--beat-accent) * 0.05);
}

/* ── Schlagzeile ─────────────────────────────────────────────────────────── */

/* Nur wenn JS zerlegt hat. Ohne .is-split steht die Zeile normal da. */
.hero__title.is-split .ch {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.42em) rotateX(-55deg);
  transform-origin: 50% 100%;
  animation: chIn 0.62s cubic-bezier(0.2, 0.9, 0.2, 1) forwards;
  will-change: transform, opacity;
}
@keyframes chIn {
  from { opacity: 0; transform: translateY(0.42em) rotateX(-55deg); }
  60%  { opacity: 1; }
  to   { opacity: 1; transform: translateY(0) rotateX(0); }
}

/* Das im Takt durchwandernde Glimmen. */
.hero__title.is-split .ch.is-lit {
  animation: chIn 0.62s cubic-bezier(0.2, 0.9, 0.2, 1) forwards, chLit var(--takt) ease-out;
}
@keyframes chLit {
  0%   { text-shadow: 0 0 0 rgba(106, 209, 255, 0); }
  18%  { text-shadow: 0 0 26px rgba(106, 209, 255, 0.85), 0 0 8px rgba(255, 255, 255, 0.6); }
  100% { text-shadow: 0 0 0 rgba(106, 209, 255, 0); }
}

/* ── Der Takt selbst ─────────────────────────────────────────────────────── */

/* Die Eins traegt mehr Gewicht als die uebrigen drei Schlaege. */
.hero__scroll span { animation-duration: calc(var(--takt) * 2); }

.eyebrow::before {
  opacity: calc(0.35 + var(--beat-pulse) * 0.65);
  box-shadow: 0 0 calc(6px + var(--beat-pulse) * 14px) rgba(106, 209, 255, 0.7);
}

/* Der Startknopf der Demo atmet mit — er ist die Einladung, im Takt zu tippen. */
.demo-launch {
  box-shadow:
    0 0 calc(18px + var(--beat-pulse) * 26px)
    color-mix(in srgb, var(--demo-accent) calc(12% + var(--beat-pulse) * 22%), transparent);
}
.demo-launch__orbit i {
  transform: translateY(-50%) scale(calc(1 + var(--beat-pulse) * 0.35));
}

/* Der Live-Punkt ueber dem Telefon blinkt nicht mehr frei, sondern auf der Eins. */
.demo-meta i {
  animation: none;
  opacity: calc(0.3 + var(--beat-pulse) * 0.7);
  transform: scale(calc(1 + var(--beat-pulse) * 0.5));
}

/* ── Reveals ─────────────────────────────────────────────────────────────── */

.rise {
  opacity: 0;
  transform: translateY(26px) scale(0.985);
  transition:
    opacity 0.66s cubic-bezier(0.2, 0.9, 0.2, 1) var(--d, 0ms),
    transform 0.66s cubic-bezier(0.2, 0.9, 0.2, 1) var(--d, 0ms);
}
.is-in .rise,
.rise.is-in { opacity: 1; transform: none; }

/* Ueberschriften kommen mit einer Maske statt mit einem Verschieben.
   Gebunden an .js-motion, das motion.js setzt: ohne JavaScript darf hier keine
   Maske liegen, sonst sind die Ueberschriften schlicht unsichtbar. */
.js-motion .sec__head .h2,
.js-motion .cinema .h2 {
  clip-path: inset(0 0 110% 0);
  transition: clip-path 0.8s cubic-bezier(0.16, 1, 0.3, 1) 60ms;
}
.js-motion .is-in .h2,
.js-motion .h2.is-in { clip-path: inset(0 0 -20% 0); }

/* ── Karten und Kacheln ──────────────────────────────────────────────────── */

.wcard { transition: transform 0.5s cubic-bezier(0.2, 0.9, 0.2, 1), border-color 0.35s, box-shadow 0.5s; }
.wcard:hover {
  transform: translateY(-8px);
  box-shadow: 0 30px 60px -34px #000, 0 0 40px -20px rgba(106, 209, 255, 0.55);
}
.wcard:hover .wcard__img img { transform: scale(1.07); }

.gallery__item { transition: transform 0.45s cubic-bezier(0.2, 0.9, 0.2, 1), box-shadow 0.45s; }
.gallery__item:hover {
  transform: translateY(-6px) scale(1.02);
  box-shadow: 0 26px 50px -28px #000, 0 0 34px -18px rgba(168, 107, 255, 0.5);
}

.feature { transition: transform 0.45s cubic-bezier(0.2, 0.9, 0.2, 1), border-color 0.35s; }
.feature:hover { transform: translateY(-5px); }

/* ── Bewegungsarm: alles einfrieren, nichts verstecken ───────────────────── */

@media (prefers-reduced-motion: reduce) {
  .hero__title.is-split .ch,
  .rise,
  .js-motion .sec__head .h2,
  .js-motion .cinema .h2 {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
    animation: none !important;
    transition: none !important;
  }
  .demo-launch,
  .demo-launch__orbit i,
  .demo-meta i,
  .eyebrow::before,
  .js-motion .stage-hero__sky,
  .js-motion .stage-hero__veil {
    animation: none !important;
    transform: none !important;
    opacity: 1 !important;
  }
}
