/*
  ╔══════════════════════════════════════════════════════════════════════╗
  ║  PROTOKOLL – was Claude zuletzt geändert hat (13.10.2026)            ║
  ║  Gleiche Nummern wie im HTML. Mit Strg + F nach "[Nummer]" suchen.   ║
  ║                                                                      ║
  ║  [1] LEISTUNG: Himmel dreht sich als Ganzes, Filter nur 1x gerechnet ║
  ║  [2] LEISTUNG: Himmel-Filter mit weniger Wolkenschichten (im HTML)   ║
  ║  [3] LEISTUNG: Sterne-Filter + statische Ebenen entlastet            ║
  ║  [4] Logo: Schrift + Stacheln unscharf und verzerrt                  ║
  ║  [5] Jugendstil-Muster unscharf und verzerrt                         ║
  ║  [6] Intro: Logo-Teile fliegen magnetisch in die Mitte               ║
  ║  [7] Intro: Jugendstil-Muster wird in die Mitte gesaugt              ║
  ║  [8] Fischauge: größerer Filterbereich (im HTML)                     ║
  ║                                                                      ║
  ║  RUNDE 2 (nach deinem Feedback):                                     ║
  ║  [9]  Himmel-Filter (Kopie, halbe Stärke) auf Schrift + Stacheln     ║
  ║  [10] Muster: Filter + Unschärfe fest eingebrannt (jugendstil.png)   ║
  ║  [11] Muster-Intro über background-size statt scale                  ║
  ║  [12] Logo-Kasten verkleinert → weniger Mischfläche                  ║
  ║  [13] Unnötige eigene Ebenen (will-change) entfernt                  ║
  ║                                                                      ║
  ║  RUNDE 3 (Firefox-Messung):                                          ║
  ║  [14] Himmel als eingebranntes Bild (.himmel-bild), SVG versteckt    ║
  ║  [15] Logo: Intro ohne SVG-Filter, danach Überblendung zu logo.webp  ║
  ║  [16] Ganze Seite invertiert (.invertieren, ganz unten im CSS)       ║
  ║  [17] Fischauge raus, neuer Filter #zerreissen (im HTML, im Bild)    ║
  ║  [18] logo.webp neu – mit deinen BASEINTHEWINE-Echos                 ║
  ║  [19] Schärfer: neue Bilder, weniger blur                            ║
  ║  [20] Jugendstil-Muster treibt (.jugendstil, Keyframes treiben)      ║
  ║  [21] Logo wabert + Nachbild (.logo-bild, .logo-geist)               ║
  ║  [22] Himmel-Tunnel (.himmel-fluss)                                  ║
  ╚══════════════════════════════════════════════════════════════════════╝
*/

/*
  ╔══════════════════════════════════════════════════════════════════════╗
  ║  NEU IM SPICKZETTEL: LEISTUNG – warum eine Seite laggt               ║
  ║                                                                      ║
  ║  Der Browser malt jede Sekunde bis zu 60 Bilder. Für jedes Bild      ║
  ║  prüft er: Hat sich etwas verändert? Nur das wird neu gemalt.        ║
  ║                                                                      ║
  ║  BILLIG  → transform, translate, rotate, scale, opacity              ║
  ║            (die Grafikkarte verschiebt nur ein fertiges Bild)        ║
  ║  TEUER   → alles, was in einem Filter (url(#…), blur) steckt UND     ║
  ║            sich bewegt: dann muss der Filter JEDES Bild neu rechnen. ║
  ║                                                                      ║
  ║  Tricks, die hier benutzt werden:                                    ║
  ║  steps(n)       → Animation springt nur n-mal statt 60x pro Sekunde  ║
  ║  will-change    → "dieses Element bekommt eine eigene Ebene":        ║
  ║                   einmal gemalt, danach nur noch verschoben.         ║
  ║                   Sparsam benutzen, jede Ebene kostet Speicher!      ║
  ║  Unsichtbares   → auch durchsichtige Elemente kosten Rechenzeit.     ║
  ║  Trip ohne Lag  → Bewegung NUR mit transform/translate/rotate/scale  ║
  ║                   und opacity auf fertigen Bildern. Die Grafikkarte  ║
  ║                   schiebt dann nur Bilder herum. [20] [21] [22]      ║
  ║  Nahtlose Schleife → Ein Kachelmuster genau um EINE Kachelgröße      ║
  ║                   verschieben: Ende sieht aus wie Anfang. [20]       ║
  ║  Einbrennen     → Ein Filter, der sich nie ändert, kann vorher       ║
  ║                   in ein Bild gerechnet werden. Ein Bild anzeigen    ║
  ║                   kostet fast nichts, ein Live-Filter viel. [10]     ║
  ║  Browser sind verschieden! Chrome merkt sich einen fertig            ║
  ║                   gerechneten Filter, Firefox rechnet ihn oft neu.   ║
  ║                   Immer in ALLEN Browsern testen, die du nutzt. [14] ║
  ║  scale beim Laden → Startet etwas 4x so groß, malt der Browser es    ║
  ║                   evtl. auch 4x so groß = 16x so viele Pixel. [11]   ║
  ║                                                                      ║
  ║  NEU IM SPICKZETTEL: EIGENE VARIABLEN PRO ELEMENT                    ║
  ║  style="--x: 40vw"  im HTML  →  var(--x)  im CSS                     ║
  ║  So benutzen viele Elemente DIESELBE Animation, aber jedes mit       ║
  ║  eigenen Werten (eigener Startpunkt, eigene Verzögerung).            ║
  ║  calc(var(--x) * -0.02) → mit Variablen rechnen                      ║
  ╚══════════════════════════════════════════════════════════════════════╝
*/

/*
  ╔══════════════════════════════════════════════════════════════════════╗
  ║  SELEKTOREN UND VERWANDTSCHAFT – kurzer Spickzettel                  ║
  ║                                                                      ║
  ║  .a .b    (Leerzeichen)  → .b irgendwo IN .a (Kind, Enkel, Urenkel…)  ║
  ║  .a > .b  (Pfeil)        → .b ist DIREKTES KIND von .a               ║
  ║  .a.b     (ohne Leerz.)  → EIN Element mit beiden Klassen            ║
  ║  .a + .b  (Plus)         → .b ist der DIREKTE NACHFOLGE-GESCHWISTER   ║
  ║  *                       → alle Elemente                             ║
  ║  :hover, :nth-child(…)   → Pseudo-KLASSE: Zustand / Position         ║
  ║  ::before, ::after       → Pseudo-ELEMENT: erzeugt ein neues Kind    ║
  ║                                                                      ║
  ║  Vererbung: Manche Werte (color, font-family, CSS-Variablen …)       ║
  ║  geben Eltern automatisch an alle Nachkommen weiter.                 ║
  ║  Andere (position, width, border …) werden NICHT vererbt.            ║
  ╚══════════════════════════════════════════════════════════════════════╝
*/

    /* ============ 1. FARBEN ============
       Zurück zu hartem Schwarz-Weiß. Das "Engelhafte" kommt vom Licht, nicht von Farbe. */

    /* :root = das <html>-Element = die Wurzel des Stammbaums.
       Variablen hier gelten für ALLE Nachkommen, also für die ganze Seite. */
    :root {
      --schwarz: #000000;
      --weiss:   #f4f4f0;
      --grau:    #777773;
      --nebel:   #2a2a28;

      box-sizing: border-box;
      padding-top: env(safe-area-inset-top, 0px);
      padding-bottom: env(safe-area-inset-bottom, 0px);
    }
    @media (prefers-color-scheme: dark) {
      :root:not([data-theme="light"]) { --schwarz: #000000; }
    }
    :root[data-theme="dark"] { --schwarz: #000000; }

    /* * = alle Elemente, *::before/*::after = ihre Pseudo-Kinder.
       box-sizing: inherit → jedes Element übernimmt den Wert von seinem ELTERNTEIL.
       So "wandert" border-box von :root durch den ganzen Stammbaum nach unten. */
    *, *::before, *::after { box-sizing: inherit; margin: 0; padding: 0; }
    html { scroll-padding-top: env(safe-area-inset-top, 0px); }

    /* body = Kind von html. color und font-family werden an ALLE Nachkommen vererbt –
       deshalb ist jeder Text auf der Seite automatisch weiß und in Special Elite. */
    body {
      background: var(--schwarz);
      color: var(--weiss);
      font-family: "Special Elite", "Courier New", monospace;
      font-size: 1.05rem;
      line-height: 1.6;
      overflow-x: hidden;
    }


    /* ============ 2. HERO: alle Ebenen liegen übereinander ============
       Reihenfolge von hinten nach vorne:
       Himmel (verzerrtes Licht) → ferne Berge → nahe Berge → Text */

    /* position: relative macht .hero zum BEZUGSPUNKT: Jedes absolut positionierte
       Kind, Enkel usw. darin misst left/top/inset ab dem Rand von .hero. */
    .hero {
      position: relative;
      height: 100vh;
      min-height: 620px;
      overflow: hidden;            /* alles, was über den Rand ragt, wird abgeschnitten */
      background: radial-gradient(circle at 50% 44%, #d9d9d2 0%, #6c6c68 18%, #1b1b1a 45%, #000 75%);
    }

    /* WICHTIGSTE ZEILE FÜR DEN STAMMBAUM:
       ">" = nur DIREKTE KINDER von .hero.
       Trifft: .chaos, .himmel, .berge.fern, .nebel, beide .staub, .sterne-verzerrt
       Trifft NICHT: die img.mitte (Enkel), die polygons, path usw. */
    .hero > * { position: absolute; }

    /* ======================================================================================================== */
    /* =======================================    Chaosstern  ================================================= */                                   
    /* ======================================================================================================== */
    /* ======================================================================================================== */

    /* Trifft alle img.mitte = ENKEL von .hero (Kinder von .sterne-verzerrt). */
    .mitte {
    position: static;   /* statt absolute: bezieht sich auf das Browserfenster */
                        /* ACHTUNG: "center" gibt es nicht → Zeile wird ignoriert → position bleibt "static".
                           Gültig sind: static, relative, absolute, fixed, sticky.
                           Folge: left, top und z-index unten wirken bei .mitte NICHT. */
    left: 50%;
    top: 50%;
    padding: 1px;
    max-width: 300px;                
    z-index: 10;
    opacity: 0.01;
    animation: chaos 0s linear infinite, drehen 20s linear infinite, steigen 20s linear infinite;   /* … nur DIESE gilt (Kaskade: die letzte gewinnt).
                                                    TIPP: Mehrere Animationen = EINE Zeile, mit Komma getrennt:
                                                    animation: chaos 20s ease-in-out infinite, drehen 2s linear infinite; */
   /* ACHTUNG: Diese drei Zeilen stehen INNERHALB von .mitte { … } (die schließende Klammer kommt erst danach).
      Das nennt man Verschachtelung (Nesting). Der Browser liest sie als ".mitte .sterne-verzerrt img…",
      also "Bilder in .sterne-verzerrt, das IN einem .mitte steckt" → trifft nichts.
      Außerdem: "nav-down" ist keine gültige Eigenschaft, und left/right wirken bei position: static nicht. */
   .sterne-verzerrt img:nth-child(2n) { left: 2%; right: 90%; nav-down: -20%; }
   .sterne-verzerrt img:nth-child(3n) { left: 10%; right: 50%; }
   .sterne-verzerrt img:nth-child(4n) { left: 30%; right: 70%; }
    }

   .sterne-verzerrt img:nth-child(2n) { animation-delay: -5s; }
   .sterne-verzerrt img:nth-child(3n) { animation-delay: -11s; }
   .sterne-verzerrt img:nth-child(4n) { animation-delay: -19s; }
   

    @keyframes chaos {
    0%   { translate: 50 50; }
    20%  { translate: 15vw -12vh; }    /* nach rechts oben */
    30%  { translate: 56vw 23vh; }
    40%  { translate: -12vw 10vh; }    /* nach links unten */
    60%  { translate: 80vw 60vh; }     /* nach rechts unten */
    80%  { translate: -15vw -10vh; }   /* nach links oben */
    100% { translate: 50 50; }           /* zurück zum Start */
    }

   
    .sterne-verzerrt {
      inset: 0; 
      pointer-events: none;
      /* GEÄNDERT [3]: Filter ausgeschaltet (auskommentiert, nicht gelöscht).
         Grund: Deine Sterne sind gerade praktisch unsichtbar – 0.01 (.mitte) × 0.11 (style im HTML)
         × 0.40 (dieser Behälter) = 0.0004 Deckkraft. Trotzdem hat der Browser für sie JEDES Bild einen
         bildschirmgroßen Verzerrungsfilter gerechnet, weil sie sich ständig bewegen.
         Wenn du die Sterne wieder sichtbar machst und den Filter willst: Zeile wieder einschalten. */
      /* filter: url(#sterne-verzerrt); */
    }
    /* TIPP: Hier fehlt eine Regel für den Behälter, damit dein Filter wirkt, z.B. eine
       Regel für .sterne-verzerrt mit inset: 0; pointer-events: none; und
       filter: url(#sterne-verzerrt);  – der Name in url(#…) ist die id aus den <defs>. */

    /* TIPP: Damit die Sterne nicht im Gleichschritt laufen: :nth-child + negatives
       animation-delay, z.B. für jedes 2. und jedes 3. Kind von .sterne-verzerrt. */
    
    /* ======================================================================================================== */
    /* =======================================    Chaosstern  ================================================= */                                   
    /* ======================================================================================================== */
    /* ======================================================================================================== */


    /* ======================================================================================================== */
    /* =============================    Nebel, zieht starr ohne bewegung    =================================== */                                   
    /* ======================================================================================================== */
    /* ======================================================================================================== */

    /* .nebel = KIND von .hero → hat schon position: absolute.
       inset: 0 = top, right, bottom, left alle 0 → füllt den ganzen Elternteil (.hero). */
    .nebel {
    inset: 0;
    z-index: 1;                 /* über fernen Bergen, unter der Kugel (2) */
    pointer-events: none;
    opacity: 0.25;
    mix-blend-mode: screen;     /* macht nur heller, nie dunkler */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1200' height='600'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.004 0.008' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3C/svg%3E");
    background-size: 1200px 600px;
    /* ENTFERNT [13]: will-change war hier unnötig – der Nebel bewegt sich nicht, eine eigene Ebene kostet nur Grafikspeicher. */
    }
    /* Hinweis: Wird gerade nicht benutzt, weil .nebel keine animation-Zeile mehr hat
       (passt zu deiner Überschrift "starr"). Kann bleiben oder weg. */
    @keyframes nebelziehen {
    to { background-position: 1200px 0; }
    }
     /* ======================================================================================================== */
    /* =============================    Nebel, zieht starr ohne bewegung    =================================== */                                   
    /* ======================================================================================================== */
    /* ======================================================================================================== */




    /* ======================================================================================================== */
    /* ========================     Lichtpartikel welche nach oben steigen    ================================= */                                   
    /* ======================================================================================================== */
    /* ======================================================================================================== */

    /* Trifft BEIDE Staub-divs (beide haben die Klasse staub). Beide = KIND von .hero. */
        .staub {
    top: 0;
    left: 0;
    width: 2px;
    height: 2px;
    border-radius: 50%;
    z-index: 1;
    pointer-events: none;
    box-shadow:                      /* jeder Schatten = eine Kopie des Punktes, verschoben um x y */
        120px 300px #fff,          90vw 120px rgba(255,255,255,0.6),
        30vw 520px #fff,           70vw 700px rgba(255,255,255,0.4),
        15vw 80px rgba(255,255,255,0.7),   55vw 420px #fff,
        82vw 560px rgba(255,255,255,0.5),  42vw 650px rgba(255,255,255,0.8),
        8vw 700px #fff,            63vw 250px rgba(255,255,255,0.5),
        95vw 480px #fff,           25vw 380px rgba(255,255,255,0.6);
    animation: steigen 40s linear infinite;
    }
    /* Trifft nur das zweite Staub-div (hat staub UND zwei).
       Erbt alles von .staub (auch box-shadow und die Animation) und ändert nur ein paar Werte. */
    .staub.zwei {
    width: 3px;
    height: 3px;
    left: 6vw;
    top: 200px;
    filter: blur(1px);
    animation-duration: 25s;         /* ändert NUR die Dauer, Name/linear/infinite bleiben von .staub */
    }
    @keyframes steigen {
    0%   { translate: 0 60vh;   opacity: 0; }
    10%  { opacity: 1; }
    90%  { opacity: 1; }
    100% { translate: 0 -80vh;  opacity: 0; }
    80% { translate: 1; }
    50% { translate: 1; }
    }

    /* ======================================================================================================== */
    /* ========================     Lichtpartikel welche nach oben steigen    ================================= */                                   
    /* ======================================================================================================== */
    /* ======================================================================================================== */

    /* ---- Ebene 1: der verzerrte Himmel ----
       Die Strahlen drehen sich langsam. Weil der Verzerrungs-Filter
       stillsteht, "wabern" sie beim Durchlaufen – verstörend unruhig. */

    /* NEU [14]: Das SVG ist nur noch die Vorlage für himmel.webp – unsichtbar und ohne Größe.
       Nicht display: none, weil manche Browser (v.a. Firefox) Filter aus einem display:none-SVG
       nicht mehr finden. Dein Sterne-Filter #sterne-verzerrt steckt auch in diesem SVG. */
    .himmel {
      visibility: hidden;
      width: 0;
      height: 0;
    }

    /* GEÄNDERT [14]: Diese Regel galt vorher für svg.himmel, jetzt für das Bild img.himmel-bild.
       Inhalt ist gleich geblieben: großes Quadrat, das sich als Ganzes dreht.
       overflow: hidden von .hero schneidet alles ab, was übersteht. */
    .himmel-bild {
      max-width: none;          /* NEU [14]: Bilder dürfen sonst oft nicht breiter als ihr Elternteil werden */
      /* GEÄNDERT [1]: Der Himmel ist jetzt ein großes QUADRAT, das sich als Ganzes dreht.
         Warum so groß? Ein gedrehtes Rechteck lässt an den Ecken Lücken. Ein Quadrat, dessen Seite
         mindestens so lang ist wie die Bildschirm-Diagonale, deckt in JEDER Drehung alles ab.
         Die Diagonale ist höchstens ca. 1,42 × die längere Seite → 145vmax (vmax = längere Fensterseite).
         left/top: 50 % minus die halbe Größe → die Mitte des Quadrats liegt genau in der Mitte des Hero.
         (Nicht mit translate: -50% zentriert, weil die "reissen"-Animation translate selbst benutzt.) */
      width: 145vmax;
      height: 145vmax;
      left: calc(50% - 72.5vmax);
      top: calc(50% - 72.5vmax);
      /* GEÄNDERT [1]: Zweite Animation "drehen" (dieselben Keyframes wie früher bei .strahlen).
         Jetzt dreht sich das FERTIG GEFILTERTE Bild – der Filter wird nur EINMAL gerechnet,
         danach dreht die Grafikkarte nur noch ein Foto davon. Das kostet fast nichts. */
      animation: reissen 9s steps(1) infinite, drehen 160s linear infinite;
      will-change: transform;   /* NEU [1]: eigene Ebene → das gefilterte Bild wird gespeichert und nur noch gedreht */
    }

    /* NEU [22]: HIMMEL-TUNNEL. Gleiche Größe und Position wie .himmel-bild.
       Grundzustand unsichtbar – nur die Animation macht sie sichtbar. */
    .himmel-fluss {
      max-width: none;
      width: 145vmax;
      height: 145vmax;
      left: calc(50% - 72.5vmax);
      top: calc(50% - 72.5vmax);
      opacity: 0;
      will-change: transform, opacity;
      animation: tunnel 18s linear infinite;
    }
    /* Die zweite Kopie: negative Verzögerung = sie ist schon in der Mitte ihres Weges,
       wenn die Seite lädt. So ist immer eine Kopie am Kommen, während die andere verschwindet. */
    .himmel-fluss.zwei { animation-delay: -9s; }

    /* Von doppelter Größe auf normale Größe, dabei ein Stück gedreht.
       Kleiner werden = alles bewegt sich zur Mitte hin = es fließt in sich hinein.
       Nie kleiner als 1, sonst würden beim Drehen die Ecken leer (siehe Kommentar bei .himmel-bild).
       opacity: rein – halten – raus, damit man den Neustart der Schleife nicht sieht. */
    @keyframes tunnel {
      0%   { scale: 2;   rotate: 50deg; opacity: 0; }
      25%  { opacity: 0.4; }
      75%  { opacity: 0.4; }
      100% { scale: 1;   rotate: 0deg;  opacity: 0; }
    }
    /* g.strahlen = URENKEL von .hero. fill wird an alle Kinder (die polygons) VERERBT –
       deshalb muss nicht jedes polygon einzeln eine Farbe bekommen. */
    .strahlen {
      fill: var(--weiss);
      transform-box: view-box;
      transform-origin: 50% 50%;
      /* GEÄNDERT [1]: Die Strahlen drehen sich NICHT mehr selbst.
         Das war der GRÖSSTE Leistungsfresser der Seite: Die Strahlen drehten sich INNERHALB des
         Verzerrungsfilters. Jede noch so kleine Drehung zwang den Browser, den bildschirmgroßen Filter
         neu zu rechnen – bis zu 60x pro Sekunde. Gemessen: ohne diese Drehung lief die Seite ca. 100x flüssiger.
         Die Drehung macht jetzt .himmel als Ganzes (siehe oben).
         Der Preis: Das Wabern (Verzerrung, die sich ständig verändert) ist eingefroren –
         die verzerrten Strahlen drehen sich jetzt wie ein Bild. */
      animation: none;
      /* WILLST DU DAS WABERN ZURÜCK? Dann die Zeile unten statt "animation: none" benutzen.
         Die Verzerrung verändert sich dann wieder langsam, kostet aber Leistung:
         steps(160) = nur 1 Neuberechnung pro Sekunde (ruckelt leicht, aber schont den Rechner).
      animation: drehen 160s steps(160) infinite;  */
    }
    @keyframes drehen { to { rotate: 360deg; } }

    /* Ab und zu reißt das Bild kurz seitlich weg */
    @keyframes reissen {
      0%, 86%, 88%, 100% { translate: 0 0; filter: none; }
      87%  { translate: -14px 0; filter: contrast(2.5); }
      87.5%{ translate: 9px 0; }
    }
    /* ======================================================================================================== */
     /* ================================   Unbenutze Text Style Sheet    ====================================== */                                   
    /* ======================================================================================================== */
    /* ======================================================================================================== */
    /* Alles in diesem Abschnitt wartet auf HTML, das es gerade noch nicht gibt.
       Die Verwandtschafts-Selektoren hier sind aber gute Beispiele zum Lernen. */

    .ecke { z-index: 4; font-size: 0.95rem; color: var(--weiss); mix-blend-mode: difference; }
    .ecke.lo { top: 1.5rem; left: 1.5rem; }
    .ecke.ro { top: 1.5rem; right: 1.5rem; text-align: right; }

    .hero-unten {
      z-index: 4;
      left: 1.5rem;
      right: 1.5rem;
      bottom: 1.5rem;
      display: flex;
      flex-wrap: wrap;
      justify-content: space-between;
      align-items: flex-end;
      gap: 1rem;
    }
    /* Leerzeichen: jedes p IRGENDWO in .hero-unten (Kind, Enkel …) */
    .hero-unten p { max-width: 34ch; color: var(--grau); }

    .knopf {
      display: inline-block;
      padding: 1rem 1.8rem;
      background: var(--weiss);
      color: var(--schwarz);
      text-decoration: none;
      clip-path: polygon(0 10%, 6% 0, 14% 12%, 25% 2%, 38% 10%, 52% 0, 66% 8%, 80% 0, 92% 10%, 100% 4%,
                         96% 50%, 100% 92%, 88% 100%, 74% 90%, 60% 100%, 46% 92%, 30% 100%, 18% 90%, 6% 100%, 0 88%, 4% 50%);
    }
    .knopf:hover { background: var(--grau); }
    a:focus-visible { outline: 3px dashed var(--weiss); outline-offset: 6px; }

    /* ============ 3. INHALT ============ */
    /* main = KIND von body. Wird AKTIV benutzt: Der weiße Rand oben ist sichtbar,
       obwohl main noch leer ist. */
    main {
      display: grid;
      grid-template-columns: 1fr 1fr;
      border-top: 6px solid var(--weiss);
    }
    section { padding: 3rem 1.5rem 4rem; }
    /* Plus: eine section, die DIREKT nach einer anderen section kommt (GESCHWISTER).
       Ergebnis: Nur die zweite, dritte … bekommt den Rand links, die erste nicht. */
    section + section { border-left: 6px solid var(--weiss); }

    h2 {
      font-family: "Big Shoulders Display", Impact, sans-serif;
      font-size: clamp(2.5rem, 7vw, 5rem);
      line-height: 0.9;
      margin-bottom: 2rem;
      text-transform: uppercase;
      left: 50;
      top: 50; 
    }

    .tracks { list-style: none; counter-reset: track; }
    /* li IRGENDWO in .tracks (hier: die direkten Kinder der Liste) */
    .tracks li {
      position: relative;            /* Bezugspunkt für das ::after-Kind weiter unten */
      counter-increment: track;
      display: flex;
      gap: 1rem;
      padding: 0.6rem 0.4rem;
      border-bottom: 1px solid var(--grau);
    }
    /* ::before = neues erstes Kind in jedem li (die Nummer) */
    .tracks li::before { content: counter(track, upper-roman); color: var(--grau); min-width: 2.2rem; }
    /* span:last-child = das span, das das LETZTE Kind seines Elternteils (li) ist */
    .tracks li span:last-child { margin-left: auto; color: var(--grau); }
    /* ::after = neues letztes Kind in jedem li (das Flüstern) */
    .tracks li::after {
      content: attr(data-fluestern);
      position: absolute;
      left: 3.6rem;
      opacity: 0;
      letter-spacing: 0.15em;
    }
    .tracks li:hover { background: var(--weiss); color: var(--schwarz); }
    /* Zustand + Verwandtschaft kombiniert: "das erste span in einem li, über dem die Maus ist" */
    .tracks li:hover span:first-child { opacity: 0; }
    .tracks li:hover::after { opacity: 1; }

    .termine { list-style: none; }
    .termine li {
      display: grid;
      grid-template-columns: 5.5rem 1fr;
      gap: 1rem;
      padding: 1rem 0;
      border-bottom: 1px solid var(--grau);
    }
    .termine time { color: var(--grau); }
    .termine .ausverkauft { text-decoration: line-through; color: var(--grau); }

    /* footer = KIND von body. Auch aktiv: Der Rand oben ist sichtbar. */
    footer {
      border-top: 6px solid var(--weiss);
      padding: 1.5rem;
      color: var(--grau);
      font-size: 0.9rem;
      display: flex;
      justify-content: space-between;
      flex-wrap: wrap;
      gap: 1rem;
    }

    /* ======================================================================================================== */
    /* =======================================    LOGO DEEPDIVE    ============================================ */
    /* ======================================================================================================== */
    /* Aufbau wie ein Bandlogo: mehrere Schichten genau übereinander, durch eine Fischaugen-Linse gesehen.
       Alle Größen in vw → das Logo bleibt beim Zoomen gleich, wie dein Himmel. */

    /* .logo = KIND von .hero → position: absolute kommt schon von ".hero > *".
       grid + place-items: center → die Linse sitzt genau in der Mitte des Kastens, ganz ohne translate.
       (translate wäre ein Problem, weil die "reissen"-Animation selbst translate benutzt.) */
    .logo {
      /* GEÄNDERT [12]: vorher inset: 0 (ganzer Bildschirm). Jetzt nur so groß wie die Linse.
         Grund: mix-blend-mode: difference muss für JEDES Pixel des Kastens rechnen – auch für die leeren.
         Kleinerer Kasten = weniger Mischarbeit. Zentriert über left/top mit calc (nicht translate,
         weil die "reissen"-Animation translate benutzt). */
      width: 86vw;
      height: 44vw;
      left: 7vw;                     /* (100vw - 86vw) / 2 */
      top: calc(50% - 22vw);         /* Mitte minus halbe Höhe */
      z-index: 20;
      display: grid;
      place-items: center;
      margin: 0;                     /* überschreibt margin-bottom aus der allgemeinen h2-Regel */
      pointer-events: none;
      text-transform: none;
      font-family: "Grenze Gotisch", Georgia, serif;
      font-weight: 700;
      line-height: 1;
      /* INVERTIEREN: Für jeden Pixel rechnet der Browser |Logo-Farbe − Hintergrund-Farbe|.
         Weiß im Logo → kehrt den Hintergrund um. Schwarz → ändert nichts, bleibt unsichtbar.
         Deshalb sind alle Teile des Logos weiß. */
      mix-blend-mode: difference;
      /* ZWEI Animationen gleichzeitig, mit Komma getrennt */
      animation: reissen 9s steps(1) infinite, flackern 5s steps(1) infinite;
      /* NEU [6]: Reißen und Flackern starten erst nach 3 Sekunden – erst fügt sich das Logo zusammen.
         Zwei Werte, weil es zwei Animationen sind (gleiche Reihenfolge wie oben). */
      animation-delay: 3s, 3s;
    }

    /* Flackern: steps(1) = harte Sprünge. Meist ruhig, dann ein kurzer, unruhiger Ausfall. */
    @keyframes flackern {
      0%, 60%  { opacity: 1; }
      62%      { opacity: 0.25; }
      63%      { opacity: 0.9; }
      65%      { opacity: 0.05; }
      67%      { opacity: 0.75; }
      68%      { opacity: 0.3; }
      70%, 100%{ opacity: 1; }
    }

    /* Die Linse: ENKEL von .hero. Sie bekommt den Fischaugen-Filter.
       Warum nicht direkt auf .logo? Weil die "reissen"-Animation dort "filter" verändert
       und den Fischaugen-Filter immer wieder überschreiben würde.
       Feste Größe, weil der Filter sich nach dem Kasten dieses Elements richtet:
       Die Mitte des Kastens = Mitte der Wölbung. */
    .linse {
      display: grid;
      place-items: center;
      width: 86vw;
      height: 44vw;
      /* ENTFERNT [15]: filter: url(#fischauge) und will-change.
         GEÄNDERT [17]: Das Fischauge gibt es nicht mehr. Stattdessen steckt der Filter #zerreissen im Bild logo.webp. */
      /* NEU [15]: Nach dem Intro verschwindet die Linse mit allen fliegenden Teilen – das Bild übernimmt.
         3.1s Verzögerung = so lange, bis das letzte Teil eingerastet ist (längste --d 1s + 2.2s Flugzeit, gerundet).
         "forwards" (animation-fill-mode) = nach dem Ende bleibt der 100 %-Zustand stehen, also unsichtbar. */
      animation: verschwinden 0.5s 3.1s forwards;
    }

    /* Trick zum Stapeln ohne position: absolute:
       Alle direkten Kinder der Linse kommen in DIESELBE Grid-Zelle (Zeile 1 / Spalte 1)
       und liegen damit übereinander. Die Reihenfolge im HTML bestimmt, wer oben liegt. */
    .linse > * { grid-area: 1 / 1; }

    /* NEU [15]: .linse und .logo-bild liegen auch per Grid übereinander (gleiche Zelle) */
    .logo > * { grid-area: 1 / 1; }

    /* NEU [15]: Das fertige Logo-Bild. Genau so groß wie der Logo-Kasten (86vw × 44vw),
       damit es exakt dort liegt, wo vorher die Linse war.
       max-width: none, weil Bilder sonst oft nicht breiter als ihr Elternteil sein dürfen.
       "backwards" = während der 3.1s Wartezeit gilt schon der 0 %-Zustand, also unsichtbar. */
    .logo-bild {
      width: 100%;
      height: 100%;
      max-width: none;
      /* GEÄNDERT [21]: zweite Animation "wabern". Startet bei 3.6s, also wenn das Bild schon da ist. */
      animation: auftauchen 0.5s 3.1s backwards, wabern 11s ease-in-out 3.6s infinite;
    }

    /* NEU [21]: WABERN – das Logo dehnt sich, wird gestaucht, kippt und neigt sich (skew), ganz langsam.
       scale mit ZWEI Werten = breiter/schmaler und höher/niedriger getrennt → wirkt wie Gummi.
       skewX = schräg ziehen, wie wenn etwas zerfließt.
       Alles in transform → die Grafikkarte verformt nur das fertige Bild, nichts wird neu gerechnet. */
    @keyframes wabern {
      0%, 100% { transform: scale(1, 1)        rotate(0deg)     skewX(0deg); }
      25%      { transform: scale(1.04, 0.97)  rotate(-1.2deg)  skewX(3deg); }
      50%      { transform: scale(0.97, 1.05)  rotate(0.8deg)   skewX(-2deg); }
      75%      { transform: scale(1.03, 1.01)  rotate(1.4deg)   skewX(1.5deg); }
    }

    /* NEU [21]: Das Nachbild. Liegt per Grid (.logo > *) genau auf dem Logo.
       Grundzustand: unsichtbar (opacity 0). Die Animation blendet es kurz ein, während es schrumpft. */
    .logo-geist {
      width: 100%;
      height: 100%;
      max-width: none;
      opacity: 0;
      animation: hineinfliessen 5s cubic-bezier(0.5, 0, 1, 1) 3.6s infinite;
    }
    /* Startet 1,5x so groß und gedreht, zieht sich immer schneller zusammen (cubic-bezier = beschleunigen)
       und verschwindet genau dann, wenn es so groß ist wie das Logo. */
    @keyframes hineinfliessen {
      0%   { transform: scale(1.5) rotate(-6deg); opacity: 0; }
      30%  { opacity: 0.35; }
      100% { transform: scale(1) rotate(0deg);    opacity: 0; }
    }
    /* NEU [15]: Überblendung. Fehlt der 100 %-Wert, geht der Browser automatisch zum normalen Wert (opacity 1). */
    @keyframes auftauchen   { from { opacity: 0; } }
    /* visibility: hidden am Ende → Firefox malt die Linse gar nicht mehr, sie kostet dann nichts */
    @keyframes verschwinden { to   { opacity: 0; visibility: hidden; } }

    /* Ornamente: Klingen und Stacheln. overflow: visible → Stacheln dürfen über das SVG hinausragen */
    .logo-ornament {
      width: 70vw;
      height: 28vw;
      overflow: visible;
      /* GEÄNDERT [9]: Kopie des Himmel-Filters (#verzerrt-logo, im HTML erklärt) + Unschärfe.
         Mehrere Filter = Leerzeichen dazwischen, sie wirken nacheinander. */
      /* GEÄNDERT [15]: nur noch Unschärfe (die rechnet auch Firefox schnell auf der Grafikkarte).
         Die Verzerrung (#verzerrt-logo) steckt jetzt im fertigen Bild logo.webp. */
      filter: blur(0.6px);   /* GEÄNDERT [19]: 0.6 statt 1.2 → schärfer */
    }
    /* fill wird an alle Pfade VERERBT. Keine Unschärfe mehr → gestochen scharfe Kanten */
    .dornen {
      fill: var(--weiss);
      stroke: none;
      opacity: 0.6;                        /* etwas durchsichtiger als das Wort → die Buchstaben heben sich ab */
    }
    /* NEU [6]: Jeder Stachel (path = Kind von g.dornen) fliegt einzeln herein.
       transform-box: fill-box + transform-origin: center → er dreht sich um seine EIGENE Mitte,
       nicht um die Ecke des SVGs. */
    .dornen path {
      transform-box: fill-box;
      transform-origin: center;
      animation: magnet 2.2s var(--d) backwards;
    }

    /* Die Echos: dasselbe Wort in der fetten Variante (900), flach gequetscht, breit gezogen, verschmiert */
    .logo-echo {
      font-size: 10vw;
      font-weight: 900;
      color: var(--weiss);
      letter-spacing: -0.04em;
      opacity: 0.4;                        /* schwächer als das Wort → wirkt wie ein Nachbild */
      /* GEÄNDERT [15]: beim Herfliegen nur Unschärfe. Das Verschmieren steckt jetzt im Bild logo.webp. */
      filter: blur(0.8px);   /* GEÄNDERT [19]: 0.8 statt 1.5 → schärfer */
      animation: magnet 2.2s var(--d) backwards;   /* NEU [6]: fliegt herein (Startpunkt steht im HTML) */
    }
    .logo-echo.oben  { transform: translateY(-12vw) scale(1.25, 0.4); }
    .logo-echo.unten { transform: translateY(12vw)  scale(1.35, -0.46); }   /* minus = gespiegelt */

    /* Das Wort selbst: weiß, hoch gestreckt, Buchstaben rücken eng zusammen */
    .logo-wort {
      font-size: 12vw;
      color: var(--weiss);
      letter-spacing: 0.01em;
      transform: scaleY(1.5);
      white-space: nowrap;
      /* GEÄNDERT [9]: Kopie des Himmel-Filters (#verzerrt-logo) + Unschärfe */
      /* GEÄNDERT [15]: nur noch Unschärfe (die rechnet auch Firefox schnell auf der Grafikkarte).
         Die Verzerrung (#verzerrt-logo) steckt jetzt im fertigen Bild logo.webp. */
      filter: blur(0.6px);   /* GEÄNDERT [19]: 0.6 statt 1.2 → schärfer */
    }
    /* NEU [6]: Jeder Buchstabe einzeln.
       display: inline-block ist PFLICHT: translate und rotate wirken nicht auf normale Inline-Elemente
       (Text-Spans), nur auf Kästen. inline-block = bleibt in der Zeile, ist aber ein Kasten. */
    .logo-wort .b {
      display: inline-block;
      animation: magnet 2.2s var(--d) backwards;
    }

    /* NEU [6]: DIE MAGNET-ANIMATION – wird von Buchstaben, Stacheln und Echos benutzt.
       var(--x), var(--y), var(--r) kommen aus dem style-Attribut JEDES Elements → jedes startet woanders.

       Der Magnet-Trick steckt in animation-timing-function INNERHALB der Keyframes:
       Sie gilt jeweils bis zum nächsten Keyframe.
       0 % → 78 %: cubic-bezier(0.7, 0, 1, 0.6) = fängt sehr langsam an und wird immer schneller,
                   wie etwas, das von einem Magneten angezogen wird.
       78 %:       Einschlag in der Mitte.
       86 %:       kleiner Rückprall (2 % des Weges zurück), dann rastet es ein.

       Fehlt eine Eigenschaft in einem Keyframe, nimmt der Browser den normalen Wert des Elements.
       Deshalb steht opacity nur bei 0 % und 20 %: danach geht jedes Element zu SEINER eigenen Deckkraft
       (Echos 0.4, Buchstaben 1) – ohne dass wir das hier festlegen müssen.

       "backwards" beim Aufruf (animation-fill-mode) = während der Wartezeit (--d) gilt schon der 0 %-Zustand,
       das Teil ist also unsichtbar draußen, bevor es losfliegt. */
    @keyframes magnet {
      0%   { translate: var(--x) var(--y); rotate: var(--r); opacity: 0;
             animation-timing-function: cubic-bezier(0.7, 0, 1, 0.6); }
      20%  { opacity: 1; }
      78%  { translate: 0 0; rotate: 0deg;
             animation-timing-function: ease-out; }
      86%  { translate: calc(var(--x) * -0.02) calc(var(--y) * -0.02); rotate: calc(var(--r) * -0.01); }
      100% { translate: 0 0; rotate: 0deg; }
    }
    /* Einzelne große Buchstaben, wie die Initialen in Bandlogos */
    .logo-wort .gross {
      font-size: 1.4em;
      vertical-align: -0.1em;
    }

    /* Text nur für Screenreader: unsichtbar, aber nicht mit display: none (das würde auch das Vorlesen verhindern) */
    .nur-vorlesen {
      position: absolute;
      width: 1px;
      height: 1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
    }
    /* ======================================================================================================== */
    /* =======================================    LOGO DEEPDIVE    ============================================ */
    /* ======================================================================================================== */


    /* ======================================================================================================== */
    /* =====================================    JUGENDSTIL-MUSTER    ========================================== */
    /* ======================================================================================================== */
    /* KIND von body (nicht von .hero!) → bekommt KEIN position: absolute von ".hero > *".
       position: fixed → klebt am Browserfenster und liegt beim Scrollen über der ganzen Seite. */
    .jugendstil {
      position: fixed;
      /* GEÄNDERT [20]: -26vw statt 0 → der Kasten ist auf jeder Seite eine Kachel größer als der Bildschirm.
         So bleibt beim Verschieben um eine Kachel nie eine leere Kante sichtbar. */
      inset: -26vw;
      z-index: 30;                         /* über allem, auch über dem Logo (20) */
      pointer-events: none;                /* Klicks gehen durch das Muster hindurch */
      /* GEÄNDERT [10]: jugendstil.png statt jugendstil.svg.
         Das Bild ist die SVG-Kachel, auf die der Himmel-Filter (#verzerrt) und eine Unschärfe schon
         VORHER angewendet wurden ("eingebrannt"). Der Browser muss nichts mehr filtern – nur ein Bild kacheln.
         Vorher lag ein Live-Filter (url + blur) auf dem bildschirmgroßen Muster. Das war teuer.
         jugendstil.svg bleibt im Ordner: Das ist die Vorlage, falls du das Muster ändern willst.
         Danach muss das PNG neu erzeugt werden – sag Bescheid. */
      background-image: url("jugendstil.png");
      background-size: 26vw 26vw;          /* in vw → bleibt beim Zoomen gleich groß */
      background-position: center;         /* NEU [11]: Kacheln wachsen/schrumpfen um die Bildschirmmitte */
      mix-blend-mode: difference;          /* wie das Logo: invertiert, was darunter liegt */
      opacity: 0.35;                       /* GEÄNDERT [10]: etwas stärker, die verzerrten Linien sind dünner */
      /* ENTFERNT [10] [13]: filter und will-change – nicht mehr nötig. */
      /* GEÄNDERT [20]: zweite Animation "treiben", endlos. will-change → eigene Ebene, die Grafikkarte schiebt sie nur. */
      animation: einsaugen 2.6s 1 backwards, treiben 40s linear infinite;
      will-change: transform;
    }
    /* NEU [20]: Das Muster treibt schräg nach rechts unten – genau EINE Kachel (26vw) in 40 Sekunden.
       Danach springt es zurück auf 0. Weil sich das Muster alle 26vw wiederholt, sieht der Sprung
       exakt gleich aus → eine nahtlose Endlosschleife. */
    @keyframes treiben {
      from { translate: 0 0; }
      to   { translate: 26vw 26vw; }
    }
    /* GEÄNDERT [11]: Das Muster wird jetzt über background-size eingesaugt statt über scale.
       Warum? Mit scale: 4 am Anfang hat der Browser das ganze Muster in VIERFACHER Größe gemalt
       (= 16x so viele Pixel, inklusive Filter). Das hat Grafikspeicher und Leistung gefressen.
       Jetzt bleibt der Kasten bildschirmgroß, nur die Kacheln darin starten 4x so groß (104vw)
       und ziehen sich auf 26vw zusammen. Weil background-position: center ist, schrumpfen sie zur Mitte hin.
       Gleicher Magnet-Trick wie beim Logo: erst langsam, dann immer schneller, kurz zu klein (25vw), dann einrasten. */
    @keyframes einsaugen {
      0%   { background-size: 104vw 104vw; opacity: 0;
             animation-timing-function: cubic-bezier(0.7, 0, 1, 0.6); }
      30%  { opacity: 0.35; }
      80%  { background-size: 25vw 25vw;
             animation-timing-function: ease-out; }
      100% { background-size: 26vw 26vw; }
    }
    /* ======================================================================================================== */
    /* =====================================    JUGENDSTIL-MUSTER    ========================================== */
    /* ======================================================================================================== */

    /* ======================================================================================================== */
    /* =====================================    ALLES INVERTIEREN [16]    ===================================== */
    /* ======================================================================================================== */
    /* KIND von body. position: fixed → klebt am Browserfenster, liegt auch beim Scrollen über allem.
       z-index: 1000 → höher als alles andere (Jugendstil 30, Logo 20) → liegt ganz oben.
       Weiß + difference = |Weiß − Farbe darunter| = die umgekehrte Farbe. Schwarz wird weiß, weiß wird schwarz,
       Grau bleibt ungefähr grau.
       Das Logo ist selbst schon "difference" → es wird zweimal umgedreht → sieht aus wie der Himmel VOR dem Umdrehen.
       pointer-events: none → Klicks gehen hindurch.

       Warum nicht einfach filter: invert(1) auf body? Ein filter auf einem Elternteil verändert,
       worauf sich position: fixed bezieht – das Jugendstil-Muster würde dann mit der Seite wegscrollen. */
    .invertieren {
      position: fixed;
      inset: 0;
      z-index: 1000;
      background: #fff;
      mix-blend-mode: difference;
      pointer-events: none;
    }
    /* ======================================================================================================== */
    /* =====================================    ALLES INVERTIEREN [16]    ===================================== */
    /* ======================================================================================================== */


    /* ============ 4. HANDY ============ */
    /* Alles hier drin gilt NUR, wenn der Bildschirm höchstens 760px breit ist. */
    @media (max-width: 760px) {
      main { grid-template-columns: 1fr; }
      section + section { border-left: none; border-top: 6px solid var(--weiss); }

      .berge.nah { height: 38%; }
    }

    /* Bei "weniger Bewegung" in den Systemeinstellungen: ALLE Animationen aus.
       !important = gewinnt gegen alles andere, auch gegen spätere Regeln. */
    @media (prefers-reduced-motion: reduce) {
      *, *::before, *::after { animation: none !important; }
      .linse { display: none; }   /* NEU [15]: ohne Animation sofort nur das fertige Logo-Bild zeigen */
      /* Hinweis [6] [7]: Bei "weniger Bewegung" gibt es auch kein Intro – alles steht sofort an seinem Platz,
         weil der Grundzustand jedes Elements schon der fertige Zustand ist. Die Animation zeigt nur den Weg dorthin. */
    }
