/* Broschi Digalytics – Baustein „Startampel“ (Hauptmoment im Kopf) und Fortschritt im Renntag.
   Gehört zu assets/motion/lichter.js. Eigener Namensraum: Klassen „lx-…“, Variablen „--lx-…“.
   Haken: [data-lights] [data-lamp] [data-lights-toggle] [data-wall] [data-wall-screen] [data-wall-card] [data-points]
          [data-timeline] [data-station]; Gestalt der Startampel (SVG) und der Schiene im Renntag aus stage.css.
   Grundsatz: Ruhezustand = Endzustand. Der Vorzustand ist sichtbar: Die Tabelle steht mit Namen und den Punkten
   vor Lauf 4 da, die Monitore (OBS-Bild, Cockpit) sind aus (abgedunkelt, Zeilenraster), die Bauchbinde ist nicht
   auf Sendung. Animiert werden nur die Ampel-Leuchten, Punkte, das Einschalten der Monitore und die Driver Card.
   Vorzustand vor dem Skript: html.lx-pre (setzt die Seite im <head>); er löst sich nach 3,6 s von selbst auf
   (lx-failsafe), falls lichter.js nicht läuft. */

:root {
  --lx-ease: cubic-bezier(0.16, 1, 0.3, 1);
  --lx-power: 520ms;     /* Monitor schaltet ein */
  --lx-stagger: 90ms;    /* Versatz zwischen den Monitoren */
  --lx-back: 160ms;      /* Übergang in den Vorzustand (Übernahme aus html.lx-pre) */
  --lx-card-at: 240ms;   /* Driver Card: Akzentlinie nach „Lichter aus“ */
  --lx-gain-at: 120ms;   /* +25/+18/… nach „Lichter aus“ */
  --lx-off: brightness(0.25) saturate(0.6);
  /* Startampel-LEDs */
  --lx-led-on: 90ms;     /* Einschalten */
  --lx-led-off: 240ms;   /* Ausschalten mit Nachglühen (sichtbar ca. 150 ms) */
  --lx-core-off: 130ms;  /* heißer Kern erlischt zuerst */
  --lx-afterglow: cubic-bezier(0.2, 0.5, 0.4, 1); /* Rest nach 60 ms 46 %, nach 100 ms 24 %, nach 150 ms 8 % */
}

/* ================= Boxenmauer ================= */

/* Bildflächen werden Bezugsrahmen für das Zeilenraster (ändert nichts am Aussehen) */
[data-wall] [data-wall-screen] { position: relative; isolation: isolate; }
[data-wall] [data-points] { position: relative; }
/* Ruhewert der Bauchbinde als inset() statt „none“, damit sich Vorzustand und Ruhe ineinander überführen lassen;
   der Rand von 24 px schneidet nichts ab */
[data-wall] [data-wall-card] { clip-path: inset(-24px); }

/* Monitore = Bildflächen ohne Tabelle (OBS-Bild mit Driver Card, Cockpit-Foto). Ihr Zeilenraster liegt immer bereit
   (unsichtbar), damit es beim Ausschalten weich einblenden kann. */
[data-wall] [data-wall-screen]:not(:has([data-points]))::after {
  content: ""; position: absolute; inset: 0; z-index: 3; border-radius: inherit; pointer-events: none; opacity: 0;
  background: repeating-linear-gradient(180deg, rgba(2, 9, 18, 0.62) 0 1px, rgba(2, 9, 18, 0) 1px 3px);
}
[data-wall] [data-wall-screen]:has(> img:only-child)::after { border-radius: var(--r-md); }
/* OBS-Monitor: Ohne Karte zeigt er nur seine dunkle Fläche. Im Standby wirkt er deshalb wie ein eingeschalteter
   Monitor ohne Signal (Fläche, schwacher Schein in der Mitte, Zeilenraster) und wird weniger abgedunkelt: nie schwarz.
   Die Schicht blendet beim Einschalten mit dem Zeilenraster aus. */
[data-wall] [data-wall-screen]:has([data-wall-card]) { --lx-off: brightness(0.6) saturate(0.7); }
[data-wall] [data-wall-screen]:has([data-wall-card])::after {
  background: repeating-linear-gradient(180deg, rgba(2, 9, 18, 0.62) 0 1px, rgba(2, 9, 18, 0) 1px 3px),
              radial-gradient(ellipse 60% 55% at 50% 50%, rgba(0, 212, 255, 0.14), rgba(0, 212, 255, 0) 72%), var(--surface-2);
}

/* Punkte-Zeichen je Zeile (+25, +18 …) aus data-gain, nur während „live“; für Screenreader stumm.
   Sitzt 4 px links vor der Zahl (--lx-gx misst lichter.js), damit es den Teamnamen nicht überdeckt. */
[data-wall].lx-live [data-points]::before {
  content: attr(data-gain); content: attr(data-gain) / "";
  position: absolute; top: 50%; right: var(--lx-gx, 29px); transform: translateY(-50%);
  padding: 3px 3px 2px; border-radius: 4px; border: 1px solid rgba(52, 211, 153, 0.5); background: var(--bg-deep);
  color: var(--success); font: 700 12px/1 var(--font-display); letter-spacing: 0.03em; white-space: nowrap; pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  /* Vorzustand: ab dem ersten Bild (html.lx-pre, bis lichter.js übernimmt) und als Klasse .lx-standby.
     Übergänge starten beim aktuellen Wert, deshalb blitzt bei der Übernahme aus html.lx-pre nichts auf. */
  html.lx-pre:not(.lx-ready) [data-wall] [data-wall-screen]:not(:has([data-points])),
  [data-wall].lx-standby [data-wall-screen]:not(:has([data-points])) {
    filter: var(--lx-off); transition: filter var(--lx-back) var(--lx-ease);
  }
  html.lx-pre:not(.lx-ready) [data-wall] [data-wall-screen]:not(:has([data-points]))::after,
  [data-wall].lx-standby [data-wall-screen]:not(:has([data-points]))::after {
    opacity: 1; transition: opacity var(--lx-back) var(--lx-ease);
  }
  html.lx-pre:not(.lx-ready) [data-wall] [data-wall-card],
  [data-wall].lx-standby [data-wall-card] {
    clip-path: inset(0 100% 0 0); transition: clip-path var(--lx-back) var(--lx-ease);
  }
  /* Sicherheitsnetz: läuft lichter.js nicht, sind die Monitore nach 3,6 s von selbst an */
  html.lx-pre:not(.lx-ready) [data-wall] [data-wall-screen]:not(:has([data-points])) { animation: lx-failsafe-mon 3.6s steps(1, end) both; }
  html.lx-pre:not(.lx-ready) [data-wall] [data-wall-screen]:not(:has([data-points]))::after { animation: lx-failsafe-scan 3.6s steps(1, end) both; }
  html.lx-pre:not(.lx-ready) [data-wall] [data-wall-card] { animation: lx-failsafe-card 3.6s steps(1, end) both; }

  /* „Lichter aus“: Monitore schalten gestaffelt ein (kurzes Aufhellen, Zeilenraster verschwindet) */
  [data-wall].lx-live [data-wall-screen]:not(:has([data-points])) {
    animation: lx-power var(--lx-power) var(--lx-ease) calc(var(--lx-i, 0) * var(--lx-stagger)) both;
  }
  [data-wall].lx-live [data-wall-screen]:not(:has([data-points]))::after {
    animation: lx-scan-off 380ms var(--lx-ease) calc(var(--lx-i, 0) * var(--lx-stagger)) both;
  }
  /* Driver Card als Bauchbinde: erst die Akzentlinie (linke Kante der Karte), dann die Fläche */
  [data-wall].lx-live [data-wall-card] {
    animation: lx-card-line 200ms var(--lx-ease) var(--lx-card-at) both,
               lx-card-plate 420ms var(--lx-ease) calc(var(--lx-card-at) + 180ms) forwards;
  }
  [data-wall].lx-live [data-points]::before { animation: lx-gain 760ms var(--lx-ease) calc(var(--lx-gain-at) + var(--lx-r, 0) * 60ms) both; }

  /* Startampel: Die Leuchten verhalten sich wie LEDs. Einschalten sehr kurz (--lx-led-on), Ausschalten mit
     Nachglühen (--lx-led-off); der heiße, fast weiße Kern erlischt zuerst (--lx-core-off). Nur Deckkraft wird
     geblendet; welche Leuchte an ist, setzt lichter.js (Zeitgeber mit einem Zustand, keine CSS-Schleife). */
  [data-lights] .lx-lit { transition: opacity var(--lx-led-off) var(--lx-afterglow); }
  [data-lights] .lx-core { transition: opacity var(--lx-core-off) var(--lx-afterglow); }
  [data-lights] [data-lamp].is-on .lx-r :is(.lx-lit, .lx-core),
  [data-lights].lx-go .lx-g :is(.lx-lit, .lx-core) { transition: opacity var(--lx-led-on) var(--lx-ease); }

  /* Anhalte-Schalter: gibt beim Drücken nach (Form in stage.css) */
  [data-lights-toggle] { transition: transform 160ms var(--lx-ease), color 150ms var(--lx-ease), border-color 150ms var(--lx-ease); }
  [data-lights-toggle]:active { transform: scale(0.97); }
}

@media (prefers-reduced-motion: reduce) {
  /* Startampel: keine Schleife; lichter.js stellt sie fest auf Grün, der Schalter entfällt */
  [data-lights-toggle] { display: none; }
  /* Ruhige Fassung der Boxenmauer. Bei reduzierter Bewegung steht sie sonst sofort im Endzustand; diese Regeln
     greifen nur, falls die Einstellung wechselt, während die Mauer gerade live geht (Monitore blenden sanft) */
  [data-wall].lx-standby [data-wall-screen]:not(:has([data-points])) { filter: brightness(0.45) saturate(0.7); transition: filter 150ms var(--lx-ease); }
  [data-wall].lx-standby [data-wall-screen]:not(:has([data-points]))::after { opacity: 1; transition: opacity 150ms var(--lx-ease); }
  [data-wall].lx-live [data-wall-screen]:not(:has([data-points])) { animation: lx-calm-on 200ms var(--lx-ease) both; }
  [data-wall].lx-live [data-wall-screen]:not(:has([data-points]))::after { animation: lx-scan-off 200ms var(--lx-ease) both; }
  [data-wall].lx-live [data-points]::before { animation: lx-gain-calm 1000ms var(--lx-ease) both; }
}

@keyframes lx-failsafe-mon { from { filter: var(--lx-off); } to { filter: none; } }
@keyframes lx-failsafe-scan { from { opacity: 1; } to { opacity: 0; } }
@keyframes lx-failsafe-card { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes lx-power {
  0% { filter: var(--lx-off); }
  35% { filter: brightness(1.35) saturate(1.1); }
  100% { filter: none; }
}
@keyframes lx-scan-off { from { opacity: 1; } to { opacity: 0; } }
@keyframes lx-calm-on { from { filter: brightness(0.45) saturate(0.7); } to { filter: none; } }
@keyframes lx-card-line {
  from { clip-path: inset(0 calc(100% - var(--lx-edge, 4px)) 100% 0); }
  to { clip-path: inset(0 calc(100% - var(--lx-edge, 4px)) 0 0); }
}
@keyframes lx-card-plate {
  from { clip-path: inset(0 calc(100% - var(--lx-edge, 4px)) 0 0); }
  to { clip-path: inset(0 0 0 0); }
}
/* Ein: 20 % (≈150 ms), Halten, Aus: 18 % (≈140 ms) – Ausgang schneller als Eingang */
@keyframes lx-gain {
  0% { opacity: 0; transform: translate(6px, -50%); }
  20% { opacity: 1; transform: translate(0, -50%); }
  82% { opacity: 1; transform: translate(0, -50%); }
  100% { opacity: 0; transform: translate(-3px, -50%); }
}
@keyframes lx-gain-calm { 0% { opacity: 0; } 15% { opacity: 1; } 85% { opacity: 1; } 100% { opacity: 0; } }

/* ================= Renntag: Fortschrittslinie ================= */

/* --lx-on: 0 = Station noch nicht erreicht, 1 = erreicht. Ohne Modus bleibt es 1 (= Gestalt der Bühne). */
@property --lx-on { syntax: "<number>"; inherits: true; initial-value: 1; }

/* Füllung liegt deckungsgleich auf der grauen Schiene (.rail::before der Bühne), unter Marke und Tageswechsel */
html.js [data-timeline] [data-station] .rail::after {
  content: ""; position: absolute; left: 0; right: 0; top: 14px; height: 2px; pointer-events: none;
  background: var(--cyan); transform: scaleX(0); transform-origin: 0 50%;
}
html.js [data-timeline] [data-station]:last-child .rail::after { background: linear-gradient(90deg, var(--cyan) 60%, transparent); }
html.js [data-timeline] [data-station] .mk,
html.js [data-timeline] [data-station] .brk { z-index: 1; }
/* Erreicht: Marke und Uhrzeit voll; noch nicht erreicht: zurückgenommen, aber lesbar (Uhrzeit ≥ 5,9:1) */
html.js [data-timeline] [data-station] .mk { opacity: calc(0.35 + 0.65 * var(--lx-on)); }
html.js [data-timeline] [data-station] .t { opacity: calc(0.55 + 0.45 * var(--lx-on)); }

/* Senkrechte Schiene ab 980 px (wie stage.css) */
@media (max-width: 980px) {
  html.js [data-timeline] [data-station] .rail::after { left: 11px; right: auto; top: 6px; bottom: -26px; width: 2px; height: auto; transform: scaleY(0); transform-origin: 50% 0; }
  html.js [data-timeline] [data-station]:last-child .rail::after { background: linear-gradient(180deg, var(--cyan) 60%, transparent); }
}

/* Modus A: CSS-Scroll-Timeline. Waagerecht läuft die Linie über alle Stationen, während der Zeitplan
   von 85 % auf 40 % der Fensterhöhe wandert (Spalten 1 : 1,08 : 1 : 1,22 wie stage.css);
   senkrecht folgt die Linie einer Leselinie bei 60 % der Fensterhöhe. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    html.js [data-timeline] { view-timeline: --lx-rd block; }
    html.js [data-timeline] [data-station] { view-timeline: --lx-st block; animation: lx-reach linear both; animation-timeline: --lx-rd; }
    html.js [data-timeline] [data-station] .rail::after { animation: lx-fill-x linear both; animation-timeline: --lx-rd; }
    html.js [data-timeline] [data-station]:nth-child(1) { animation-range: cover 15vh cover 16.5vh; }
    html.js [data-timeline] [data-station]:nth-child(2) { animation-range: cover 25.47vh cover 26.97vh; }
    html.js [data-timeline] [data-station]:nth-child(3) { animation-range: cover 36.77vh cover 38.27vh; }
    html.js [data-timeline] [data-station]:nth-child(4) { animation-range: cover 47.23vh cover 48.73vh; }
    html.js [data-timeline] [data-station]:nth-child(1) .rail::after { animation-range: cover 15vh cover 25.47vh; }
    html.js [data-timeline] [data-station]:nth-child(2) .rail::after { animation-range: cover 25.47vh cover 36.77vh; }
    html.js [data-timeline] [data-station]:nth-child(3) .rail::after { animation-range: cover 36.77vh cover 47.23vh; }
    html.js [data-timeline] [data-station]:nth-child(4) .rail::after { animation-range: cover 47.23vh cover 60vh; }
    @media (max-width: 980px) {
      html.js [data-timeline] [data-station]:nth-child(n) { animation-timeline: --lx-st; animation-range: cover 40vh cover 42vh; }
      html.js [data-timeline] [data-station]:nth-child(n) .rail::after { animation-name: lx-fill-y; animation-timeline: --lx-st; animation-range: cover 40vh cover calc(100% - 60vh); }
    }
  }
}
@keyframes lx-reach { from { --lx-on: 0; } to { --lx-on: 1; } }
@keyframes lx-fill-x { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes lx-fill-y { from { transform: scaleY(0); } to { transform: scaleY(1); } }

/* Modus B (ohne Scroll-Timeline oder bei reduzierter Bewegung): lichter.js setzt .lx-rd-io und markiert
   erreichte Stationen mit .lx-reached; waagerecht (.lx-rd-h) läuft die Linie dann einmal durch. */
html.js [data-timeline].lx-rd-io [data-station] { --lx-on: 0; transition: --lx-on 150ms var(--lx-ease); }
html.js [data-timeline].lx-rd-io [data-station].lx-reached { --lx-on: 1; transition: --lx-on 260ms var(--lx-ease) var(--lx-at, 0ms); }
html.js [data-timeline].lx-rd-io [data-station] .rail::after { transition: transform 150ms var(--lx-ease); }
html.js [data-timeline].lx-rd-io [data-station].lx-reached .rail::after { transform: none; transition: transform var(--lx-seg, 380ms) var(--lx-seg-ease, var(--lx-ease)) var(--lx-at, 0ms); }
html.js [data-timeline].lx-rd-h [data-station] { --lx-at: calc(var(--lx-si, 0) * 260ms); --lx-seg: 260ms; --lx-seg-ease: linear; }
html.js [data-timeline].lx-rd-h [data-station]:last-child { --lx-seg-ease: var(--lx-ease); }
/* Ruhige Fassung: Linie wächst nicht, sie blendet je erreichter Station ein */
html.js [data-timeline].lx-rd-calm [data-station] .rail::after,
html.js [data-timeline].lx-rd-calm [data-station].lx-reached .rail::after { transform: none; opacity: 0; transition: opacity 150ms var(--lx-ease); }
html.js [data-timeline].lx-rd-calm [data-station].lx-reached .rail::after { opacity: 1; transition: opacity 200ms var(--lx-ease); }
