/* ============================================================
   HERO UND ÜBERGANG

   Eine gemeinsame Bühne von 240 svh, darin ein gepinnter Rahmen von
   einer Viewporthöhe. Das Bild steht dadurch von der ersten bis zur
   letzten Sekunde still — es gibt keine Naht, an der eine Sektion
   endet und die nächste dasselbe Bild noch einmal anfängt.

   1. HERO (die ersten 28 %): im Waldvideo bricht die Kamera durch
      die Wipfel und gibt eine geschwungene Straße mit einem Lastwagen
      frei; danach laufen die letzten sieben Sekunden in einer
      Schleife, der Lastwagen fährt immer weiter (js/hero.js). Darüber
      die vier Anker der Faustina-Vorlage: Metazeile, Name in zwei
      Ecken, Aussage, Satz — und ein Knopf, der das Video anhält.

   2. ÜBERGANG (Rest): die Hero-Texte blenden weg, und aus der Mitte
      zieht ein clip-path die Fläche der nächsten Sektion auf — erst
      ein schmaler Bogen, dann Vollbild. Der Wald weicht zurück, die
      Seite tritt hervor. Im Bogen steht die Porträtkarte aus der
      About-Sektion (css/components.css).

   Alles am Übergang hängt an einem einzigen, gefederten
   Fortschrittswert, den js/hero.js berechnet.
   ============================================================ */

:root {
  --light: var(--c-lamp);    /* Farbe des Straßenlichts (= #fdf6e6) */
  --light-core: #fffdf6;

  /* Radius des Bogens oben. Bewusst groß: bei 28 % Seiteneinzug ist
     der Ausschnitt rund 600 px breit, erst ein Radius in dieser
     Größenordnung liest sich als Bogen und nicht als Kasten. */
  --srh-radius: 200px;
}

/* ---------- Bühne ---------------------------------------------------
   240 svh Scrollweg, darin ein gepinnter Rahmen von 100 svh. Bleiben
   140 svh Weg: die ersten 39 gehören dem Hero — so lange steht er,
   während seine Texte weggehen —, die restlichen 101 dem Bogen. Den
   Schnitt setzt BRIDGE_FROM in js/hero.js.

   Vorher waren es 320 svh. Der Übergang war korrekt, aber zäh: 154 svh
   nur für das Aufziehen des Bogens sind zwei volle Bildschirme
   Wischen. */
.stage {
  position: relative;
  width: 100%;
  height: 240svh;
  /* Auf ganze Pixel gerundet: 240 svh sind auf einem 844er Gerät
     2025,6 px, die Unterkante des gepinnten Rahmens läge also auf
     einem Bruchteil. Bogen und Standbild runden dort unterschiedlich,
     und es blieb eine Zeile Wald zwischen Bogen und nächster Sektion
     stehen. Ältere Browser ohne round() behalten die Zeile davor. */
  height: round(240svh, 1px);
  background: #000;
}

/* Die Kante der Bühne — .stage__content und der Scrollhinweis richten
   sich beide danach. */
.stage__pin {
  --hero-x: var(--gutter);
  position: sticky;
  top: 0;
  left: 0;
  width: 100%;
  height: 100svh;
  overflow: hidden;
  background: #000;
}

/* ---------- Hero: Bild, Schleier, Text ------------------------------- */
.stage__hero {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.stage__scene {
  position: absolute;
  inset: 0;
}

/* ---------- Vorschau gegen den schwarzen Anfang ----------------------
   Bis das erste Videobild da ist, ist die Bühne schwarz. Gemessen auf
   1,6 Mbit/s mit 150 ms Latenz, 390 px breit: erster Paint nach 992 ms,
   das Poster erst nach 1352 ms — über eine Sekunde nichts.

   Dagegen steht hier das erste Videobild zweimal, übereinander:

   Unten als Miniatur im Stylesheet, 64 × 36 bzw. 40 × 71 Pixel,
   zusammen unter 800 Byte. Sie kostet keine eigene Anfrage und ist
   damit genau dann da, wenn überhaupt zum ersten Mal gezeichnet wird.
   Ein Preloader mit Spinner wäre das Gegenteil: noch ein Skript, noch
   eine Anfrage, und am Ende sieht man ein Rädchen statt des Bildes.

   Darüber als Poster in voller Schärfe. Es stand früher als
   poster-Attribut am <video>, aber das kennt kein media: Das Handy bekam
   das quere Bild (960 px) und zeigte davon die mittleren 26 % — 250
   Pixel für 1170 Gerätepixel. Hier hat hochkant ein eigenes (900 px).
   Auf WebKit steht es spürbar lange: das MP4 läuft dort erst an, wenn
   das erste MiB geladen ist, bei 6 Mbit/s nach gut 2 s, bei 1,6 nach
   knapp 8 s.

   Das Video ist bis zu seinem ersten Bild durchsichtig und legt sich
   dann darüber — alles deckt dieselbe Fläche, background-size: cover
   rahmt wie object-fit: cover.

   Bei reduzierter Bewegung bleibt es beim Verlauf weiter unten: dort
   erscheint das Standbild vom ENDE des Clips, die Vorschau vom Anfang
   würde dazwischenblitzen. */
.stage__scene {
  background-color: #0d1210;
  background-image:
    url("../assets/hero-waldlichter-fein-poster.webp"),
    url("data:image/webp;base64,UklGRgIBAABXRUJQVlA4IPYAAABwCQCdASpAACQAPpE4mEgloyKhMBgKqLASCWcAyRAR9lzcwkfziOb95vWPmEdykwxlrSP6v+DkBE7g0N6x7j1K0B9EE+vVbgs2VlG2zHnK8xsvZZQA/vLRbBguifSuivWWSRsRhotPlJ52aF4S0oYm31phMWxlGzTmR9ZYjVDynedHIGfnxDMOraSsvzyJs3/liLEwyqCNhh3Tm4FMWIym+qR5U57EFfb700JAzGXxtEQnvO6SLk2YFGVYkwDW3L4pnvgJz7HjWssbYqFKsI/i/Ib4h+KHHqVKn/4cUmFWalhC/28zsPN6d0kA6Yfys0tyCoiuAAA=");
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}

@media (max-width: 560px) and (orientation: portrait) {
  .stage__scene {
    background-image:
      url("../assets/hero-waldlichter-fein-poster-hoch.webp"),
      url("data:image/webp;base64,UklGRi4BAABXRUJQVlA4ICIBAACwCQCdASooAEcAPpE+mEoloyIhqrZqaLASCWdnnlZAg+TH8alOTSTso5/vAn1yiJJ9SgeAaZSQnO4gQnrdPpfWsf71CFbfOELrju6EmYijEDK4s4fOgAD+wo1gtqvR+TJKaH6PZfNVft+fYYRJNyiJcj99YxWG5roiHHEXuYS8hrACFJAmluooosx7Wm5687YGxQe3jRt+jAg+MizzFggxVNLvd3qszGrJiSa7rQK5PZRDhLYFCdZpiuHuWK6YRl1g0c7mNh4a49yht3SzFsRVxF6fOn4wH7EHZv6KIure5I6UAwoQZP6AhGR8cLH2aAgKq5vt/S6zvtGI0mEjwJzDhby51yArkpmh6Nk2wWPWLUaRS0oXLdc2pmLr1eK+8dAAAA==");
  }
}

/* ---------- Video und eingefrorenes Standbild -------------------------
   Das Video läuft einmal durch und friert auf seinem letzten Bild ein;
   das Standbild zeigt genau dieses Bild. Es übernimmt außerdem, wenn es
   keine Bewegung geben darf oder kann: reduzierte Bewegung, abgelehntes
   Autoplay, eine ausgefallene Quelle, ein hängendes Video. Ein
   Bild kostet keine Dekodierung und bleibt zuverlässig stehen — manche
   Browser entladen pausierte Videos. */
.stage__video,
.stage__still {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
}

.stage__still { opacity: 0; }

/* Umschalten beim Einfrieren. Ohne Blende, sonst blitzt der Wechsel.
   `display: none` statt `opacity: 0`: ein durchsichtiges Video bliebe
   eine eigene Compositing-Ebene. */
.stage.is-frozen .stage__video { display: none; }
.stage.is-frozen .stage__still { opacity: 1; }

/* Schleier. Die Farbe setzt js/hero.js: im Hero 0, im Übergang
   wandert sie hoch und schiebt den Wald hinter die aufziehende Seite.

   Dazu kommt fest ein Verlauf oben und unten. Das Nebelstraßen-Video
   ist an den Rändern nicht einheitlich hell oder dunkel: oben steht
   heller Dunst in der Mitte zwischen dunklen Fichten, unten fährt der
   weiße Koffer des Lastwagens durchs Bild. Keine Schriftfarbe trägt
   auf beidem. Der Verlauf dunkelt nur die Ränder ab, auf denen Schrift
   steht, und lässt die Mitte frei — dort läuft das Bild. Der Verlauf
   ist ein background-image, die Farbe des Skripts liegt als
   background-color darunter, beide stören sich nicht. */
.stage__tint {
  position: absolute;
  inset: 0;
  background-color: rgba(0, 0, 0, 0);
  background-image:
    linear-gradient(to bottom,
      rgba(8, 14, 10, 0.74) 0%,
      rgba(8, 14, 10, 0.52) 12%,
      rgba(8, 14, 10, 0.26) 22%,
      rgba(8, 14, 10, 0) 38%,
      rgba(8, 14, 10, 0) 58%,
      rgba(8, 14, 10, 0.42) 80%,
      rgba(8, 14, 10, 0.68) 100%);
}

/* ============================================================
   HERO-INHALT

   Anordnung: oben die Wortmarke riesig über die volle Breite, unten
   links die Aussage in zwei versetzten Zeilen, unten rechts der Knopf.
   Mehr steht nicht im Bild — das Video trägt die Mitte.
   ============================================================ */
.stage__content {
  /* Kein Flusslayout: die vier Anker liegen absolut in den Ecken. Die
     Kante steht als Custom Property, weil ein Padding hier nichts
     brächte — absolut positionierte Kinder rechnen gegen die
     Polsterkante des Elternteils, nicht gegen dessen Inhaltskante. */
  --hero-t: clamp(20px, 3.4svh, 44px);
  --hero-b: clamp(26px, 4.4svh, 52px);

  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  will-change: transform, opacity;
}

/* ============================================================
   HERO-INHALT — Aufbau nach der Faustina-Vorlage

   Vier Anker statt eines Blocks: die Metazeile oben über die volle
   Breite, der Name in zwei Hälften diagonal in die Ecken, unten links
   die Aussage in Versalien, rechts auf halber Höhe der erklärende
   Satz. Die Mitte bleibt frei — dort läuft das Video.

   Die Vorlage arbeitet mit Neongelb auf dem Foto. Hier entscheidet
   nicht der Geschmack, sondern das Bild: nachgemessen über die ganze
   Laufzeit liegt das obere Band bei L 0,45 bis 0,98 — heller Dunst und
   Himmel —, das untere durchgehend bei 0,04 bis 0,17. Helle Schrift
   käme oben auf 1,0 bis 2,0:1 und wäre schlicht weg.

   Deshalb zweifarbig, nicht aus Laune: oben Tinte (8,9 bis 18,4:1),
   unten Lampenlicht (4,6 bis 12,8:1). Der Name wechselt dabei mit dem
   Grund die Farbe — er steht mit einem Fuß im Himmel und mit dem
   anderen im Wald.
   ============================================================ */

/* ---------- Metazeile ------------------------------------------------
   Vier Angaben auf einer Linie, gleichmäßig verteilt. Klein und weit
   gesperrt — sie soll gelesen werden können, ohne die Ecken zu
   stören. */
.hero__meta {
  position: absolute;
  left: var(--hero-x);
  right: var(--hero-x);
  top: var(--hero-t);
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-size: clamp(10px, 0.86vw, 13px);
  font-weight: var(--w-semi);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--light-core);
  text-shadow: 0 1px 18px rgba(0, 0, 0, 0.6);
}

/* Der einzige Weg nach draußen im Bild — deshalb als Link erkennbar,
   nicht bloß als weitere Angabe. */
.hero__metalink {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding-bottom: 2px;
  border-bottom: 1px solid rgba(255, 253, 246, 0.45);
  pointer-events: auto;
  transition: border-color var(--d-ui) var(--ease-ui);
}

.hero__metalink svg { width: 0.85em; height: 0.85em; }
.hero__metalink:hover { border-bottom-color: var(--light-core); }
.hero__metalink:focus-visible { outline: 2px solid var(--light-core); outline-offset: 4px; }

/* ---------- Der Slogan, rechts unten ---------------------------------
   Er steht dort, wo vorher „Beratung" in Versalien stand, aber leicht:
   300er Schnitt, gut halb so groß, normale Schreibung. Er soll das Bild
   tragen, nicht erschlagen — die Straße im Nebel ist das Motiv. */
.hero__claim {
  position: absolute;
  right: var(--hero-x);
  bottom: var(--hero-b);
  margin: 0;
  text-align: right;
  font-size: clamp(30px, 4.4vw, 66px);
  font-weight: 300;
  line-height: 1.02;
  letter-spacing: -0.025em;
  color: var(--light-core);
  text-shadow: 0 2px 40px rgba(0, 0, 0, 0.45);
}

/* Sobald der Übergang läuft, ist der Link nicht mehr anklickbar —
   er blendet weg und läge sonst unsichtbar über der Seite. */
.stage.is-leaving .hero__metalink { pointer-events: none; }

/* ---------- Pause-Knopf -----------------------------------------------
   Das Video läuft in einer Schleife, also ohne Ende — und endlose
   Bewegung neben Text braucht einen Weg, sie anzuhalten (WCAG 2.2.2).
   Schrift wie die Metazeile, dazu ein kleines Symbol.

   Platz: an der linken Kante unter dem Scrollhinweis. Verglichen mit
   darüber, rechts gespiegelt und in der Metazeile, in 1920×1080,
   1440×900, 1280×720, 768×1024, 390×844 und 360×640. Rechts liegt er
   hochkant auf dem Satz (390 und 360 überlappen, über dem Satz 768),
   in der Metazeile überlappt er dort die umbrochenen Angaben, und
   dunkle Schrift käme auf die Wipfel des ersten Flugs (1,0:1, Frames
   1–9). Über dem Hinweis reicht im ersten Flug der Dunst am Horizont
   heran (1280×720: 1,2:1 ohne Unterlage), darunter bleibt es Wald.
   Zur nächsten Schrift bleiben mindestens 9,8 px Trefferfläche bzw.
   15,6 px sichtbare Form.

   Die Unterlage ist gemessen, nicht Zierde. Lampenlicht allein kam
   gegen den hellsten Pixel seines Kastens, über alle 281 Frames plus
   Poster und Standbild, auf 0,99:1 (390×844: der weiße Koffer des
   Lastwagens fährt im ersten Flug hindurch) und am Desktop auf 2,2:1
   (1440×900, Standbild). Mit Schwarz bei 60 % Deckkraft, in Chrome
   Frame für Frame nachgemessen (Video, Unterlage und Körnung so, wie
   sie gerendert werden): Schrift mindestens 5,43:1 (390×844, Frame 41
   im ersten Flug), in der Schleife 6,99:1, am Desktop 10,57:1; das
   Symbol 12,1:1. Rechnet man die Körnung auch noch dunkel in die
   Schrift, bleiben 4,97:1. Mit 55 % waren es dort nur 4,16:1.

   Trefferfläche 44 px hoch: Die sichtbare Form ist 2,5 em (25–33 px),
   der Knopf darum herum hält die Höhe. Die Oberkante liegt 58 px unter
   der Bildmitte, der Hinweis reicht 48 px hinab (3 em bei 16 px). */
.hero__pause {
  position: absolute;
  left: var(--hero-x);
  bottom: var(--hero-b);
  display: inline-flex;
  align-items: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: transparent;
  font-size: clamp(10px, 0.86vw, 13px);
  font-weight: var(--w-semi);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--light-core);
  cursor: pointer;
  pointer-events: auto;
  -webkit-tap-highlight-color: transparent;
}

.hero__pause[hidden] { display: none; }

.hero__pause-face {
  display: inline-flex;
  align-items: center;
  gap: 0.8em;
  height: 2.5em;
  padding: 0 1.15em 0 1em;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.6);
  line-height: 1;
  transition: background-color var(--d-ui) var(--ease-ui);
}

/* Beide Beschriftungen im selben Rasterfeld: die unsichtbare längere
   („Abspielen") hält die Breite, sonst sprang die rechte Kante der
   Form beim Umschalten um 4,5–5,9 px unter dem Zeiger weg. */
.hero__pause-label { display: inline-grid; }
.hero__pause-label::after {
  content: "Abspielen";
  grid-area: 1 / 1;
  height: 0;
  overflow: hidden;
  visibility: hidden;
}

.hero__pause-icon {
  flex: none;
  width: 0.9em;
  height: 0.9em;
  overflow: visible;
}

.hero__pause-bars { fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; }
.hero__pause-play { fill: currentColor; display: none; }
.hero__pause.is-paused .hero__pause-bars { display: none; }
.hero__pause.is-paused .hero__pause-play { display: inline; }

.hero__pause:hover .hero__pause-face { background-color: rgba(0, 0, 0, 0.72); }

/* Fokusring zweifarbig: innen Lampenlicht direkt an der dunklen Form
   (dasselbe Verhältnis wie die Schrift, also mindestens 5,43:1), außen
   ein dunkler Saum mit derselben Deckkraft, der ihn auch vom weißen
   Lastwagen trennt. Der durchsichtige Umriss wird nur im Kontrastmodus
   von Windows sichtbar — der entfernt Schatten, sonst bliebe dort gar
   kein Ring. */
.hero__pause:focus-visible { outline: none; }
.hero__pause:focus-visible .hero__pause-face {
  outline: 2px solid transparent;
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--light-core), 0 0 0 4px rgba(0, 0, 0, 0.6);
}

.stage.is-leaving .hero__pause { pointer-events: none; }

/* ============================================================
   ÜBERGANG

   Ein Bogen, der die Fläche der nächsten Sektion aufzieht. Er selbst
   bleibt leer: was darin steht, ist die Porträtkarte aus der
   About-Sektion, die js/hero.js so lange in der Bildmitte festhält,
   bis ihr Platz zwischen den Spalten dort angekommen ist.
   ============================================================ */

/* ---------- Der Bogen -------------------------------------------------
   Die Fläche der nächsten Sektion, aus der Mitte aufgezogen. Der
   Startzustand steht auch im CSS, damit vor dem ersten Frame von
   js/hero.js nichts aufblitzt. */
.bridge__panel {
  position: absolute;
  inset: 0;
  z-index: 3;
  background: var(--bg);
  will-change: clip-path;
  clip-path: inset(100% 28% 0% 28% round var(--srh-radius) var(--srh-radius) 0 0);
  -webkit-clip-path: inset(100% 28% 0% 28% round var(--srh-radius) var(--srh-radius) 0 0);
}

/* ---------- Responsiv -------------------------------------------------- */
@media (max-width: 900px) {
  /* Vier Angaben nebeneinander werden auf schmalen Bildschirmen zu
     Buchstabensalat. Zwei Zeilen zu zwei, mit Umbruch. */
  .hero__meta { flex-wrap: wrap; justify-content: flex-start; gap: 6px 24px; }
  .hero__meta li:last-child { margin-left: auto; }
}

@media (max-width: 560px) {
  .stage__pin { --hero-x: 16px; }

  /* Die Metazeile bricht auf zwei Reihen. */
  .hero__meta { font-size: 10px; letter-spacing: 0.12em; }

  /* Der Knopf steht hochkant über dem Slogan statt daneben: in 358 px
     passen beide nicht auf eine Zeile. */
  .hero__pause { bottom: calc(var(--hero-b) + 96px); }

}

/* ---------- Reduzierte Bewegung ---------------------------------------
   Kein Pin, kein Aufziehen, kein Video: der Hero ist eine gewöhnliche
   Sektion von einer Viewporthöhe mit dem Standbild, darunter steht die
   About folgt als gewöhnliche Sektion mit dem Porträt an seinem
   Platz. Die Reihenfolge bleibt also dieselbe, nur ohne Bewegung. */
@media (prefers-reduced-motion: reduce) {
  .stage { height: auto; background: var(--bg); }

  .stage__pin {
    position: static;
    height: auto;
    overflow: visible;
    background: transparent;
  }

  /* Bis das Standbild da ist, steht dahinter sein Verlauf: Zeilenmittel
     aus hero-waldlichter-still-1920 in Zehnerschritten. Ohne ihn stünde
     die helle Schrift kurz auf Creme. Den oberen Rand dunkelt der
     Schleier (.stage__tint) ohnehin ab, darauf liegt die Metazeile. */
  .stage__hero {
    position: relative;
    height: 100svh;
    background: linear-gradient(#48647d, #395064 10%, #495b6c 20%, #45515f 30%, #3f4750 40%, #3d4045 50%, #363739 60%, #363333 70%, #2d2c2c 80%, #2c2827 90%, #242322);
  }

  /* Der Bogen ist leer — ohne Aufziehen bleibt nur eine cremefarbene
     Platte übrig, die niemand braucht. Die Karte steht ohnehin an
     ihrem Platz in der Sektion darunter. */
  .bridge__panel { display: none; }

  .stage__video { display: none; }
  .stage__still { opacity: 1; }
  .stage__scene { background: none; }   /* Verlauf darunter statt Vorschau */
  .hero__pause { display: none; }   /* ohne Video nichts anzuhalten */
}
