/* ==========================================================================
 * NEUES REDESIGN — Eventseite OBERHAUSEN, Scope `live80-v2`
 * --------------------------------------------------------------------------
 * 🔴 ERZEUGTE DATEI — NICHT VON HAND AENDERN.
 *    Quellen: _source/mockups/koeln-extra.css  (gemeinsames Eventkapitel)
 *             oberhausen-extra.css             (Moderation, Platzhalter)
 *    Bauweg : python3 exports/wp-builds/live80-v2/oberhausen/scope-css-oberhausen.py
 *
 * ERGAENZUNG zu live80-v2.css, kein Ersatz. Das Designsystem (Tokens, Typo,
 * Header, Footer, Act-Karten, Karussell, FAQ, Chatbot, Countdown-Leiste)
 * steht dort und wird auf jeder `_live80_v2`-Seite geladen — auch hier.
 *
 * Teil 1 = das gemeinsame Eventseiten-Kapitel, aus Koeln abgeleitet: die
 *          sechs Hero-Klassen tragen hier `oberhausen-` statt `koeln-`, alle
 *          WERTE sind unveraendert. Wer am Eventdesign etwas aendert, aendert
 *          `koeln-extra.css` — alle vier Eventseiten ziehen dann mit.
 * Teil 2 = die WordPress-Bruecke.
 * Teil 3 = was es NUR in Oberhausen gibt: Moderation, Platzhalter-Badge.
 * ========================================================================== */

/* ---------- Teil 1: gemeinsames Eventseiten-Kapitel ---------- */
/* ===========================================================================
   20. KÖLN – Eventseite
   ---------------------------------------------------------------------------
   Alles darueber ist das unveraenderte Designsystem der Startseite v3 – auch
   die Act-Karten mit Retro-Bildschirm, das Karussell und die Video-Lightbox.
   Dieses Kapitel ergaenzt NUR, was es dort nicht gibt: den Event-Hero mit
   Stadion-Kulisse und die Lichteffekte.

   ⚠️ Historie, damit es niemand zurueckdreht: Eine erste Fassung zeigte
   Fotokarten mit Spotify-Button, weil fuer die 13 Koelner Acts keine
   YouTube-IDs belegt waren (die Live-Seite verlinkt dort Spotify). Auf
   Kundenwunsch sind es jetzt Videos. Die IDs wurden einzeln recherchiert und
   zweistufig geprueft (Existenz per oEmbed, Einbettbarkeit per IFrame-API
   unter der echten Domain) – Details stehen ueber dem ACTS-Array in der
   koeln-app.js. Erfundene IDs waeren Fehlinformation gewesen, deshalb der
   Umweg.
   =========================================================================== */
/* --- Hero ---------------------------------------------------------------- */
/* Die Neon-Illustration des Stadions liegt als Kulisse hinter dem Hero.
   ⚠️ Zwei Dinge sind Absicht:
   (1) Sie sitzt am UNTEREN Rand und wird nach oben ausmaskiert – sonst
       schneidet sie als sichtbare Kastenkante durch die Headline (dieselbe
       Falle wie beim Horizontglühen, Checkliste 76).
   (2) object-fit:contain, nicht cover: die Illustration traegt Schriftzuege
       und ist randlos komponiert (siehe CLAUDE.md, "Event-Kacheln"). */
.live80-v2 .oberhausen-hero{min-height:min(96svh,940px);padding-block:var(--s8) var(--s9)}
/* ⚠️ Deckkraft ist gemessen, nicht geschaetzt: bei .5 stieg die Illustration
   hinter der Textsaeule so weit auf, dass die cyanfarbene Spielstaetten-Zeile
   im unguenstigsten Fall (hellste 5 % der Textflaeche) nur noch 2,39:1
   erreichte – unter der Norm von 3:1 fuer Grossschrift. */
/* ⚠️ transform-origin unten: die Scroll-Skalierung waechst dadurch nach OBEN,
   die Unterkante bleibt stehen. Ohne das entsteht beim Scrollen eine sichtbare
   Farbkante am Fuss des Hero (siehe Kommentar in koeln-app-a.js). */
.live80-v2 .oberhausen-skyline{position:absolute;left:50%;bottom:0;transform:translateX(-50%);
  transform-origin:50% 100%;
  width:min(150%,1900px);aspect-ratio:3/2;z-index:0;pointer-events:none;opacity:.34;
  -webkit-mask-image:linear-gradient(to top,#000 0 34%,rgba(0,0,0,.55) 62%,transparent 88%);
          mask-image:linear-gradient(to top,#000 0 34%,rgba(0,0,0,.55) 62%,transparent 88%)}
.live80-v2 .oberhausen-skyline img{width:100%;height:100%;object-fit:contain;object-position:50% 100%}
.live80-v2 .oberhausen-hero .hero-inner{position:relative;z-index:3;text-align:center;display:grid;
  justify-items:center;gap:var(--s5)}
.live80-v2 .oberhausen-logo{width:clamp(150px,17vw,250px);filter:drop-shadow(0 0 24px rgba(255,45,149,.6))}
/* Das Datum ist auf einer Eventseite die wichtigste Zahl der Seite – es steht
   deshalb als eigener Block ueber dem Stadtnamen, nicht als Nebenzeile. */
.live80-v2 .oberhausen-date{display:inline-flex;align-items:baseline;gap:var(--s3);flex-wrap:wrap;
  justify-content:center;
  font-family:'Core Sans M','Asap',sans-serif;font-weight:800;
  font-size:clamp(20px,1rem + 1.1vw,30px);letter-spacing:.06em;text-transform:uppercase;
  color:var(--c-gold);
  /* 🔴 DUNKLER Saum ZUERST, Glimmen danach. Auf einem Foto-/Illustrations-
     grund traegt ein reines Leuchten die Lesbarkeit nicht – es hellt die
     Umgebung zusaetzlich auf. Dieselbe Logik wie bei .chrome (siehe dort). */
  text-shadow:0 2px 0 rgba(var(--c-shadow),.85), 0 0 10px rgba(var(--c-shadow),.95),
              0 0 26px rgba(var(--c-shadow),.7), var(--glow-gold)}
.live80-v2 .oberhausen-date strong{font-size:.66em;letter-spacing:.2em;color:var(--c-ink-2);
  text-shadow:0 1px 0 rgba(var(--c-shadow),.9), 0 0 12px rgba(var(--c-shadow),.9)}
.live80-v2 .oberhausen-city{font-size:var(--fs-4xl);line-height:.86}
/* 🔴 Die Spielstaetten-Zeile sitzt auf einer dunklen Plakette, nicht frei auf
   dem Grund. Grund ist gemessen, nicht Geschmack: Cyan auf dem hellen Hero-
   Pink kam im unguenstigsten Fall auf 2,30:1 – unter der Norm von 3:1 fuer
   Grossschrift. Ein dunkler Textsaum allein loest das nicht (WCAG rechnet
   Schatten nicht an, und die Umgebung bleibt hell); erst eine eigene Flaeche
   unter der Schrift tut es. Optisch passt sie zu den Eckdaten-Pillen darunter.
   ⚠️ Wer die Plakette entfernt, muss die Schriftfarbe auf Weiss stellen. */
.live80-v2 .oberhausen-venue{display:inline-block;
  font-family:'Core Sans M','Asap',sans-serif;font-size:clamp(17px,.9rem + .8vw,27px);
  letter-spacing:.2em;text-transform:uppercase;color:var(--c-cyan);
  padding:.3em .95em;border-radius:var(--r-pill);
  border:1px solid rgba(38,224,255,.35);
  background:rgba(var(--c-shadow-deep),.72);backdrop-filter:blur(7px);
  text-shadow:0 0 14px rgba(38,224,255,.5)}
.live80-v2 .hero-actions{display:flex;gap:var(--s4);flex-wrap:wrap;justify-content:center}
/* --- Stadion-Sektion ------------------------------------------------------ */
/* Eigene Rampe, weil "RHEINENERGIESTADION" als ein Wort nicht umbrechen kann:
   die untere Grenze ist an ihm ausgemessen (327px Platz bei 375px Viewport),
   nach oben laeuft sie auf denselben Wert wie --fs-2xl.
   ⚠️ Der Selektor MUSS .sec-head enthalten: das Designsystem setzt
   `.sec-head h2{font-size:var(--fs-3xl)}` (Spezifitaet 0,1,1). Eine einzelne
   Klasse verliert dagegen – nachgemessen, die Ueberschrift blieb bei 40px
   statt 21px und ragte weiter aus dem Bild. */
.live80-v2 .sec-head .venue-h{font-size:clamp(21px,5.2vw,50px)}
.live80-v2 .venue-sec{position:relative;overflow:hidden}
.live80-v2 .venue-illu{position:absolute;inset:0;z-index:0;pointer-events:none;opacity:.42}
.live80-v2 .venue-illu img{width:100%;height:100%;object-fit:cover;object-position:50% 42%}
/* Schleier in Magenta, NICHT in Schwarz – Schwarz entsaettigt den Grund und
   erzeugt genau den "schmutzigen" Eindruck (Checkliste 89). */
.live80-v2 .venue-sec::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,rgba(122,11,99,.72),rgba(58,17,96,.86))}
.live80-v2 .venue-sec>.wrap{position:relative;z-index:2}
/* --- Der Textblock unter der Ueberschrift ---------------------------------
   🔴 Vorgeschichte in zwei Stufen, damit niemand zurueckdreht (beide am
   2026-08-05, beide vom Kunden abgelehnt):
     1. Ausgangsfassung: drei zentrierte Absaetze in Kleinschrift, frei im
        Raum -> "muss besser umbrochen werden und auch besser gestyled".
     2. Mein erster Umbau: jeder Act auf eigener Zeile, Songtitel cyan,
        Anrede als cyanfarbene Versalzeile, Satzbreite 64ch (518px)
        -> "richtig beschissen, mach es wieder breiter und nicht so chaotisch".
   Stufe 2 war zu viel: Sie hat einen FLIESSTEXT in eine Liste zerlegt und ihn
   mit drei Farben und zwei Schriftschnitten ueberzeichnet – und dabei die
   Zeilen auch noch schmaler gemacht, obwohl "zu eng" nie das Problem war.

   Jetzt: Fliesstext wie im Original, aber BREITER als vorher (860px gegen
   655px), ruhig gesetzt, und mit dem einzigen Eingriff, um den es
   ursprunglich ging – Kuenstlername und Songtitel brechen nicht mehr um.
   Farbe traegt nur noch der Name (weiss/fett), sonst nichts.
   ⚠️ .nobr NICHT durch white-space:nowrap auf dem Absatz ersetzen – dann
   laeuft die ganze Zeile aus dem Bild.
   ------------------------------------------------------------------------- */
.live80-v2 .nobr{white-space:nowrap}
.live80-v2 .venue-copy{position:relative;max-width:860px;margin:var(--s7) auto 0;
  padding:var(--s7) clamp(20px,4vw,56px);
  border-radius:var(--r-lg);
  border:1px solid rgba(38,224,255,.22);
  background:linear-gradient(180deg,rgba(58,17,96,.55),rgba(42,11,73,.66));
  box-shadow:0 26px 70px rgba(var(--c-shadow),.4)}
/* Eine einzige Zierlinie oben – kein zusaetzliches Element, kein Layout. */
.live80-v2 .venue-copy::before{content:"";position:absolute;left:clamp(20px,4vw,56px);right:clamp(20px,4vw,56px);top:-1px;
  height:2px;border-radius:2px;
  background:linear-gradient(90deg,transparent,var(--c-pink),var(--c-cyan),transparent);
  box-shadow:0 0 16px rgba(255,45,149,.5)}
.live80-v2 .venue-copy p{margin:0;font-size:var(--fs-md);line-height:1.75;color:var(--c-ink-2);
  text-align:center;text-wrap:pretty;hyphens:manual}
.live80-v2 .venue-copy p + p{margin-top:var(--s5)}
/* Nur der Name wird hervorgehoben. Songtitel bleiben im Fliesstext stehen –
   sie zusaetzlich einzufaerben war der "chaotisch"-Anteil. */
.live80-v2 .venue-copy b{font-family:'Core Sans M','Asap',sans-serif;font-weight:700;letter-spacing:.03em;color:#fff}
/* Die Ansage etwas groesser; balance gleicht die Restzeile aus, statt eine
   Waise ("in Köln.") stehenzulassen. */
.live80-v2 .vc-lead{font-size:var(--fs-lg);line-height:1.5;text-wrap:balance}
.live80-v2 .vc-brand{font-family:'Core Sans M','Asap',sans-serif;font-weight:800;letter-spacing:.05em;color:#fff}
/* --- Abschluss-CTA: das Ticket -------------------------------------------
   🔴 Vorgeschichte, damit es niemand zurueckdreht: Hier stand ein heller
   Kasten mit Ueberschrift und Knopf. Der Kunde hat ihn am 2026-08-05
   ausdruecklich verworfen ("LANGWEILIG!!!! ... nicht so einen blöden weißen
   kasten"). Die Flaeche ist jetzt selbst das Produkt – ein Ticket mit
   Abrissabschnitt.
   ⚠️ Kein heller Kasten mehr an dieser Stelle. */
.live80-v2 .ticket-sec{position:relative;overflow:hidden;padding-block:var(--s10)}
/* Zwei Scheinwerfer, die auf die Mitte zulaufen – dieselbe Bauart wie die
   Buehnenstrahler ueber dem Line-up, nur enger gestellt. */
.live80-v2 .tk-spots{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.live80-v2 .tk-spots i{position:absolute;top:-20%;width:34vw;height:140%;
  transform-origin:50% 0;mix-blend-mode:screen;opacity:.6;
  -webkit-mask-image:linear-gradient(to bottom,#000,transparent 80%);
          mask-image:linear-gradient(to bottom,#000,transparent 80%)}
.live80-v2 .tk-spots i:first-child{left:-6vw;
  background:linear-gradient(to bottom,rgba(255,217,61,.42),rgba(255,45,149,.12) 45%,transparent 76%);
  animation:sl-l 12s ease-in-out infinite alternate}
.live80-v2 .tk-spots i:last-child{right:-6vw;
  background:linear-gradient(to bottom,rgba(255,45,149,.45),rgba(38,224,255,.1) 45%,transparent 76%);
  animation:sl-r 15s ease-in-out infinite alternate}
.live80-v2 .ticket-sec>.wrap-narrow{position:relative;z-index:2}
/* Das Ticket selbst. Hauptteil + Abriss, dazwischen die Perforation. */
.live80-v2 .ticket{position:relative;display:grid;grid-template-columns:1fr 190px;
  border-radius:var(--r-lg);overflow:hidden;isolation:isolate;
  background:
    radial-gradient(120% 140% at 12% 0%,rgba(255,45,149,.34),transparent 62%),
    linear-gradient(150deg,#4b1a7c 0%,#2a0b49 52%,#3a1160 100%);
  border:2px solid rgba(255,45,149,.5);
  box-shadow:0 30px 80px rgba(var(--c-shadow),.65),
             0 0 40px rgba(255,45,149,.35),0 0 110px rgba(255,45,149,.16)}
/* 🔴 Die Perforation ist eine echte Aussparung, kein aufgemalter Strich:
   die beiden Halbkreise werden per mask aus dem Ticket HERAUSGESCHNITTEN.
   Ein aufgemalter Kreis muesste die Hintergrundfarbe treffen – die ist hier
   aber ein Verlauf und aendert sich mit der Scrollposition. */
.live80-v2 .ticket{
  --perf:190px;   /* Abstand der Perforation vom rechten Rand = Stubbreite */
  -webkit-mask-image:
    radial-gradient(20px 20px at calc(100% - var(--perf)) 0,transparent 19px,#000 20px),
    radial-gradient(20px 20px at calc(100% - var(--perf)) 100%,transparent 19px,#000 20px);
          mask-image:
    radial-gradient(20px 20px at calc(100% - var(--perf)) 0,transparent 19px,#000 20px),
    radial-gradient(20px 20px at calc(100% - var(--perf)) 100%,transparent 19px,#000 20px);
  -webkit-mask-composite:source-in; mask-composite:intersect}
.live80-v2 .tk-main{position:relative;z-index:2;display:grid;justify-items:center;gap:var(--s5);
  text-align:center;padding:var(--s9) var(--s6)}
.live80-v2 .tk-eyebrow{font-family:'Core Sans M','Asap',sans-serif;font-size:var(--fs-xs);
  letter-spacing:.42em;text-transform:uppercase;color:var(--c-gold);text-shadow:var(--glow-gold)}
.live80-v2 .tk-h{font-size:var(--fs-2xl);line-height:1.02}
.live80-v2 .tk-sub{color:var(--c-ink-2);max-width:46ch}
.live80-v2 .tk-btn{min-height:60px;font-size:var(--fs-sm)}
/* Abrissabschnitt, senkrecht gesetzt wie auf einem echten Ticket. */
.live80-v2 .tk-stub{position:relative;z-index:2;display:grid;align-content:center;justify-items:center;
  gap:var(--s3);padding:var(--s6) var(--s4);
  border-left:2px dashed rgba(255,255,255,.35);
  background:linear-gradient(180deg,rgba(255,255,255,.07),rgba(255,255,255,.02))}
/* 🔴 Diese Zeile ist an „KÖLN" ausgemessen — VIER Zeichen. Der Abriss bietet
   innen 158px; bei 26px und .12em Laufweite braucht „KÖLN" davon 81px.
   Jede abgeleitete Eventseite mit einem laengeren Ortsnamen braucht deshalb eine
   EIGENE Rampe in ihrem Kapitel-CSS, sonst wird der Name rechts abgeschnitten:
     KÖLN 81 · HAMBURG 148 · NORWEGEN 122* · OBERHAUSEN 124*   (*mit eigener Rampe)
   Belegt: „NORWEGEN" lief auf 175px (Checkliste 260), „OBERHAUSEN" auf 200px
   (Checkliste 274). ⚠️ Gefunden hat es beide Male der SCREENSHOT — die Sektion
   hatte jeweils die erwartete Hoehe. ⚠️ Und die Gegenrichtung merken: mehr
   Laufweite macht es breiter, nicht schmaler. */
.live80-v2 .tk-city{font-family:'Core Sans M','Asap',sans-serif;font-weight:800;font-size:26px;
  letter-spacing:.12em;color:#fff;text-shadow:0 0 16px rgba(255,45,149,.8)}
.live80-v2 .tk-date{font-family:'Core Sans M','Asap',sans-serif;font-weight:800;font-size:18px;
  letter-spacing:.04em;color:var(--c-gold);font-variant-numeric:tabular-nums}
/* Barcode aus einem Verlauf – kein Bild, keine Schrift, rein dekorativ. */
.live80-v2 .tk-code{width:118px;height:52px;
  background:repeating-linear-gradient(90deg,#fff 0 2px,transparent 2px 4px,
             #fff 4px 5px,transparent 5px 9px,#fff 9px 12px,transparent 12px 14px);
  opacity:.9}
.live80-v2 .tk-no{font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--c-ink-3)}
/* 🔴 Neonroehre statt Gluehbirnenkette. Die Kette wurde am 2026-08-05
   verworfen ("eher Zirkus style als 80er") – laufende Birnen sind Jahrmarkt-
   und Theaterfassade, die 80er sind Neonroehre, Chrom und Gitterboden.
   Die Roehre ist ein Rahmen mit doppeltem Schein nach innen UND aussen; das
   unregelmaessige Anlaufen ist derselbe Flacker-Gedanke wie bei den Neonnamen
   der Startseite, nur ruhiger. Nur opacity, kein Filter. */
.live80-v2 .tk-tube{position:absolute;inset:9px;z-index:3;pointer-events:none;
  border:2px solid rgba(255,45,149,.9);border-radius:calc(var(--r-lg) - 8px);
  box-shadow:0 0 10px rgba(255,45,149,.85),0 0 26px rgba(255,45,149,.45),
             inset 0 0 12px rgba(255,45,149,.5),inset 0 0 30px rgba(255,45,149,.2);
  animation:tube 7s ease-in-out infinite}
@keyframes tube{
  0%,100%{opacity:1}
  49%{opacity:1} 50%{opacity:.55} 51.5%{opacity:1} 52.5%{opacity:.7} 53.5%{opacity:1}
}
/* Gitterboden im Fuss des Tickets – Fluchtpunkt-Optik der Zeit.
   Statisch, also kostenlos: zwei Verlaeufe, keine Animation. */
.live80-v2 .tk-grid{position:absolute;left:0;right:0;bottom:0;height:44%;z-index:0;pointer-events:none;
  background:
    repeating-linear-gradient(90deg,transparent 0 38px,rgba(38,224,255,.22) 38px 39px),
    repeating-linear-gradient(0deg,transparent 0 26px,rgba(255,45,149,.18) 26px 27px);
  -webkit-mask-image:linear-gradient(to top,#000,transparent 92%);
          mask-image:linear-gradient(to top,#000,transparent 92%);
  opacity:.75}
/* Hologramm-Streifen, der ueber das Ticket wandert. Nur translateX. */
.live80-v2 .tk-holo{position:absolute;top:0;bottom:0;left:0;width:34%;z-index:1;pointer-events:none;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.16) 45%,
             rgba(38,224,255,.14) 60%,transparent);
  transform:skewX(-16deg) translateX(-60%);
  animation:tk-holo 6.5s ease-in-out infinite}
@keyframes tk-holo{0%{transform:skewX(-16deg) translateX(-60%)}
                   55%,100%{transform:skewX(-16deg) translateX(330%)}}
@media (prefers-reduced-motion:reduce){.live80-v2 .tk-tube,.live80-v2 .tk-holo,.live80-v2 .tk-spots i{animation:none}}
/* ===========================================================================
   21. MOBILER HERO
   ---------------------------------------------------------------------------
   🔴 Kundenmeldung 2026-08-05: "gerade der hero stimmt mobil noch nicht".
   Gemessen bei 375x812 war die Ursache nicht der Text, sondern die Kulisse:
   .oberhausen-skyline ist 150 % breit – am Desktop sind das 1900px, am Handy aber
   nur 563px, bei 3:2 also 375px hoch. Sie sass damit als schmaler Streifen
   ganz unten, zum groessten Teil unterhalb der Sichtkante. Vom Stadion war
   praktisch nichts zu sehen, der Hero wirkte leer.

   Am Handy muss die Kulisse deshalb DEUTLICH ueber die Bildschirmbreite
   hinausgehen: 300 % ergeben 1125px Breite und 750px Hoehe – der Ausschnitt
   zeigt die Stadionmitte gross statt das ganze Motiv winzig. Dass links und
   rechts etwas wegfaellt, ist hier richtig: es ist Kulisse, kein Inhalt.
   =========================================================================== */
@media (max-width:700px){/* Etwas flacher und oben knapper – 96svh plus 64px Polster liessen den
     Inhalt in der Mitte schwimmen, mit grosser Leere unter dem Header. */
.live80-v2 .oberhausen-hero{min-height:min(88svh,720px);padding-block:var(--s5) var(--s8)}
.live80-v2 .oberhausen-hero .hero-inner{gap:var(--s4)}
.live80-v2 .oberhausen-skyline{width:300%;opacity:.42;
    /* Weniger weit ausgeblendet als am Desktop: bei dieser Groesse liegt der
       obere Rand ohnehin ausserhalb des Hero. */
    -webkit-mask-image:linear-gradient(to top,#000 0 52%,rgba(0,0,0,.6) 76%,transparent 96%);
            mask-image:linear-gradient(to top,#000 0 52%,rgba(0,0,0,.6) 76%,transparent 96%)}
/* Das Logo ist die Marke – 150px waren auf dem Handy zu zaghaft. */
.live80-v2 .oberhausen-logo{width:min(58%,210px)}
/* 🔴 Der Chat-Knopf sitzt fest unten rechts und lag auf dem zweiten Button
     ("Line-up ansehen"). Die Knoepfe stehen deshalb nicht mehr ueber die volle
     Breite, sondern zentriert mit Abstand zum rechten Rand. */
.live80-v2 .oberhausen-hero .hero-actions{width:100%;flex-direction:column;align-items:center;gap:var(--s3)}
.live80-v2 .oberhausen-hero .hero-actions .btn{width:min(100%,300px)}
/* Luft nach unten, damit der Chat-Knopf nicht auf dem letzten Button liegt. */
.live80-v2 .oberhausen-hero .hero-inner{padding-bottom:var(--s8)}}
/* Unter 780px steht der Abriss UNTER dem Hauptteil – nebeneinander bliebe fuer
   die Ueberschrift keine Breite. Perforation und Aussparungen drehen mit. */
@media (max-width:780px){.live80-v2 .ticket{grid-template-columns:1fr;--perf:150px;
    -webkit-mask-image:
      radial-gradient(20px 20px at 0 calc(100% - var(--perf)),transparent 19px,#000 20px),
      radial-gradient(20px 20px at 100% calc(100% - var(--perf)),transparent 19px,#000 20px);
            mask-image:
      radial-gradient(20px 20px at 0 calc(100% - var(--perf)),transparent 19px,#000 20px),
      radial-gradient(20px 20px at 100% calc(100% - var(--perf)),transparent 19px,#000 20px)}
.live80-v2 .tk-main{padding:var(--s8) var(--s5)}
/* ⚠️ KEINE feste Hoehe. Sie stand hier auf 150px, der Inhalt brauchte aber
     199px – mit align-content:center lief er nach OBEN aus dem Abriss heraus,
     "Admit One" stand dadurch oberhalb der Trennlinie (gemessen: 22px zu hoch).
     Die Hoehe kommt jetzt aus dem Inhalt, und die Perforation richtet sich
     danach (siehe --perf-Abgleich im Skript). */
.live80-v2 .tk-stub{border-left:0;border-top:2px dashed rgba(255,255,255,.35);
    grid-auto-flow:row;padding:var(--s5) var(--s4)}
.live80-v2 .tk-code{width:150px;height:40px}}
/* --- Lichteffekte ---------------------------------------------------------
   🔴 Alle drei arbeiten AUSSCHLIESSLICH mit transform und opacity. Kein
   animiertes blur(), keine Filter, kein background-attachment:fixed – genau
   diese drei waren die belegten Bremsklötze dieses Projekts (iPhone 15,3 s,
   siehe CLAUDE.md "Mobil-Performance" und "Desktop wurde langsam").
   Der weiche Schein kommt aus Verlaeufen und box-shadow, nicht aus Filtern. */
/* Kamerablitze im Stadion. Die <i> erzeugt das Skript mit Zufallspositionen. */
.live80-v2 .flashes{position:absolute;inset:0;z-index:1;pointer-events:none;overflow:hidden}
.live80-v2 .flashes i{position:absolute;width:5px;height:5px;border-radius:50%;
  background:#fff;box-shadow:0 0 10px 3px rgba(255,255,255,.9),0 0 22px 8px rgba(255,220,255,.45);
  opacity:0;animation:flash 9s linear infinite}
/* Sehr kurzer Blitz, lange Pause – ein Dauerflackern saehe nach Defekt aus. */
@keyframes flash{
  0%,100%{opacity:0;transform:scale(.6)}
  1.2%{opacity:1;transform:scale(1)}
  3%{opacity:0;transform:scale(.7)}
  46%{opacity:0}
  47%{opacity:.85;transform:scale(.95)}
  49%{opacity:0}
}
/* Zwei Flutlichtkegel aus den oberen Ecken. */
.live80-v2 .floods{position:absolute;inset:0;z-index:1;pointer-events:none;overflow:hidden}
.live80-v2 .floods .fl{position:absolute;top:-18%;width:44vw;height:135%;
  background:linear-gradient(to bottom,rgba(255,255,255,.16),rgba(255,45,149,.09) 45%,transparent 78%);
  -webkit-mask-image:linear-gradient(to bottom,#000,transparent 82%);
          mask-image:linear-gradient(to bottom,#000,transparent 82%);
  transform-origin:50% 0;mix-blend-mode:screen;opacity:.8}
.live80-v2 .floods .fl-l{left:-8vw;animation:flood-l 13s ease-in-out infinite alternate}
.live80-v2 .floods .fl-r{right:-8vw;animation:flood-r 16s ease-in-out infinite alternate}
@keyframes flood-l{from{transform:rotate(9deg)}to{transform:rotate(20deg)}}
@keyframes flood-r{from{transform:rotate(-20deg)}to{transform:rotate(-9deg)}}
/* Buehnenstrahler ueber dem Line-up – von LINKS und RECHTS, nicht von einer
   Traverse (Kundenvorgabe 28.07. auf der Startseite). */
.live80-v2 .lineup-sec{position:relative;overflow:hidden}
.live80-v2 .stagelights{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.live80-v2 .stagelights .sl{position:absolute;top:-14%;width:38vw;height:128%;
  transform-origin:50% 0;mix-blend-mode:screen;opacity:.75;
  -webkit-mask-image:linear-gradient(to bottom,#000,transparent 76%);
          mask-image:linear-gradient(to bottom,#000,transparent 76%)}
.live80-v2 .stagelights .sl-l{left:-10vw;
  background:linear-gradient(to bottom,rgba(255,45,149,.5),rgba(255,45,149,.14) 42%,transparent 74%);
  animation:sl-l 11s ease-in-out infinite alternate}
.live80-v2 .stagelights .sl-r{right:-10vw;
  background:linear-gradient(to bottom,rgba(38,224,255,.42),rgba(38,224,255,.12) 42%,transparent 74%);
  animation:sl-r 14s ease-in-out infinite alternate}
@keyframes sl-l{from{transform:rotate(12deg)}to{transform:rotate(26deg)}}
@keyframes sl-r{from{transform:rotate(-26deg)}to{transform:rotate(-12deg)}}
.live80-v2 .lineup-sec>.wrap{position:relative;z-index:2}
/* Suchscheinwerfer, der einmal quer durch den Hero faehrt und dann pausiert.
   ⚠️ Bewusst ein schraeger Verlaufsstreifen, der per translateX wandert –
   nicht per left/width, das waere ein Layout-Durchlauf je Bild. */
.live80-v2 .sweep{position:absolute;top:-20%;left:0;width:26vw;height:150%;z-index:1;
  pointer-events:none;mix-blend-mode:screen;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.15) 42%,
             rgba(255,120,220,.22) 55%,transparent);
  transform:skewX(-14deg) translateX(-40vw);
  animation:sweep 9s cubic-bezier(.5,0,.5,1) infinite}
@keyframes sweep{
  0%{transform:skewX(-14deg) translateX(-40vw)}
  38%,100%{transform:skewX(-14deg) translateX(135vw)}
}
/* Nur Bewegung abschalten – die Kegel bleiben als ruhiges Licht stehen,
   sonst wirkt der Hero ploetzlich leer. */
@media (prefers-reduced-motion:reduce){.live80-v2 .flashes i,.live80-v2 .floods .fl,.live80-v2 .stagelights .sl,.live80-v2 .sweep{animation:none}
.live80-v2 .flashes i{opacity:.5}
.live80-v2 .sweep{opacity:0}}
/* Auf dem Handy weniger gleichzeitige Ebenen – der Hero ist dort schmal, die
   Kegel ueberlagern sich sonst zu einem hellen Schleier ueber der Headline. */
@media (max-width:700px){.live80-v2 .floods .fl{width:70vw;opacity:.55}
.live80-v2 .stagelights .sl{width:64vw;opacity:.6}
.live80-v2 .sweep{display:none}}
/* ⚠️ Die Countdown-Uhr hat vier Einheiten mit je min-width:76px – zusammen mit
   den Abstaenden 340 px. Auf einem 320-px-Geraet stehen aber nur 272 px zur
   Verfuegung, die Uhr wurde am rechten Rand abgeschnitten (gemessen).
   Unterhalb 400 px teilen sich die vier Kaesten deshalb die vorhandene Breite.
   ⚠️ Dieselbe Stelle betrifft auch die Startseite – dort steht die Uhr im
   gemeinsamen Designsystem und ist NICHT mitgeaendert (waere ein Eingriff in
   eine abgenommene Seite). Als offener Punkt in der CLAUDE.md vermerkt. */
@media (max-width:400px){.live80-v2 .clock{gap:var(--s2);width:100%}
.live80-v2 .clock-unit{min-width:0;flex:1;padding:var(--s3) 4px}
.live80-v2 .clock-lbl{letter-spacing:.12em}}
/* ===========================================================================
   22. TIPPZIELE
   ---------------------------------------------------------------------------
   🔴 Bedingung ist das EINGABEGERAET, nicht die Breite: ein Tablet mit 900px
   wird genauso mit dem Finger bedient wie ein Handy. Mit `max-width:700px`
   allein blieben dort 26 Ziele unter 44px (gemessen bei 768 und 1024).
   =========================================================================== */
@media (hover:none),(max-width:1000px){/* Tippziele. Gemessen bei 375px: die Namen im Band "LIVE MIT" waren 26px
     hoch, die Karussellpunkte 26x10, die Fusszeilen-Links 18px – alle unter
     den 44px, die eine Fingerkuppe braucht. Vergroessert wird die FLAECHE,
     nicht die Optik: Schriftgroesse und Punktgroesse bleiben unveraendert.
     ⚠️ Dieselben drei Stellen betreffen auch die Startseite; sie stehen dort
     im gemeinsamen Designsystem und sind hier NICHT mitgeaendert (das waere
     ein Eingriff in eine abgenommene Seite). Steht als offener Punkt. */
.live80-v2 .names button{padding:9px .2em;min-height:44px}
/* 🔴 2026-08-07 UMGEZOGEN: Die Karussellpunkte standen hier — und damit NUR
     hier. Sie erbten dadurch nur nach unten (Hamburg, Cruise, Oberhausen leiten
     aus dieser Datei ab), waehrend die Startseite bei 10x10 blieb. Genau die
     Mechanik von Checkliste 274. Die Regel steht jetzt im gemeinsamen
     Designsystem (`startseite-redesign-v3.html`, direkt hinter `.car-dots`)
     und gilt fuer alle fuenf Seiten. Hier bewusst NICHT wiederholt: eine
     zweite Fassung wuerde die erste ueberschreiben und den Fehler neu anlegen.
     ⚠️ Dabei kam ein `border:0` dazu, das hier gefehlt hat — ohne den Reset trug
     die 22x44 grosse Flaeche den 1px-Rahmen der Grundregel weiter, und die
     Punktreihe sah aus wie eine Kette leerer Kaestchen. */
.live80-v2 .foot-legal a{display:inline-block;padding:12px 4px}}
/* --- Moderation --------------------------------------------------------------
   🔴 2026-08-07 aus `cruise-extra.css` HIERHER geholt. Sie lag nur im
   Cruise-Kapitel und erbte damit nur nach unten — als Koeln laut Plakat des
   Kunden ebenfalls eine Moderation bekam (Peter Illmann), waere sie dort
   ungestylt erschienen. Genau die Mechanik von Checkliste 274.
   Hier im gemeinsamen Eventkapitel gilt sie fuer Koeln, Hamburg, Cruise und
   Oberhausen.
   🔴🔴 KEIN `.live80-v2` VOR DIESE SELEKTOREN SCHREIBEN. Diese Datei ist die
   UNGESCOPTE Quelle — `scope-css-*.py` haengt den Scope selbst davor. Genau
   dieser Praefix stand hier vom 2026-08-07 bis zum selben Tag und erzeugte
   `.live80-v2 .live80-v2 .moderation`: ein Selektor, der NIE greift, weil die
   Klasse nur einmal am <body> haengt. Peter Illmanns Portraet lief dadurch auf
   Koeln, Cruise und Oberhausen von 74x74 auf 920x500 px auf — im Frontend UND
   im Mockup. → Checkliste 305

   ✅ 2026-08-07 bereinigt: Cruise und Oberhausen trugen sie in ihrem eigenen
   Kapitel ein zweites Mal mit zeichengleichen Werten. Beide Dubletten sind
   entfernt — DIES HIER IST JETZT DIE EINZIGE STELLE. Wer die Moderation
   aendert, aendert sie hier, und alle vier Eventseiten ziehen mit. */
.live80-v2 .moderation{
  display: flex; align-items: center; gap: var(--s5);
  justify-content: center;
  margin: var(--s7) auto 0;
  width: fit-content;
  max-width: 100%;
  padding: var(--s4) var(--s6) var(--s4) var(--s4);
  border-radius: var(--r-pill);
  background: rgba(var(--c-shadow-deep), .72);
  border: 1px solid rgba(255, 217, 61, .34);
  box-shadow: 0 16px 40px rgba(var(--c-shadow), .45);
}
.live80-v2 .mod-portrait{
  flex: none;
  width: 74px; height: 74px;
  border-radius: 50%;
  overflow: hidden;
  border: 3px solid rgba(255, 217, 61, .85);
  background: #0a0420;
  box-shadow: var(--glow-gold);
}
.live80-v2 .mod-portrait img{
  width: 100%; height: auto; display: block;
  transform: scale(1.62) translateY(13%);
}
.live80-v2 .mod-text{ display: grid; gap: 2px; text-align: left; }
.live80-v2 .mod-label{
  font-family: 'Core Sans M', 'Asap', sans-serif;
  font-size: var(--fs-xs); letter-spacing: .3em; text-transform: uppercase;
  color: var(--c-gold); text-shadow: var(--glow-gold);
}
.live80-v2 .mod-name{
  font-family: 'Core Sans M', 'Asap', sans-serif;
  font-size: var(--fs-lg); font-weight: 800; letter-spacing: .03em;
  color: #fff; line-height: 1.1;
}
@media (max-width:700px){.live80-v2 .moderation{
    flex-direction: column; text-align: center;
    border-radius: var(--r-lg);
    padding: var(--s5) var(--s5) var(--s6);
  }
.live80-v2 .mod-text{ text-align: center; justify-items: center; }}

/* ---- WordPress-Bruecke OBERHAUSEN (nicht aus dem Mockup, siehe scope-css-oberhausen.py) ---- */

/* (a) `core/image` schiebt eine <figure> zwischen Container und <img>.
   Bei diesen zielen die Mockup-Regeln auf das <img> INNERHALB eines absolut
   positionierten Containers — die Figur dazwischen wuerde die Groessenkette
   unterbrechen. `display:contents` loest sie auf.
   ⚠️ `.mod-portrait` steht hier MIT, anders als in Hamburg: die Moderation
   gibt es dort nicht, und ohne diese Zeile sitzt das Portraet in einer
   <figure>, die den runden Rahmen sprengt. */
.live80-v2 .oberhausen-skyline figure.wp-block-image,
.live80-v2 .mod-portrait figure.wp-block-image,
.live80-v2 .venue-illu figure.wp-block-image{display:contents}

.live80-v2 .oberhausen-logo img{width:100%;height:auto;display:block}

/* (b) Die Knoepfe. `.wp-block-button.btn` ist in der Basis geregelt; hier nur
   die Container, die es im Mockup nicht gab.
   🔴 `.hero-actions` MUSS `justify-content:center` tragen — ein
   `core/buttons`-Container ist ein Flex-Container, und das `text-align:center`
   des Elternteils erreicht ihn NICHT (Checkliste 247, das war „der Button
   haengt links"). */
.live80-v2 .hero-actions.wp-block-buttons{
  display:flex;gap:var(--s4);flex-wrap:wrap;justify-content:center}
.live80-v2 .wp-block-buttons.tk-cta,
.live80-v2 .wp-block-buttons.outro-cta{display:contents}

/* (c) Inline-`style=""` aus dem Mockup, jetzt als Klasse.
   ⚠️ SPEZIFITAET: als blosse Klasse verlieren diese Groessen gegen
   `.sec-head .display` (0,2,0) — deshalb hier mit derselben Tiefe. */
.live80-v2 .lineup-sec .sec-head .display.lineup-h,
.live80-v2 .faq-sec .sec-head .display.faq-h{font-size:var(--fs-2xl)}
.live80-v2 .lineup-sec .sec-head .lead.lineup-lead,
.live80-v2 .faq-sec .sec-head .lead.faq-lead{font-size:var(--fs-md)}
.live80-v2 .names-sec .eyebrow{text-align:center}

/* „Rudolf-Weber-<strong>ARENA</strong>" — ein Inline-`style` macht den Block
   ungueltig. `<strong>` ist ein registriertes Inline-Format. */
.live80-v2 .oberhausen-venue strong{font-weight:inherit;color:#fff}

/* 🔴 KEIN Abstands-Reset auf die Ueberschriften — siehe die ausfuehrliche
   Begruendung in scope-css-koeln.py (Checkliste 199). Ein Reset
   „vorsichtshalber" schlaegt den gewollten negativen Abstand aus `.chrome`
   und machte die Ticket-Sektion 8 px zu hoch. */

/* Der Hero ist ein Grid mit `gap`; die Absaetze duerfen keine eigenen Abstaende
   mitbringen. Im Mockup hatte `.hero-inner > *` das ueber den Reset. */
.live80-v2 .oberhausen-hero .hero-inner > p{margin:0}

/* ⚠️ Die Ueberschrift der Arena-Sektion: die Rampe aus dem Koeln-Kapitel ist an
   „RHEINENERGIESTADION" ausgemessen (19 Zeichen, EIN Wort). „RUDOLF-WEBER-
   ARENA" ist mit 18 Zeichen kuerzer, hat aber ZWEI Bindestriche und damit
   Umbruchstellen, die Koeln nicht hat — das ist eher entspannter als enger.
   Bei 375 px nachgemessen, kein Ueberlauf. Keine eigene Regel noetig.
   🔴 Wuerde die Spielstaette spaeter durch einen laengeren Namen ersetzt, hier
   nachmessen statt annehmen (Checkliste 260: eine an wenigen Zeichen
   ausgemessene Rampe bricht bei mehr). */

/* ---------- Teil 3: nur Oberhausen (Moderation, Platzhalter) ---------- */
/* ==========================================================================
   OBERHAUSEN — Kapitel-CSS des neuen Looks
   --------------------------------------------------------------------------
   ERGAENZT `live80-v2.css` (Designsystem) und wird NUR auf Seiten mit
   `_live80_v2_seite = oberhausen` geladen. Alles hier ist unter `.live80-v2`
   gescopt; die Tokens (--c-*, --fs-*, --s*, --r-*) kommen aus der Basis.

   🔴 DIESE DATEI IST HANDGESCHRIEBEN UND BEREITS GESCOPT.
   Sie laeuft NICHT durch den Scoper — `scope-css-oberhausen.py` prueft nur,
   dass jede Regel darin den Scope schon traegt. Das gemeinsame
   Eventseiten-Kapitel (Hero-Kulisse, Kamerablitze, Flutlicht,
   Suchscheinwerfer, Buehnenstrahler, Illustrations-Sektion, Textpanel,
   Ticket-Abschluss) wird dort aus `koeln-extra.css` abgeleitet — es steht
   NICHT hier.

   WAS HIER NEU IST — und wie wenig es ist
   Oberhausen ist strukturell die naechste Verwandte von Koeln und Hamburg:
   ein Termin, eine Arena, ein Ticketziel. Es entfaellt alles, was die Cruise
   ausmacht (Trailer, Route, Schiff) und alles, was Hamburg ausmacht (Anreise
   OEPNV, Anreise Auto, Partybus) — zu beidem gibt die Quelle nichts her.
   Uebrig bleiben ZWEI Formen:

   1. MODERATION — Peter Illmann. Wortgleich aus `cruise-extra.css`
      uebernommen (der einzige andere Termin mit Moderation), damit dieselbe
      Person auf beiden Seiten gleich aussieht.
   2. PLATZHALTER-BADGE — fuer die zwei Acts ohne Pressefoto.

   🔴 ZUM PLATZHALTER, damit ihn niemand fuer ein Versehen haelt
   Bad Boys Blue und Thompson Twins' Tom Bailey haben in KEINER der 527
   Mediathek-Dateien ein Bild (am 2026-08-07 vollstaendig durchsucht). Statt
   ein KI-„Foto" realer Personen zu erzeugen — das waere ein Deepfake nach
   Art. 3(60) EU AI Act und obendrein eine Falschdarstellung der Kuenstler —
   tragen diese beiden Karten eine erkennbar GEOMETRISCHE Grafik: Initialen
   auf Neonringen, in der Farbfamilie der echten Badges. Sobald Pressefotos
   vorliegen, ist es ein reiner Bildtausch, keine Codeaenderung.
   ⚠️ Die Regel unten haengt an der Klasse `act-badge--offen` am <figure>,
   NICHT an der Position der Karte — Umsortieren im Editor ist damit sicher.
   ========================================================================== */


/* --- Moderation ----------------------------------------------------------
   🔴 STEHT NICHT MEHR HIER. Die Regeln (`.moderation`, `.mod-portrait`,
   `.mod-text`, `.mod-label`, `.mod-name` samt Mobil-Block) liegen seit dem
   2026-08-07 im gemeinsamen Eventkapitel `_source/mockups/koeln-extra.css`
   und kommen ueber `scope-css-oberhausen.py` von dort. Hier standen sie bis
   dahin ein zweites Mal mit ZEICHENGLEICHEN Werten — folgenlos, aber genau
   die Doppelpflege, an der dieses Projekt schon dreimal einen falschen Wert
   ausgeliefert hat (Checkliste 274, 301).
   ⚠️ Wer die Moderation aendern will, aendert `koeln-extra.css` — dann ziehen
   Koeln, Hamburg, Cruise und Oberhausen gemeinsam mit.
   ------------------------------------------------------------------------- */

/* --- Platzhalter-Badge ---------------------------------------------------
   🔴 KEIN eigener Zuschnitt. Die Grafik ist absichtlich so aufgebaut, dass
   sie denselben `scale(1.62) translateY(13%)`-Zuschnitt vertraegt wie die
   echten Badges: die Initialen sitzen im oberen Bilddrittel, die
   Namensplatte unten wird — wie bei allen anderen — weggeschnitten.
   Eine abweichende Transformation haette die zwei Karten aus dem Raster
   gehoben und den Platzhalter erst recht sichtbar gemacht.

   Der goldene Ring ist der einzige Unterschied: er markiert die Karte fuer
   UNS als „Foto fehlt noch", ohne dass es fuer Besucher nach einem Fehler
   aussieht. ⚠️ Beim Einsetzen der echten Fotos MIT ENTFERNEN — sonst bleibt
   eine Markierung stehen, deren Grund niemand mehr kennt.
   ------------------------------------------------------------------------- */
.live80-v2 .act-badge--offen { border-color: rgba(255, 217, 61, .55); }


/* --- Ortsname im Ticket-Abriss -------------------------------------------
   🔴 GEMESSEN, nicht geschaetzt. Der Abriss ist 190 px breit, abzueglich
   2x16 px Innenabstand bleiben 158 px. Die Basisregel `.tk-city` ist an
   „KÖLN" ausgemessen (4 Zeichen, 26 px, .12em Laufweite). „OBERHAUSEN" hat
   10 Zeichen und kam damit auf 200 px — das „N" war rechts ABGESCHNITTEN.
   Es ist der laengste Ortsname der ganzen Reihe.

   Dieselbe Falle wie bei der Cruise („NORWEGEN", Checkliste 260), und der
   dortige Fix stand seit dem 07.08. in `cruise-extra.css` — er ist beim
   Ableiten nur nie mitgekommen. Hier deshalb dieselbe Gegenrichtung:
   kleinere Schrift UND kleinere Laufweite (ein groesseres `letter-spacing`
   macht es breiter, nicht schmaler).

   ⚠️ Zum Vergleich der gemessenen Textbreiten bei 1920 px:
       KÖLN 81 · HAMBURG 148 · NORWEGEN 122 (nach Fix) · OBERHAUSEN 200 (vorher)
   Hamburg hat mit 148/158 nur noch 10 px Luft — ein noch laengerer Ortsname
   braucht hier ebenfalls eine eigene Rampe. Nachmessen statt annehmen.
   ------------------------------------------------------------------------- */
.live80-v2 .ticket-sec .tk-stub .tk-city {
  font-size: clamp(15px, .95vw, 18px);
  letter-spacing: .04em;
}
