/* NORDIX — Datenlinien (Leiterbahnen)
   Übernimmt die Bildmarke aus Björns Bestand — `assets/vector/Leiterbahn_*.svg`
   und die Flyer-Datalines — als Element der Seite.

   WARUM NACHGEZEICHNET STATT EINGEBUNDEN
   Die vorhandenen SVG haben feste Maße (512×507, 123×389) und feste Strichstärken
   von 10 bis 12 Einheiten. Eingebunden als <img> würden sie beim Skalieren
   entweder fett wie ein Balken oder fadenfein — und die Enden säßen dort, wo es
   das Seitenverhältnis gerade will, nicht dort, wo die Seite eine Kante hat.
   Deshalb wird die Geometrie im selben Vokabular (Senkrechte, 45°-Schrägen,
   Ringe als Lötaugen) zur Laufzeit auf die tatsächliche Größe der Stelle
   gezeichnet. Die Strichstärke bleibt dabei konstant, die Linie folgt der Kante.

   DIE PAKETE
   Auf jeder Bahn läuft ein kurzer heller Strich entlang: ein Datenpaket.
   Technisch ist das ein zweiter Pfad mit derselben Geometrie, dessen
   `stroke-dasharray` genau einen Strich ergibt und dessen `stroke-dashoffset`
   animiert wird. Der Lückenanteil ist doppelt so lang wie die Bahn — dadurch
   ist das Paket die halbe Zeit unterwegs und die halbe Zeit gar nicht da.
   Genau diese Pause verhindert, dass es hektisch wirkt.

   Das Tempo wird in Pixeln pro Sekunde vorgegeben, nicht als feste Dauer.
   Sonst liefe ein Paket auf einer kurzen Bahn schneller als auf einer langen. */

/* ---------- Stärke: die einzige Stellschraube ---------- */
:root{
  --lb-ruhe:.16;        /* Deckkraft der ruhenden Bahn */
  --lb-hell:.55;        /* Deckkraft des Pakets */
  --lb-breite:2px;      /* Strichstärke */
  --lb-tempo:52;        /* Pixel pro Sekunde */
  --lb-paketlaenge:52;  /* Länge des Pakets in Pixeln */
}
html[data-leiter="2"]{
  --lb-ruhe:.26;
  --lb-hell:.85;
  --lb-breite:2.6px;
  --lb-tempo:64;
  --lb-paketlaenge:64;
}

/* ---------- Die Ebene ---------- */
.leiter{
  position:absolute;z-index:0;
  pointer-events:none;
  /* Die Bahnen dürfen über den Rand ihrer Ebene hinauslaufen — sie sollen
     aussehen, als kämen sie von außerhalb der Seite. */
  overflow:visible;
}
.leiter svg{display:block;overflow:visible}

.leiter .bahn{
  fill:none;stroke:var(--orange);
  stroke-width:var(--lb-breite);
  stroke-linecap:round;stroke-linejoin:round;
  opacity:var(--lb-ruhe);
}
/* Lötauge */
.leiter .pad{
  fill:var(--bg);stroke:var(--orange);
  stroke-width:calc(var(--lb-breite) * .95);
  opacity:var(--lb-ruhe);
}

.leiter .paket{
  fill:none;stroke:var(--orange-hell,var(--orange-hell));
  stroke-width:var(--lb-breite);
  stroke-linecap:round;stroke-linejoin:round;
  opacity:var(--lb-hell);
  stroke-dasharray:var(--p-strich);
  animation:lb-lauf var(--p-dauer) linear infinite;
  animation-delay:var(--p-warten,0s);
}
/* Der Schein um das Paket: ein zweiter, breiterer Strich statt eines Filters.
   `drop-shadow` auf einem laufenden Pfad zwingt den Browser bei jedem Bild zu
   einer neuen Unschärfeberechnung — das kostet mehr als die ganze Animation. */
.leiter .paket.aura{
  stroke-width:calc(var(--lb-breite) * 3.6);
  opacity:calc(var(--lb-hell) * .16);
}

@keyframes lb-lauf{to{stroke-dashoffset:var(--p-weg)}}

/* Nur laufen lassen, was zu sehen ist. */
.leiter:not([data-sichtbar]) .paket{animation-play-state:paused}

/* ---------- Stellen ---------- */

/* Hero: die Bahnen kommen oben rechts herein und laufen unten aus dem Bild.
   `:not(.leiter)`, weil die Ebene selbst ein Kind des Heros ist — ohne den
   Ausschluss bekäme sie dieselbe z-index-Stufe wie der Text und läge davor. */
.hero{position:relative}
.hero > *:not(.leiter){position:relative;z-index:1}
.leiter-hero{top:0;right:0}

/* Ablauf: die Spur läuft in der Randspalte, in der schon die Kapitelnummer
   steht. Sie ist die einzige Stelle, an der die Linie etwas erzählt statt nur
   zu schmücken — sie führt an den drei Schritten entlang, und die Pakete laufen
   in Leserichtung mit. Die Beschriftung der Randspalte bleibt davor. */
#ablauf .sec{position:relative}
#ablauf .marg{z-index:2}
.leiter-spur{left:0}

/* Ruhige Sektionen: eine einzelne Bahn im freien Raum rechts neben der
   Lesespalte. Wie breit dieser Raum ist, entscheidet erst das Fenster —
   deshalb misst das Skript ihn, setzt `left` selbst und lässt die Bahn ganz
   weg, wenn der Raum zu schmal wird. */
.leiter-flanke{top:0}

/* Randspalte als Ausweichplatz. Nur gesetzt, wenn rechts nichts frei ist —
   seit die Karte über beide Spalten geht, ist das beim Einzugsgebiet der Fall.
   Lage und Höhe kommen aus dem Skript; hier bleibt nur zu sichern, dass die
   Kapitelbeschriftung darüber steht und nicht die Bahn über der Schrift.

   Nur `z-index`, ausdrücklich keine `position`: Die Randspalte ist ohnehin
   `position:sticky` und wandert beim Scrollen mit. Ein `position:relative`
   hier überschrieb das — auf dem Telefon rutschte die Beschriftung dadurch in
   die Überschrift darunter. */
#einzugsgebiet .marg{z-index:2}

/* ---------- Schmale Schirme ----------

   Bis Runde 57 stand hier `.leiter{display:none}`. Der Grund war richtig:
   Unter 1000 px klappt das Sektionsraster auf eine Spalte, die Randspalte
   verschwindet, der Text füllt die Breite — für eine Bahn IM Abschnitt ist da
   wirklich kein Platz.

   Die Folge war aber, dass eines von Björns Markenzeichen ausgerechnet auf dem
   Gerät fehlte, auf dem die meisten die Seite sehen. Also nicht mehr im
   Abschnitt, sondern in der Fuge dazwischen: Dort steht ohnehin Leerraum,
   gemessene 211 px am Telefon und 260 px am Tablet.

   Die Ebene liegt über die ganze Fensterbreite und beginnt oberhalb ihrer
   Sektion, mitten im Abstand — deshalb kommt `top` aus dem Skript und ist
   negativ. */
.leiter-fuge{left:0}

/* Hier stand kurz ein `main{overflow-x:clip}` gegen einen Querüberlauf, den
   die Bahnen verursachen könnten: Sie laufen bis an die Bildkante, und die
   runde Strichkappe ragt ein halbes Strichmaß darüber hinaus.

   Die Sperre ist nicht nötig und deshalb wieder draußen. Was über den Rand
   ragt, ist reine Farbe — die Ebene selbst ist genau so breit wie die Sektion,
   und Farbe außerhalb einer Box vergrößert die Seite nicht. Nachgemessen bei
   375, 820 und 1000 px, jeweils mit und ohne Sperre: Rollbreite gleich
   Fensterbreite, in allen sechs Fällen.

   Wichtiger als die eingesparte Zeile ist, was sie mitgebracht hätte:
   `overflow` auf `main` greift in die Eröffnung ein, in der das Videoband
   kurzzeitig `position:fixed` über dem ganzen Fenster steht. Eine Sperre gegen
   ein Problem, das es nicht gibt, ist teurer als das Problem. */

@media(prefers-reduced-motion:reduce){
  .leiter .paket{animation:none;opacity:0}
}

/* ---------- Lötaugen im Takt der Pakete (Variante d3) ----------
   Nur aktiv mit <html data-puls="an">. Der Startversatz kommt aus leiter.js
   und ist so gerechnet, dass das Aufleuchten mit dem Paket zusammenfällt.

   Die Größenänderung läuft über `transform`, nicht über den Radius `r`:
   `transform-box:fill-box` gibt dem Kreis seine eigene Box als Bezug, damit
   `scale` um den Mittelpunkt geschieht und nicht um den SVG-Ursprung. */
.leiter .pad[style*="--b-dauer"],
.leiter .pad-schein[style*="--b-dauer"]{
  transform-box:fill-box;transform-origin:center;
}
.leiter .pad[style*="--b-dauer"]{
  animation:lb-blitz var(--b-dauer) linear infinite;
  animation-delay:var(--b-warten,0s);
}

/* Der Schein liegt unter dem Lötauge und ist im Ruhezustand gar nicht da —
   er ist der Grund, warum das Aufleuchten als Leuchten gelesen wird und
   nicht bloß als Farbwechsel. */
.leiter .pad-schein{
  fill:var(--orange-hell,var(--orange-hell));stroke:none;
  opacity:0;
  animation:lb-schein var(--b-dauer) linear infinite;
  animation-delay:var(--b-warten,0s);
}

@keyframes lb-blitz{
  0%  {opacity:var(--lb-ruhe);stroke:var(--orange);transform:scale(1)}
  4%  {opacity:1;stroke:var(--orange-hell,var(--orange-hell));transform:scale(1.22)}
  20% {opacity:var(--lb-ruhe);stroke:var(--orange);transform:scale(1)}
  100%{opacity:var(--lb-ruhe);stroke:var(--orange);transform:scale(1)}
}
@keyframes lb-schein{
  0%  {opacity:0;transform:scale(1)}
  4%  {opacity:calc(var(--lb-hell) * .45);transform:scale(1.3)}
  26% {opacity:0;transform:scale(2.6)}
  100%{opacity:0;transform:scale(1)}
}

.leiter:not([data-sichtbar]) .pad,
.leiter:not([data-sichtbar]) .pad-schein{animation-play-state:paused}

@media(prefers-reduced-motion:reduce){
  .leiter .pad,.leiter .pad-schein{animation:none}
  .leiter .pad-schein{display:none}
}
