/* ============================================================================
   Club Velvet Leipzig — Design und Layout
   ----------------------------------------------------------------------------
   Neubau im Clubmuster, Vorlage cosmopolar-hp: schwarzer Grund, weisse
   Schrift, Inter in Versalien, Akzent in Rot #910909 (Betreiber,
   03.11.2026; gleich der Akzentfarbe in Clubinio). Gerundete Kanten.

   Keine Inline-Styles. Die Content-Security-Policy fuehrt style-src 'self'
   ohne unsafe-inline; was aus der API kommt, wird als <img> oder
   textContent gesetzt, nie als style-Attribut.
   ========================================================================== */

/* ------------------------------------------------------------- Schriften -- */

/* Inter als variabler Schnitt: eine Datei fuer alle Gewichte von 100 bis
   900, 71 KB. Die drei Poppins-Schnitte brauchten zusammen 151 KB und
   deckten nur 400, 700 und 900 ab.

   Die Datei ist der Latin-Auszug des Inter-Projekts und deckt den gesamten
   Text dieser Seite ab — nachgezaehlt gegen Markup, Clubinio-Daten und
   config.js. Nicht enthalten sind Emoji; die kommen ohnehin immer aus der
   Systemschrift. Ebenso wenig enthalten ist der Pfeil U+2192, deshalb
   zeichnet das CSS ihn selbst (siehe `.knopf::after`).

   Die Poppins-Dateien bleiben vorerst liegen — ein Zurueck kostet dann nur
   diesen Block. */
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-var.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* Montserrat traegt die Display-Ebene: Ueberschriften, Navigation, Knoepfe
   und Etiketten. Inter bleibt fuer den Fliesstext.

   Zwei Familien mit klarer Aufgabenteilung — Montserrat ist als
   geometrische Display-Schrift gezeichnet und traegt grosse Versalien,
   Inter als Oberflaechenschrift und bleibt im Absatz ruhig. Zusammen
   105 KB, beide variabel. */
@font-face {
  font-family: 'Montserrat';
  src: url('../fonts/montserrat.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* Plakat-Fassung (Betreiber, 03.11.2026: „2026 urban"): Source Code Pro für Überschriften und Text
   (Kunde, 05.11.2026), davor Big Shoulders für die Überschriften. Gestaltungsrichtung „Loud
   and flat", Seed 2000821529 (.taste-skill/direction.json). Inter und
   Montserrat bleiben als Dateien liegen, werden aber nicht mehr geladen. */
@font-face {
  font-family: 'Big Shoulders';
  src: url('../fonts/big-shoulders-800-latin.woff2') format('woff2');
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Source Code Pro';
  src: url('../fonts/source-code-pro-var-latin.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ----------------------------------------------------------------- Token -- */

:root {
  /* Flaechen. Die Werte stammen aus dem Elementor-Kit der bestehenden Seite. */
  /* Seitengrund. **Nicht reines Schwarz.** Die bestehende Seite fuehrt
     durchgehend ein sehr dunkles Grau; reines #000 wirkt besonders auf
     OLED-Displays wie ein Loch, weil die Pixel dort wirklich aus sind und
     es keinerlei Abstufung zum Inhalt gibt. Ein paar Punkte Helligkeit
     geben der Flaeche Tiefe, ohne sie aufzuhellen. */
  --nacht:        #0b0b0e;   /* Seitengrund */
  --box:          #161616;   /* Karten, Kaesten */
  --box-hell:     #202020;   /* abgesetzte Flaeche in einer Box */
  --flaeche:      #181818;   /* Abschnittsgrund, wo er sich abheben soll */
  --karte:        #181818;   /* Eventkarten — Originalwert */
  --kopf:         #0e0e0e;   /* Kopfzeile, sobald sie deckend wird */
  --linie:        #2a2a2a;   /* Trenner und Rahmen */

  /* Schrift: zwei Ebenen mit klarer Aufgabe. */
  --schrift-display: 'Source Code Pro', ui-monospace, Menlo, Consolas, monospace;
  --schrift-text:    'Source Code Pro', ui-monospace, Menlo, Consolas, monospace;

  /* Schrift. */
  --tinte:        #ffffff;
  --tinte-leise:  #b4b4b4;
  /* #7d7d7d der Vorlage kam auf dem Infokasten der Eventseite (#17171a) nur
     auf 4,34 : 1; #878787 erreicht 4,98 : 1 dort und 4,54 : 1 auf #202020
     (gemessen 03.11.2026). */
  --tinte-still:  #878787;

  /* Akzent der Marke. */
  --akzent:       #910909;
  /* Schrift auf dem Akzent — Weiss, 9,35 : 1 auf #910909.
     **Bewusste Ausnahme:** Als Schriftfarbe auf dem dunklen Grund erreicht
     #910909 nur 2,12 : 1 (AA verlangt 4,5 : 1). Der Betreiber hat das
     Rot trotzdem auch fuer Schrift-Akzente festgelegt (03.11.2026,
     .auftrag.md A9). tools/kontrast.js fuehrt diese Paare als Ausnahme. */
  --akzent-tinte: #ffffff;

  /* Rundungen. Gestaffelt nach Flaechengroesse — ein einheitlicher Radius
     laesst kleine Elemente verspielt und grosse Flaechen hart wirken. */
  /* Plakat-Fassung: überall eckig, ein Maß für die ganze Seite. */
  --r-knopf:      0;
  --r-feld:       0;
  --r-karte:      0;
  --r-klein:      0;
  /* Hoehe des Abschnitts unter der Perforation. Kerben und Trennlinie
     haengen beide daran — ein Wert, damit sie nicht auseinanderlaufen. */
  --abriss:       46px;

  /* Weiche Schatten statt Rahmen, wo etwas abheben soll. */
  /* Plakat-Fassung: keine Schatten, Flächen trennt ein Tonschritt. */
  --schatten:     none;
  --schatten-hoch: none;

  /* Uebergang mit leichtem Ueberschwingen — nicht linear, nicht traege. */
  --kurve:        cubic-bezier(0.32, 0.72, 0, 1);
  --kurve-weich:  cubic-bezier(0.22, 0.61, 0.36, 1);

  /* Haken fuer die eigenen Kaestchen. Als data:-Adresse im Stylesheet und
     nicht als eigene Datei: 200 Byte sind keinen zweiten Abruf wert. */
  --haken: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%230b0b0e' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round' d='M3.2 8.6l3.1 3.1 6.5-6.9'/%3E%3C/svg%3E");

  /* Masse. */
  --breite:       1200px;
  --breite-schmal: 760px;
  --gutter:       clamp(1rem, 4vw, 2.5rem);
  /* Hoehe der Kopfzeile. Hero, Bannerversatz, Menue und Ankersprung
     rechnen damit — weicht der Wert von der tatsaechlichen Hoehe ab,
     verschiebt sich der Inhalt um die Differenz.

     **Zwei Werte, weil die Zeile nicht ueberall gleich hoch ist.** Ihre
     Hoehe ergibt sich aus dem hoechsten Kind plus Polster: auf dem
     Schreibtisch das Logo (46px), auf dem Telefon der Menueknopf (44px).
     Mit einem einzigen Wert klaffte zwischen Kopfzeile und aufgeklapptem
     Menue eine Luecke von 2px, durch die das Bild schien.
     Nachgemessen: 82px / 80px. */
  --kopf-hoehe:   82px;

  /* Typografie. Die Skala ist die der bestehenden Seite (36/50/60/85 px),
     hier als clamp(), damit sie auf dem Telefon nicht ueberlaeuft. */
  /* Plakat-Fassung: fünf Stufen. Source Code Pro läuft breit, die Display-
     Stufen sind deshalb kleiner als zu Zeiten von Big Shoulders. */
  --t-hero:   clamp(5.5rem, 15vw, 14rem);
  --t-h1:     clamp(2.25rem, 7vw, 6rem);
  --t-h2:     clamp(2.25rem, 6vw, 5.5rem);
  --t-h3:     clamp(1.125rem, 1rem + 0.5vw, 1.5rem);
  --t-text:   clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem);
  --t-klein:  0.875rem;
}

/* --------------------------------------------------------------- Grundlage -- */

*, *::before, *::after { box-sizing: border-box; }

/* Sicherheitsnetz gegen seitliches Verschieben. Die randlose Bildstrecke
   rechnet die Scrollleiste bereits heraus (`--sb`); das hier faengt ab, was
   kuenftig dazukommt, ohne dass es jemandem auffaellt.

   `clip`, nicht `hidden`: `overflow: hidden` an einem Vorfahren setzt
   `position: sticky` ausser Kraft, und die Kopfzeile klebt. */
html, body { overflow-x: clip; }

/* `hidden` muss gewinnen. Der Browser setzt dafuer nur `display: none` mit
   schwacher Spezifitaet — jede eigene display-Regel schlaegt es. Genau das
   ist passiert: `.knopf { display: inline-flex }` hat ein `hidden` am
   Lounge-Knopf ueberstimmt, und der stand auf jeder Eventseite, obwohl ihn
   nichts eingeblendet hatte. */
[hidden] { display: none !important; }

html {
  scroll-behavior: smooth;
  /* Anker sollen nicht unter der festen Kopfzeile landen. */
  scroll-padding-top: calc(var(--kopf-hoehe) + 1rem);
}

/* Wer Bewegung abbestellt hat, bekommt auch kein sanftes Scrollen. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--nacht);
  color: var(--tinte);
  font-family: var(--schrift-text);
  font-size: var(--t-text);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* Menue offen oder Lightbox aktiv: der Hintergrund darf nicht mitscrollen. */
html.menu-offen, html.lb-aktiv { overflow: hidden; }

img, video { max-width: 100%; height: auto; display: block; }

a { color: inherit; text-decoration: none; }
a:focus-visible, button:focus-visible, summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--akzent);
  outline-offset: 3px;
}

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--schrift-display);
  font-weight: 800;
  line-height: 1;
  text-transform: uppercase;
  /* Source Code Pro läuft breit: Ohne negative Sperrung zerfallen lange
     Versalüberschriften in Einzelbuchstaben. */
  letter-spacing: -0.04em;
}

p { margin: 0 0 1rem; }
p:last-child { margin-bottom: 0; }

/* Nur fuer Lesegeraete — etwa die H1 der Startseite. */
.nur-sr {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.sprung {
  position: absolute;
  left: -9999px;
  z-index: 100;
  padding: 0.75rem 1.25rem;
  background: var(--akzent);
  color: var(--akzent-tinte);
  font-weight: 700;
}
.sprung:focus { left: 1rem; top: 1rem; }

/* ---------------------------------------------------------------- Raster -- */

.huelle {
  width: 100%;
  max-width: var(--breite);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.huelle-schmal { max-width: var(--breite-schmal); }

.abschnitt { padding-block: clamp(3.5rem, 9vw, 7rem); }
.abschnitt-flaeche { background: var(--flaeche); }

/* Der Eventabschnitt liegt im Original auf einem Clubfoto mit dunklem
   Schleier (Deckung 0,48). Das Bild steht im CSS und nicht als <img> im
   Markup, weil es Zierde ist und keinen Inhalt traegt. */
/* Abschnittskopf: Ueberschrift plus Unterzeile, zentriert. */
.kopfzeile { text-align: center; margin-bottom: clamp(2rem, 5vw, 3.5rem); }
.kopfzeile h2 { font-size: var(--t-h2); }
.kopfzeile p {
  margin: 0.75rem 0 0;
  color: var(--tinte-leise);
  text-transform: none;
}
/* Die Unterzeilen unter „Next Events" und „Einblick" stehen im Original in
   der Akzentfarbe, nicht gedaempft. */
.kopfzeile .unterzeile { color: var(--akzent); font-weight: 400; }

/* ---------------------------------------------------------------- Knoepfe -- */

.knopf {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.85rem 1.75rem;
  border: 1.5px solid var(--akzent);
  border-radius: var(--r-knopf);
  background: var(--akzent);
  color: var(--akzent-tinte);
  font: inherit;
  font-family: var(--schrift-display);
  font-weight: 800;
  font-size: var(--t-klein);
  text-transform: uppercase;
  /* Weniger Sperrung als vorher: in der Pille wirkt enge Laufweite ruhiger. */
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: transform 0.25s var(--kurve), box-shadow 0.25s var(--kurve),
              background 0.2s ease, color 0.2s ease;
}
.knopf:hover {
  background: transparent;
  color: var(--akzent);
  transform: translateY(-1px);
  box-shadow: var(--schatten);
}
/* Beim Druecken wieder herunter — das macht den Knopf greifbar. */
.knopf:active { transform: translateY(0) scale(0.98); box-shadow: none; }

/* Pfeil am Ende, wie bei allen Knoepfen des Originals. Als ::after und nicht
   im Markup: eine Zierde gehoert nicht in den Quelltext, und Lesegeraete
   sollen „Alle Events ansehen" vorlesen, nicht „Alle Events ansehen Pfeil".

   **Gezeichnet, nicht gesetzt.** Inter fuehrt U+2192 nicht; als Textzeichen
   fiele der Pfeil auf die Systemschrift zurueck und passte in Strichstaerke
   und Groesse nicht zur Beschriftung daneben. Als Maske uebernimmt er
   `currentColor` und skaliert mit der Schriftgroesse. */
.knopf::after {
  content: '';
  width: 1em;
  height: 1em;
  flex: none;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h12.2l-4.6-4.6L14 6l6 6-6 6-1.4-1.4 4.6-4.6H5v-2Z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h12.2l-4.6-4.6L14 6l6 6-6 6-1.4-1.4 4.6-4.6H5v-2Z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.knopf-ohne-pfeil::after { content: none; }

/* Der Ticketknopf traegt im Original ein Ticketsymbol vorn statt des
   Pfeils am Ende. */
.knopf-ticket::after { content: none; }
.knopf-ticket::before { content: '\1F39F'; margin-right: 0.15rem; }

.knopf-leer {
  background: transparent;
  color: var(--tinte);
  /* Gedaempfter Rahmen statt voller Kontrast — ein zweiter Knopf soll den
     ersten nicht ueberschreien. */
  border-color: rgb(255 255 255 / 35%);
}
.knopf-leer:hover {
  background: var(--tinte);
  color: var(--nacht);
  border-color: var(--tinte);
}

.knopf[disabled] { opacity: 0.5; cursor: not-allowed; }
.knopf[disabled]:hover { background: var(--akzent); color: var(--akzent-tinte); }

.knopf-reihe {
  display: flex;
  flex-wrap: wrap;
  gap: 0.875rem;
}

/* Die Absendeknoepfe laufen im Original ueber die volle Formularbreite. */
.form .knopf-reihe { display: block; }
.form .knopf-reihe .knopf { width: 100%; }

.icon { flex: none; }

/* ---------------------------------------------------------------- Kopf --- */

.kopf {
  position: sticky;
  top: 0;
  z-index: 50;
  background: transparent;
  isolation: isolate;
  transition: background 0.25s ease;
}

/* Ueber dem Hero steht die Zeile frei im Bild. Sobald gescrollt wird,
   bekommt sie einen Grund — darunter liegen Text und Karten, und ohne
   Grund staende die Schrift mitten darin.

   **Nur die Farbe aendert sich, nicht die Hoehe.** Eine klebende Zeile
   belegt weiterhin ihren Platz im Fluss; aenderte sich dabei die Hoehe,
   ruckte der gesamte Inhalt darunter. */
.kopf[data-fest='ja'] {
  background: rgb(11 11 14 / 92%);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

/* **Weichzeichner aus, solange das Menue offen ist.** Nicht aus Geschmack,
   sondern weil `backdrop-filter` — wie `transform`, `filter` und
   `perspective` — einen umgebenden Block fuer `position: fixed` erzeugt.
   `.menu` liegt im Markup innerhalb von `.kopf`; mit Weichzeichner bezieht
   sich sein `inset: var(--kopf-hoehe) 0 0` nicht mehr auf das Sichtfeld,
   sondern auf die 80 Pixel hohe Kopfzeile. Das Menue war dann 64 statt
   764 Pixel hoch und der Seiteninhalt schien darunter durch — aber nur im
   gescrollten Zustand, weil `data-fest` erst dort gesetzt wird.

   Die Zeile darueber gibt der Kopfzeile bei offenem Menue ohnehin eine
   deckende Flaeche; der Weichzeichner hat dann nichts mehr zu tun. */
.kopf[data-offen='ja'] {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* Die Leiste darunter ist halbdurchsichtig, damit das Bild durchscheint —
   deckend wuerde sie zusammen mit dem Streifen daruber einen dicken Block
   ergeben. */
/* Kein Grund, kein Schatten — die Zeile steht frei im Bild. Stattdessen
   Luft nach oben: Sie rueckt vom Fensterrand weg und bekommt Raum, statt
   sich mit einer Flaeche vom Bild abzusetzen.

   Oben mehr als unten, damit die Zeile optisch nicht klebt und der Blick
   trotzdem zuerst aufs Bild faellt. */
.kopf-innen {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 56px;
  padding-top: 1.75rem;
  padding-bottom: 0.5rem;
  transition: padding 0.25s ease;
}

/* Gescrollt sitzt die Schrift mittig in der Leiste statt tief darin. Oben
   steht sie frei im Bild und darf nach unten haengen; auf einem Grund
   wirkt dieselbe Asymmetrie wie ein Fehler.

   **Die Summe bleibt gleich** (28+8 oben, 18+18 gescrollt — beides 36px).
   Eine klebende Zeile belegt weiter ihren Platz im Fluss; aenderte sich
   die Hoehe, ruckte der gesamte Inhalt darunter beim Umschalten. */
.kopf[data-fest='ja'] .kopf-innen {
  padding-top: 1.125rem;
  padding-bottom: 1.125rem;
}

/* `.huelle` begrenzt die Breite, die Flaeche soll aber ueber die ganze
   Fensterbreite laufen. Statt der Begrenzung uebernimmt das Polster die
   Zentrierung: Es ist so breit wie der Rand neben der Inhaltsspalte, und
   faellt nie unter den Seitenabstand.

   **Ohne `+ var(--gutter)`.** Mit dem Zuschlag war die Leiste 80px
   schmaler als der Inhalt darunter — die Marke stand 40px weiter innen
   als alles auf der Seite und die Zeile wirkte verzogen. */
.kopf-innen {
  max-width: none;
  padding-inline: max(var(--gutter), calc((100% - var(--breite)) / 2));
}

.logo { display: flex; align-items: center; }
/* Auf dem Telefon deutlich kleiner — bei voller Groesse nimmt die Wortmarke
   dort die halbe Kopfzeile ein. */
.logo img { height: 46px; width: auto; }
@media (max-width: 899px) {
  .logo img { height: 34px; }
}

.menu-knopf {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 6px;
  /* 44px bleibt die Trefferflaeche — die Balken sind schmaler. Ohne eigene
     Breite zogen sie sich auf die vollen 44px und das Kreuz wirkte wie ein
     Scheibenwischer. */
  width: 44px; height: 44px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}
.menu-knopf span {
  display: block;
  width: 26px;
  height: 2px;
  border-radius: 2px;
  background: var(--tinte);
  transition: transform 0.28s var(--kurve), opacity 0.2s ease;
}
/* 8px = halbe Balkenhoehe plus Abstand — so treffen sich beide in der Mitte. */
.kopf[data-offen='ja'] .menu-knopf span:nth-child(1) { transform: translateY(8px) rotate(45deg); }
.kopf[data-offen='ja'] .menu-knopf span:nth-child(2) { opacity: 0; transform: scaleX(0.4); }
.kopf[data-offen='ja'] .menu-knopf span:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }

.menu ul {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.2vw, 1.75rem);
  margin: 0; padding: 0;
  list-style: none;
}

/* Keine Trennstriche. Sie stammen aus der fruheren Vollbreitenleiste, wo
   sie Ordnung in eine lange Zeile brachten. In der Pille zerhacken sie den
   knappen Raum — der Entwurf kommt ohne sie aus. */
@media (min-width: 900px) {
  /* Drei Spalten mit gleich breiten Aussenspalten — nur so stehen die
     Punkte wirklich mittig in der Pille. Mit `space-between` verteilten
     sie sich zwischen schmalem Logo und breitem Knopf und landeten
     rechts; die Marke wirkte dadurch eingequetscht.

     Die dritte Spalte bleibt leer: Sie haelt den Platz, den die Marke
     links einnimmt, und haelt damit die Mitte. */
  /* Punkte rechtsbuendig. Die Grundregel traegt das bereits
     (`justify-content: space-between` mit Marke und Navigation als
     einzigen Kindern) — hier stand vorher eine Rasterueberschreibung fuer
     die mittige Fassung. */
  .menu li { display: flex; align-items: center; }

}

.menu a {
  font-family: var(--schrift-display);
  font-size: 1rem;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding-block: 0.5rem;
  transition: color 0.15s ease;
}
/* Keine Unterstreichung — weder fest noch beim Darueberfahren. Der aktive
   Punkt ist eingefaerbt, das genuegt als Signal. */
.menu a:hover { color: var(--akzent); }
.menu a[aria-current='page'] { color: var(--akzent); }

/* Der Menuefuss gehoert nur ins aufgeklappte Menue auf schmalen Geraeten.
   Ohne diese Zeile laeuft er auf dem Schreibtisch ungestaltet im Fluss
   unter den Punkten mit — dort gibt es kein Vollbildmenue, in das er
   gehoerte. Die Mobilabfrage schaltet ihn wieder ein. */
.menu-fuss { display: none; }

/* Schmale Geraete: das Menue fuellt den Bildschirm. */

@media (max-width: 899px) {
  :root { --kopf-hoehe: 80px; }

  /* Solange das Menue offen ist, muss die Kopfzeile decken. Auf der
     Startseite ist sie ueber dem Hero durchsichtig — ohne das hier stand
     ueber dem Menue ein Streifen, durch den das Hero-Video schien. */
  .kopf[data-offen='ja'] { background: var(--kopf); }

  .menu {
    position: fixed;
    inset: var(--kopf-hoehe) 0 0;
    background: var(--kopf);
    padding: 1rem var(--gutter) 3rem;
    /* Statt von rechts einzuschieben: aufblenden und leicht aufziehen. Das
       Einschieben liess den Inhalt dahinter kurz wandern. */
    opacity: 0;
    transform: scale(1.03);
    /* Geschlossen auch fuer Tastatur und Lesegeraet weg — sonst wandert der
       Fokus in Menuepunkte, die niemand sieht. */
    visibility: hidden;
    transition: opacity 0.28s ease, transform 0.35s var(--kurve),
                visibility 0.28s ease;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
  }
  /* Punkte und Fuss bilden einen Block, den die Flaeche mittig setzt.
     Vorher nahm die Liste per `flex: 1` den ganzen Raum und schob den Fuss
     an den unteren Rand — dazwischen klaffte ein Loch. */
  .menu { justify-content: center; }
  .menu ul { flex: none; }
  .kopf[data-offen='ja'] .menu {
    opacity: 1;
    transform: none;
    visibility: visible;
  }

  /* Punkte mittig, gross und untereinander — mit Platz, nicht gedraengt. */
  /* Punkte oben beginnen lassen, nicht im freien Raum zentrieren.
     Mit `flex: 1` nimmt die Liste die ganze Hoehe zwischen Kopfzeile und
     Fuss ein; zentriert darin rutschten die Punkte in die Mitte dieser
     Flaeche und standen dadurch weit unterhalb der Kopfzeile.

     `min-height: 100%` ist raus — zusammen mit `flex: 1` zog es die Liste
     zusaetzlich auf und verstaerkte den Effekt. */
  .menu ul {
    flex-direction: column;
    align-items: center;
    gap: 1.5rem;
  }
  .menu li { justify-content: center; }
  .menu a {
    font-size: clamp(1.75rem, 7vw, 2.25rem);
    letter-spacing: -0.01em;
  }
  /* U18 steht auf dem Telefon in der Kopfzeile neben der Marke, nicht im
     aufgeklappten Menue — es braucht dort also keine eigene Regel. */

  /* Fuss im aufgeklappten Menue: Anschrift und Symbole. Vier Punkte
     allein lassen die Vollbildflaeche leer wirken — hier steht, was man
     sonst erst im Seitenfuss findet. */
  .menu-fuss {
    margin-top: 2.5rem;
    display: grid;
    justify-items: center;
    gap: 0.35rem;
    text-align: center;
  }
  .menu-fuss p { color: var(--tinte-still); font-size: var(--t-klein); margin: 0; }
  .menu-fuss a { font-size: var(--t-klein); color: var(--tinte-leise); }
  .menu-fuss .fuss-social { margin-top: 0.75rem; }


  /* Die Punkte laufen nacheinander ein, statt alle gleichzeitig
     aufzutauchen. Die Verzoegerung steht je Position im CSS, weil ein
     Inline-Style unter `style-src 'self'` nicht erlaubt ist. */
  .menu li {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 0.3s ease, transform 0.4s var(--kurve);
  }
  .kopf[data-offen='ja'] .menu li { opacity: 1; transform: none; }
  .kopf[data-offen='ja'] .menu li:nth-child(1) { transition-delay: 0.08s; }
  .kopf[data-offen='ja'] .menu li:nth-child(2) { transition-delay: 0.13s; }
  .kopf[data-offen='ja'] .menu li:nth-child(3) { transition-delay: 0.18s; }
  .kopf[data-offen='ja'] .menu li:nth-child(4) { transition-delay: 0.23s; }
  .kopf[data-offen='ja'] .menu li:nth-child(5) { transition-delay: 0.28s; }

  /* Wer Bewegung abbestellt hat, bekommt sie auch hier nicht. */
  @media (prefers-reduced-motion: reduce) {
    .menu li { opacity: 1; transform: none; transition: none; }
    .menu { transition: visibility 0.01s; transform: none; }
  }
}
@media (min-width: 900px) {
  .menu-knopf { display: none; }
}

/* ----------------------------------------------------------------- Hero -- */

.hero {
  position: relative;
  /* Feste Hoehe als `height`, nicht als `aspect-ratio` mit `max-height`:
     bei dieser Kombination zieht Chrome die Breite mit und laesst auf einem
     breiten, flachen Fenster rechts eine dunkle Flaeche stehen.
     Auch keine `vh`-Einheiten — sonst springt die Hoehe auf dem Telefon,
     wenn die Adressleiste ein- und ausfaehrt. */
  height: clamp(500px, 71svh, 790px);
  margin-top: calc(var(--kopf-hoehe) * -1);
  display: grid;
  place-items: center;
  overflow: hidden;
  background: var(--nacht);
  text-align: center;
}

.hero-medium {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero-medium img, .hero-medium video {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center;
}

/* Schleier, damit die Schrift auf dem Video traegt. Dunkel, nicht hell —
   die bestehende Seite setzt weisse Schrift auf das Clubvideo. */
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg, rgb(0 0 0 / 55%) 0%, rgb(0 0 0 / 35%) 45%, rgb(0 0 0 / 75%) 100%);
}

.hero-text {
  position: relative;
  z-index: 2;
  padding-top: var(--kopf-hoehe);
}

/* Logo ueber der Ueberschrift. Die Breiten sind die des Originals: 10 % der
   Spalte auf dem Schreibtisch, 28 % ab Tablet abwaerts. */
/* Der Hero-Titel ist ein <p>, kein <h1> — die H1 der Seite steht statisch
   und fuer Lesegeraete unsichtbar im Markup. Sonst waeren es zwei. */
.hero-titel {
  margin: 0 0 1.25rem;
  font-family: var(--schrift-display);
  font-size: var(--t-hero);
  font-weight: 900;
  line-height: 1.02;
  text-transform: uppercase;
  letter-spacing: 0;
}
.hero-titel span { display: block; }

/* Knapper als die uebrigen Knoepfe. Die bestehende Seite macht es ebenso —
   im Hero steht der Knopf unter einer sehr grossen Ueberschrift und muss
   sie nicht noch einmal ueberbieten. */
.hero-text .knopf {
  padding: 0.7rem 1.4rem;
  font-size: 0.8125rem;
}

/* ------------------------------------------------------------- Ueber uns -- */

.ueber {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
@media (min-width: 900px) {
  .ueber { grid-template-columns: 1fr 1fr; }
}

/* Blocksatz wie im Original. */
.ueber-text p { color: var(--tinte-leise); text-align: justify; }

/* --------------------------------------------------------------- Karten -- */

/* Drei Spalten, Abstand 20px — und ab Tablet abwaerts eine Spalte. Das
   Original schaltet bei 1024 px direkt auf einspaltig, nicht stufenweise. */
.karten {
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (max-width: 1024px) {
  .karten { grid-template-columns: 1fr; }
}

.karte {
  display: flex;
  flex-direction: column;
  /* Die Kerben sind **Aussparungen im Kartenhintergrund**, keine farbigen
     Kreise. Zwei Kreise in der Hintergrundfarbe waeren nur auf schwarzem
     Grund unsichtbar — der Eventabschnitt der Startseite liegt aber auf
     einem Foto, dort staenden sie als dunkle Punkte. So stanzen sie
     wirklich, und es zeigt sich, was immer dahinterliegt. */
  background:
    radial-gradient(circle 11px at 0 calc(100% - var(--abriss)),
      transparent 11px, var(--karte) 11.5px) left / 51% 100% no-repeat,
    radial-gradient(circle 11px at 100% calc(100% - var(--abriss)),
      transparent 11px, var(--karte) 11.5px) right / 51% 100% no-repeat;
  border-radius: var(--r-karte);
  /* Damit der Flyer die Rundung der Karte uebernimmt, ohne ihn einzeln zu
     runden — sonst steht an der Oberkante eine Ecke ueber. */
  overflow: hidden;
  box-shadow: var(--schatten);
  transition: transform 0.3s var(--kurve), box-shadow 0.3s var(--kurve);
}
.karte:hover {
  transform: translateY(-6px);
  box-shadow: var(--schatten-hoch);
}
.karte:active { transform: translateY(-2px); }

.karte-bild { background: var(--box-hell); }
/* Flyer sind 16:9 — ein quadratischer Beschnitt schneidet den Titel weg. */
.karte-bild img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.karte-text {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  padding: 0.875rem 0.9375rem 1rem;
  flex: 1;
}
/* Der Abschnitt unter der Perforation, wie bei einer Eintrittskarte:
   links Termin und Uhrzeit, rechts der Weg zur Veranstaltung.

   Feste Hoehe aus `--abriss`, damit die Trennlinie genau dort sitzt, wo die
   Kerben im Kartenhintergrund ausgespart sind. Waechst der Abschnitt mit
   seinem Inhalt, wandert die Linie und die Stanzung passt nicht mehr. */
.karte-abriss {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  height: var(--abriss);
  margin: 0;
  padding-inline: 0.9375rem;
  /* Plakat-Fassung: keine Strichlinie; der Abriss setzt sich als eigene
     Tonstufe ab (siehe .karte-abriss im Abschnitt Plakat). */
  border-top: 0;
  font-size: 0.75rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.karte-termin { color: var(--tinte-leise); white-space: nowrap; }
.karte-infos {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  color: var(--akzent);
  transition: gap 0.22s var(--kurve);
}
/* Der Pfeil rueckt beim Darueberfahren ein Stueck weiter — die Karte ist
   ein Link, und das zeigt sie damit. */
.karte:hover .karte-infos { gap: 0.6rem; }
.karte-titel {
  font-size: var(--t-h3);
  line-height: 1.2;
}
/* Ortszeile zwischen Titel und „mehr erfahren" — im Original in der
   Akzentfarbe, wie die Datumszeile. */
.karte-ort {
  margin: 0;
  color: var(--akzent);
  font-size: var(--t-klein);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Monatsueberschrift der Eventliste. */
/* Zentriert und weiss, ohne Trennlinie — wie im Original. */
.monat {
  font-size: var(--t-h3);
  color: var(--tinte);
  text-align: center;
  margin: clamp(2.5rem, 5vw, 3.5rem) 0 1.5rem;
}
.monat:first-child { margin-top: 0; }

.leer {
  color: var(--tinte-leise);
  text-align: center;
  padding-block: 3rem;
}

/* ------------------------------------------------------- Seitenkopf (Unter) -- */

/* Feste Hoehe. Ohne sie richtet sich jeder Kopf nach der Laenge seines
   Einleitungssatzes und die Unterseiten stehen unterschiedlich hoch. */
/* Bildbanner der Unterseiten — im Original je Seite ein anderes Clubfoto,
   mit dunklem Schleier darueber. */
.seitenkopf-bild {
  position: relative;
  background-position: center center;
  background-size: cover;
  background-repeat: no-repeat;
  isolation: isolate;
}
.seitenkopf-bild::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgb(0 0 0 / 58%);
}
/* Der Bildausschnitt folgt dem Motiv, nicht der Bildmitte: Beim Jobs-Banner
   steht der Leuchtschriftzug im rechten Bilddrittel, beim Events-Banner das
   Ringlicht links der Mitte. Mit `center` schnitt der Beschnitt auf schmalen
   Geraeten genau daran vorbei. */
.seitenkopf-bild[data-banner='events'] {
  background-image: url('../img/banner/events.webp');
  background-position: 42% center;
}
.seitenkopf-bild[data-banner='kontakt'] {
  background-image: url('../img/banner/kontakt.webp');
  background-position: 50% center;
}
.seitenkopf-bild[data-banner='fotos'] {
  background-image: url('../img/einblick/04.webp');
  background-position: 50% center;
}
.seitenkopf-bild[data-banner='jobs'] {
  background-image: url('../img/banner/jobs.webp');
  background-position: 66% center;
}

.seitenkopf {
  /* Hoehe waechst mit der Fensterbreite, statt auf dem Telefon als flacher
     Streifen dazustehen, durch den das Bild stark beschnitten wird. */
  min-height: clamp(320px, 34vw, 460px);
  display: grid;
  align-content: center;
  /* Der Banner laeuft unter die Kopfzeile, damit die schwebende Leiste
     auch hier auf einem Bild sitzt und nicht auf leerer Flaeche.

     Negativer Rand **und** Polster gehoeren zusammen: Der Rand schiebt den
     Banner unter die Leiste, das Polster holt den Inhalt wieder in die
     sichtbare Flaeche. Eines ohne das andere drueckt ihn aus der Mitte —
     genau das war hier frueher der Fall, als das Polster ohne Gegenstueck
     stand. */
  margin-top: calc(var(--kopf-hoehe) * -1);
  padding-top: calc(var(--kopf-hoehe) + clamp(2.5rem, 7vw, 4rem));
  padding-bottom: clamp(2.5rem, 7vw, 4rem);
  /* `background-color`, nicht die Kurzschreibweise `background`. Das
     Element traegt beide Klassen (`seitenkopf seitenkopf-bild`), und die
     Kurzschreibweise setzt alle uebrigen background-Werte zurueck — damit
     fiel `background-size: cover` aus `.seitenkopf-bild` auf `auto`
     zurueck und das Bannerbild lag in Originalgroesse in der Flaeche,
     also dreifach vergroessert. Das Bild ueberlebte nur, weil die
     Banner-Regeln hoehere Spezifitaet haben. */
  background-color: var(--flaeche);
  border-bottom: 1px solid var(--linie);
  text-align: center;
}
/* Eigene Skala, nicht `--t-h1`: Die Bannerueberschrift steht allein auf
   einer grossen Flaeche und darf deutlich groesser anfangen als eine
   Ueberschrift im Fliesstext. */
/* Auf dem Telefon traegt die Ueberschrift den ganzen Banner — sie darf
   dort deutlich groesser anfangen. 13vw heisst rund 51px auf einem
   390px-Geraet statt der vorherigen 40px. */
.seitenkopf h1 {
  font-size: clamp(3rem, 13vw, 4.5rem);
  /* „Datenschutzerklärung" ist bei 51px in Versalien 759px breit und lief
     bei 390 aus dem Bild (gemessen 03.11.2026, in der Vorlage genauso).
     Silbentrennung nach lang="de", nur wo das Wort sonst nicht passt. */
  hyphens: auto;
  overflow-wrap: break-word;
}
.seitenkopf p {
  margin: 1rem auto 0;
  max-width: 54ch;
  color: var(--tinte-leise);
  text-transform: none;
}
.seitenkopf .unterzeile {
  color: var(--akzent);
  font-weight: 400;
  font-size: clamp(0.9375rem, 2.6vw, 1.125rem);
}

/* Auf dem Telefon traegt der Banner ein festes Seitenverhaeltnis statt einer
   Mindesthoehe. Der Umweg ueber eigene Hochformat-Zuschnitte war falsch: Ein
   schmaler Ausschnitt aus einem Breitbild heisst staerker vergroessern, nicht
   schwaecher. Und eine feste Mindesthoehe bei schmaler Breite erzwingt genau
   diese Vergroesserung, weil `cover` die Hoehe fuellen muss.

   **3:2 statt 16:9 — gemessen, nicht geschaetzt.** Mit dem Verhaeltnis des
   Bildes (16:9, die Datei ist 1536x864) war das Band bei 390 Pixel Breite
   219 Pixel hoch. Davon gehen 80 fuer die schwebende Kopfzeile ab, es
   bleiben 139 fuer 96 Pixel Text: 21 Pixel Luft ueber der Ueberschrift,
   22 darunter. Die Schrift klebte oben an der Leiste und unten an der
   Kante — genau das wirkte gequetscht.

   Das Polster ist hier **nicht** der Hebel: `align-content: center`
   zentriert den Inhalt, sobald er die Inhaltsbox ueberlaeuft, und das tut
   er auf jeder Telefonbreite. Ein kleineres Polster verschiebt deshalb
   nichts. Nur mehr Hoehe hilft.

   3:2 ergibt 260 Pixel, also 180 nutzbare statt 139 — die Luft verdoppelt
   sich auf gut 40 Pixel. Der Preis sind rund 16 Prozent seitlicher
   Beschnitt. Das ist der Tausch: etwas weniger Bild gegen Text, der nicht
   zwischen zwei Kanten klemmt. */
@media (max-width: 759px) {
  .seitenkopf-bild {
    min-height: 0;
    aspect-ratio: 3 / 2;
    background-position: center center;
  }
}

/* ------------------------------------------------------------------ FAQ -- */

.kontakt-raster {
  display: grid;
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: start;
}
@media (min-width: 900px) {
  .kontakt-raster { grid-template-columns: 1fr 1fr; }
  /* Ist die FAQ leer, faellt die linke Spalte weg und das Formular rueckt
     in die Mitte. */
  .kontakt-raster[data-ohne-faq='ja'] {
    grid-template-columns: minmax(0, 640px);
    justify-content: center;
  }
}

.faq {
  border-bottom: 1px solid var(--linie);
}
.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.125rem 0;
  cursor: pointer;
  font-weight: 700;
  list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
/* Das Pluszeichen dreht sich beim Aufklappen zum Minus. Als ::after und
   nicht als Symbol im Markup: eine Zierde gehoert nicht in den Quelltext. */
.faq summary::after {
  content: '';
  flex: none;
  width: 14px; height: 14px;
  background:
    linear-gradient(var(--akzent), var(--akzent)) center / 100% 2px no-repeat,
    linear-gradient(var(--akzent), var(--akzent)) center / 2px 100% no-repeat;
  transition: transform 0.2s ease;
}
.faq[open] summary::after { transform: rotate(45deg); }
.faq[open] summary { color: var(--akzent); }
.faq-text {
  padding-bottom: 1.25rem;
  color: var(--tinte-leise);
}
/* Die Antwort kommt als reiner Text aus Clubinio, mit Zeilenumbruechen —
   `page-kontakt.js` setzt sie als `textContent`. Ohne `pre-wrap` faltet CSS
   die Umbrueche zu Leerzeichen und aus einer gegliederten Antwort wird ein
   Block. Dieselbe Loesung wie bei der Eventbeschreibung weiter unten, aus
   demselben Grund: kein Markup aus einem Shopadmin-Feld interpretieren. */
.faq-text p { white-space: pre-wrap; overflow-wrap: anywhere; }

/* ---------------------------------------------------------------- Jobs -- */

/* Im Original steht die Ansprache linksbuendig und in normaler Schriftlage,
   nicht als zentrierte Versalueberschrift. */
.abschnitt-oben { padding-block: clamp(2.5rem, 6vw, 4rem) 0; }
/* Ansprache und Formular gehoeren zusammen. Ohne das hier stossen zwei
   volle Abschnittspolster aneinander und reissen eine Luecke zwischen
   Einleitung und erstem Feld. Die zweite Zeile ueberspringt die
   ausgeblendeten Stellen. */
.abschnitt-oben + .abschnitt,
.abschnitt-oben + [hidden] + .abschnitt { padding-top: clamp(1.75rem, 4vw, 2.75rem); }
.jobs-ansprache {
  font-size: var(--t-h3);
  text-transform: none;
  margin-bottom: 1rem;
}
.jobs-intro { color: var(--tinte-leise); max-width: 70ch; }

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

.stelle {
  padding: 1.5rem;
  background: rgb(255 255 255 / 5%);
  border: 1px solid rgb(255 255 255 / 8%);
  border-radius: var(--r-karte);
  margin-bottom: 1rem;
}
.stelle h3 { font-size: var(--t-h3); margin-bottom: 0.5rem; }
/* `white-space` wie bei der FAQ-Antwort: `page-jobs.js` setzt die
   Beschreibung als reinen Text, die Umbrueche darin sollen stehen bleiben. */
.stelle p {
  color: var(--tinte-leise);
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ------------------------------------------------------------ Formulare -- */

.form { display: grid; gap: 1.125rem; }

/* h2 traegt global keinen Abstand; ueber einem Formular braucht sie einen,
   sonst sitzt sie auf der ersten Feldbeschriftung. */
#kontaktformular h2 { margin-bottom: 1.5rem; }

/* Im Original stehen kurze Felder nebeneinander, nicht alle untereinander.
   `auto-fit` statt fester Spalten: unter ~420px je Feld bricht die Reihe
   von selbst um, ohne eigene Abfrage. */
.form-reihe {
  display: grid;
  gap: 1.125rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
}

.feld { display: grid; gap: 0.4rem; }
/* Im Original stehen die Beschriftungen in Normalschrift und gemischter
   Schreibung, nicht als fette Versalien. */
.feld > span {
  font-size: var(--t-klein);
  font-weight: 400;
  color: var(--tinte-leise);
}
.feld-pflicht { color: var(--akzent); }

input[type='text'], input[type='email'], input[type='tel'],
input[type='number'], input[type='file'], textarea, select {
  width: 100%;
  padding: 0.95rem 1.05rem;
  /* Kein Rahmen. Die Flaeche allein zeigt, wo geschrieben wird — eine Linie
     um jedes Feld zieht das Formular in Kaestchen auseinander. */
  border: 0;
  border-radius: var(--r-feld);
  background: rgb(255 255 255 / 6%);
  color: var(--tinte);
  font: inherit;
  transition: box-shadow 0.2s ease, background 0.2s ease;
}
:is(input[type='text'], input[type='email'], input[type='tel'],
    input[type='number'], textarea, select):hover:not(:focus) {
  background: rgb(255 255 255 / 8%);
}
textarea {
  min-height: 150px;
  resize: vertical;
  border-radius: var(--r-feld);
}
/* Fokus als schmaler Ring aussen. Er liegt ueber dem Rand, nicht darin,
   und verschiebt deshalb nichts. */
input:focus, textarea:focus, select:focus {
  outline: 0;
  background: rgb(255 255 255 / 10%);
  box-shadow: 0 0 0 2px var(--tinte);
}
::placeholder { color: var(--tinte-still); }

/* Das Dateifeld traegt keine eigene Flaeche: sonst steht ein Knopf in
   einem Kasten in einem Formular. Nur der Knopf bleibt sichtbar, der
   Dateiname steht daneben im Text. */
input[type='file'] {
  padding: 0;
  border: 0;
  background: none;
  font-size: var(--t-klein);
  color: var(--tinte-leise);
}
input[type='file']:focus {
  background: none;
  box-shadow: none;
}
input[type='file']::file-selector-button {
  margin-right: 0.75rem;
  padding: 0.6rem 1.2rem;
  border: 0;
  border-radius: var(--r-knopf);
  background: rgb(255 255 255 / 10%);
  color: var(--tinte);
  font: inherit;
  font-size: var(--t-klein);
  cursor: pointer;
  transition: background 0.2s ease;
}
input[type='file']::file-selector-button:hover {
  background: rgb(255 255 255 / 16%);
}
input[type='file']:focus-visible::file-selector-button {
  outline: 2px solid var(--akzent);
  outline-offset: 2px;
}

/* Das Fieldset traegt im Original keinen Rahmen — nur die Beschriftung
   darueber, wie bei jedem anderen Feld. */
fieldset.feld {
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;
}
fieldset.feld legend { padding: 0; }

.zustimmung {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  font-size: var(--t-klein);
  color: var(--tinte-leise);
}
.zustimmung input { margin-top: 0.1rem; }

/* Ein eigenes Kaestchen fuer beide Stellen. Das Systemkaestchen ist ein
   weisses Quadrat und passt zu nichts hier; gefuellt statt umrandet spricht
   es dieselbe Sprache wie die Eingabefelder. */
.auswahl input, .zustimmung input {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  width: 20px; height: 20px;
  border: 0;
  border-radius: 7px;
  background: rgb(255 255 255 / 10%);
  cursor: pointer;
  transition: background 0.2s ease;
}
.auswahl label:hover input:not(:checked),
.zustimmung:hover input:not(:checked) { background: rgb(255 255 255 / 16%); }
.auswahl input:checked, .zustimmung input:checked {
  background: var(--haken) var(--akzent) center / 13px 13px no-repeat;
}
.auswahl input:focus-visible, .zustimmung input:focus-visible {
  outline: 2px solid var(--akzent);
  outline-offset: 2px;
}
.zustimmung a { color: var(--akzent); text-decoration: underline; }

/* Honigtopf. Fuer Menschen unsichtbar, fuer Skripte verlockend.
   Nicht `display: none` — manche Skripte ueberspringen genau das. */
.honigtopf {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

.rueckmeldung {
  margin: 0;
  font-size: var(--t-klein);
  min-height: 1.4em;
}
.rueckmeldung[data-state='ok']      { color: var(--akzent); }
.rueckmeldung[data-state='fehler']  { color: #ff6b5e; }
.rueckmeldung[data-state='laeuft']  { color: var(--tinte-still); }

/* ------------------------------------------------------------- Eventseite -- */

/* Inhaltsspalte ~820px und Titel ~40px — Originalwerte. */
.event { max-width: 820px; margin-inline: auto; }
.event h1 { font-size: clamp(1.75rem, 4vw, 2.5rem); }

.event-flyer {
  width: 100%;
  border-radius: var(--r-karte);
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--box);
  margin-bottom: 1.75rem;
}

.event .knopf-reihe { margin-bottom: 2rem; }
.event .knopf-reihe .knopf { flex: 1 1 260px; }

/* Der U18-Knopf laeuft ueber dieselbe Breite wie der Ticketknopf. Als
   schmaler Knopf unter einem breiten stand er auf dem Schreibtisch
   verloren in der Flaeche. */
.event .knopf-reihe-u18 .knopf { width: 100%; }

/* U18-Formular. Erscheint nur, wenn Minderjaehrige eingelassen werden —
   tools/build.py entscheidet das je Termin aus `ageRestriction`.

   Steht unter den Knoepfen und nicht daneben: Es ist kein gleichrangiger
   Weg zum Ticket, sondern eine Bedingung fuer einen Teil der Gaeste. Der
   Abstand nach oben ist deshalb negativ gegen den Abstand der Knopfreihe —
   Hinweis und Knopf gehoeren optisch zusammen, nicht zum Flyer darueber. */
/* Der Knopf steht direkt unter dem Ticketknopf, der Hinweis darunter: Die
   Handlung zuerst, die Erklaerung als Beschriftung dazu. Der negative
   Abstand nach oben arbeitet gegen den Abstand der Ticketreihe — beide
   Knoepfe gehoeren zusammen. */
.event .knopf-reihe-u18 { margin: -1rem 0 0.6rem; }
.u18-hinweis {
  margin: 0 0 2.5rem;
  color: var(--tinte-still);
  font-size: var(--t-klein);
}

.event-datum {
  color: var(--akzent);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 0.625rem;
}
.event h1 { margin-bottom: 1.5rem; }
/* Die Beschreibung steht auf der Eventseite fast allein auf der Flaeche.
   Eine leichte Absetzung gibt ihr eine Kante, statt sie im Grund
   verschwinden zu lassen — ohne sie als Kasten zu rahmen. */
.event-text a { color: var(--akzent); }
.event-text {
  margin-top: 0.5rem;
  padding: 1.25rem 1.375rem;
  background: rgb(255 255 255 / 3.5%);
  border-radius: var(--r-karte);
  color: var(--tinte-leise);
  line-height: 1.55;
  /* Die Beschreibung kommt als reiner Text aus Clubinio, mit Zeilenumbruechen
     und Emoji. `pre-wrap` erhaelt die Umbrueche, ohne dass dafuer Markup
     aus einem Shopadmin-Feld interpretiert werden muss. */
  white-space: pre-wrap;
  /* Lange Adressen haben keine Trennstelle — ohne das hier laufen sie aus
     dem Kasten heraus und werden am Rand abgeschnitten. `anywhere` statt
     `break-word`, weil es auch in die Mindestbreite einfliesst: Sonst zieht
     ein einziger langer Link den Kasten breiter als den Bildschirm. */
  overflow-wrap: anywhere;
}

.infokasten {
  margin-top: 2.5rem;
  padding: 1.75rem;
  background: rgb(255 255 255 / 5%);
  border: 1px solid rgb(255 255 255 / 8%);
  border-radius: var(--r-karte);
}
.infokasten h2 { font-size: var(--t-h3); margin-bottom: 1.25rem; }
/* Zwei Paare nebeneinander, Beschriftung ueber dem Wert — wie im Original.
   `dt`/`dd` stehen im Markup abwechselnd; das Raster setzt sie deshalb in
   eine eigene Zelle je Paar, indem jedes `dt` eine neue Zeile beginnt. */
.infokasten dl {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem 2.5rem;
  margin: 0;
}
@media (min-width: 620px) {
  .infokasten dl { grid-template-columns: 1fr 1fr; }
}
.infopaar dt { margin: 0; }
.infokasten dd {
  text-transform: uppercase;
  font-weight: 700;
  margin-top: 0.25rem;
}
.infokasten dt {
  color: var(--tinte-still);
  font-size: var(--t-klein);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.infokasten dd { margin: 0; }


/* Zentriert mit Pfeil davor — wie im Original. Der Pfeil ist wie bei den
   Knoepfen gezeichnet, nicht gesetzt. */
.zurueck::before {
  content: '';
  width: 1em;
  height: 1em;
  flex: none;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19 12H6.8l4.6-4.6L10 6l-6 6 6 6 1.4-1.4L6.8 12H19v-2Z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19 12H6.8l4.6-4.6L10 6l-6 6 6 6 1.4-1.4L6.8 12H19v-2Z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.zurueck {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.5rem;
  margin-top: 2.5rem;
  color: var(--tinte-leise);
  font-size: var(--t-klein);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.zurueck:hover { color: var(--akzent); }

/* ------------------------------------------------------------ Rechtstext -- */

.rechtstext { max-width: 72ch; }
.rechtstext h2 {
  font-size: var(--t-h3);
  margin: 2.5rem 0 0.875rem;
  text-transform: none;
}
.rechtstext h3 {
  font-size: 1.0625rem;
  margin: 1.75rem 0 0.5rem;
  text-transform: none;
}
.rechtstext p, .rechtstext li { color: var(--tinte-leise); }
.rechtstext a { color: var(--akzent); text-decoration: underline; }
.rechtstext ul { padding-left: 1.25rem; }
.rechtstext address { font-style: normal; margin-bottom: 1.5rem; }

/* ------------------------------------------------------------- Newsletter -- */

/* Baustein aus garage-hp (dort nach dem Clubinio-Plugin gemessen), hier
   als Kasten auf der Startseite (Betreiber, 03.11.2026). Geht als
   Systembaustein in die Vorlage zurück, siehe docs/README.md. */
.newsletter .form {
  display: block;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
}
.newsletter-zeile {
  display: flex;
  max-width: 460px;
  height: 48px;
  overflow: hidden;
  border: 1px solid #2a2f3a;
  border-radius: 999px;
  background: #12151c;
}
.newsletter-zeile input {
  flex: 1;
  min-width: 0;
  padding: 0 18px;
  border: 0;
  background: transparent;
  color: var(--tinte);
  font: inherit;
  font-family: var(--schrift-text);
  font-size: 15px;
  line-height: 1.5;
}
.newsletter-zeile input::placeholder { color: rgb(255 255 255 / 45%); }
.newsletter-zeile input:focus { outline: none; }
.newsletter-zeile:focus-within { outline: 2px solid var(--akzent); outline-offset: 2px; }
.newsletter-zeile .knopf {
  padding: 12px 22px;
  font-family: var(--schrift-text);
  border-radius: 3px;
  font-size: 13.6px;
  font-weight: 800;
  line-height: 1.5;
  text-transform: uppercase;
  box-shadow: none;
}
.newsletter .zustimmung {
  max-width: 460px;
  margin-top: 9px;
  font-family: var(--schrift-text);
  font-size: 11.52px;
  color: #7a8595;
}
.newsletter .rueckmeldung { margin-top: 12px; max-width: 460px; }

/* Auf der Eventseite 26px unter dem Infokasten — gemessen. */
.event .newsletter { margin-top: 26px; }

/* Als eigener Kasten auf der Eventseite (Baustein aus drip-hp, dasselbe
   Plugin auf der Altseite von garage-hp gemessen):
   #111, Rundung 22, Polster 80/40, mittig. Darüber das Foto mit 40 %
   Deckung und ein Verlauf 0,55 → 0,85 (#0a0b0e). Das Original legt Foto
   und Verlauf als zwei leere <span> hinein; hier sind es Hintergrund-
   schichten desselben Kastens — der 60-%-Schleier in #111 über dem Foto
   ergibt rechnerisch dasselbe wie das Foto mit 40 % über #111. */
.newsletter-kasten {
  overflow: hidden;
  padding: 80px 40px;
  border-radius: 22px;
  background:
    linear-gradient(rgb(10 11 14 / 55%), rgb(10 11 14 / 85%)),
    linear-gradient(rgb(17 17 17 / 60%), rgb(17 17 17 / 60%)),
    /* Bild: tools/medien.py (newsletter.webp, Gäste-Foto aus dem
       Kundenmaterial). Der Kasten steht auf der Startseite. */
    url('../img/newsletter.webp') center / cover no-repeat,
    #111111;
  text-align: center;
}
/* Überschrift 41,6px/1,1 — auf der Eventseite 800, auf /newsletter/ 700. */
.newsletter-kasten h1,
.newsletter-kasten h2 {
  font-size: 41.6px;
  font-weight: 800;
  line-height: 1.1;
  text-transform: uppercase;
}
.newsletter-kasten h1 { font-weight: 700; }
.newsletter-kasten > p {
  max-width: 560px;
  margin: 10px auto 26px;
  font-size: 16.8px;
  line-height: 1.5;
  color: #cfd6e0;
}
.newsletter-kasten .newsletter-zeile {
  max-width: 540px;
  height: auto;
  margin-inline: auto;
  gap: 10px;
  overflow: visible;
  border: 0;
  border-radius: 0;
  background: transparent;
}
.newsletter-kasten .newsletter-zeile input {
  height: 56px;
  padding: 16px 20px;
  border-radius: 999px;
  background: rgb(255 255 255 / 96%);
  color: #111111;
  font-size: 16px;
}
.newsletter-kasten .newsletter-zeile input::placeholder { color: #757575; }
.newsletter-kasten .newsletter-zeile .knopf {
  padding: 16px 32px;
  border-radius: 999px;
  font-size: 16px;
  line-height: 1.5;
}
.newsletter-kasten .zustimmung {
  max-width: 540px;
  margin: 14px auto 0;
  font-size: 12.8px;
  line-height: 1.45;
  color: #c3ccd8;
}
/* Telefon: Polster 54/24, Überschrift 32px, Feld und Knopf untereinander
   über die volle Breite. */
@media (max-width: 767px) {
  .newsletter-kasten { padding: 54px 24px; }
  .newsletter-kasten h1,
  .newsletter-kasten h2 { font-size: 32px; }
  .newsletter-kasten .newsletter-zeile { flex-direction: column; }
  /* `flex: 1` würde das Feld in der Spalte auf die Inhaltshöhe drücken. */
  .newsletter-kasten .newsletter-zeile input { flex: none; }
}

/* ------------------------------------------------------------------ Fuss -- */

/* Zwei Spalten wie im Original: links Marke und Rechtslinks, rechts die
   Anfahrt samt Social-Symbolen und dem Clubinio-Zeichen. */
.fuss {
  background: var(--kopf);
  padding-block: clamp(2.5rem, 6vw, 4rem);
}
.fuss-raster {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  grid-template-columns: 1fr;
}
@media (min-width: 760px) {
  .fuss-raster { grid-template-columns: 1.4fr 1fr; }
}


.fuss p, .fuss li { color: var(--tinte-leise); font-size: var(--t-klein); }
.fuss a:hover { color: var(--akzent); }

/* Impressum und Datenschutz stehen im Original nebeneinander unter dem
   Text, in der Akzentfarbe — keine eigene Spalte mit Ueberschrift. */
.fuss-recht {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  margin-top: 1.25rem;
}
.fuss-recht a { color: var(--akzent); }

/* Symbole ohne Rahmen, in der Akzentfarbe — so stehen sie im Original. */
.fuss-social { display: flex; gap: 0.75rem; margin: 1.25rem 0; }
.fuss-social a { color: var(--akzent); }
.fuss-social a:hover { color: var(--tinte); }

.clubinio { display: inline-block; }
.clubinio img { height: 38px; width: auto; }

/* --------------------------------------------------------------- Plakat -- */

/* Plakat-Fassung (Betreiber, 03.11.2026: „nicht wie die anderen 0815 Läden
   … 2026 urban, viel Bilder"). Gestaltungsrichtung „Loud and flat"
   (.taste-skill/direction.json): flache Felder in Rot, Schwarz und Weiß,
   hohe Plakatschrift, Fotos wie angeklebte Abzüge. Die Idee: Das Plakat
   über der Bühne des Velvet („TAKE MORE CHANCES, DANCE MORE DANCES.") wird
   zum Plakat der Seite.

   Alles hier sind Varianten der Systemklassen (`.hero--plakat`,
   `.fuss--hell`, `.abschnitt--…`) oder neue Bausteine mit Namen nach
   ihrer Aufgabe (`.abzuege`, `.portraet`). Die Vorlage bleibt darunter
   unverändert. */

:root {
  --feld-rot:   var(--akzent);
  --feld-weiss: #ebebea;   /* neutrales Knochenweiß, kein Gelbstich */
  --tinte-dunkel: #0b0b0e;
}

/* Kopfzeile: flach statt Milchglas. */
.kopf[data-fest='ja'] {
  background: var(--nacht);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.menu a { font-weight: 800; font-size: 1.0625rem; letter-spacing: -0.02em; }
.menu a:hover { color: var(--tinte); }
/* Der aktive Punkt in Rot verschwände auf dem roten Hero. */
.menu a[aria-current='page'] { color: var(--tinte); }

/* Knöpfe: ein Rechteck, gefüllt, für die ganze Seite.

   Zweite Runde (Betreiber, 03.11.2026: „finde die jetzigen gut, aber sie
   sehen bissl vibecoded aus"). Form und Farben bleiben; weg sind die
   Baukasten-Merkmale: kein Anheben und kein Schatten beim Drüberfahren,
   kein Standardpfeil, kein Emoji am Ticketknopf. Stattdessen spricht der
   Knopf die Sprache der Hero-Balken: Beim Drüberfahren zieht eine zweite
   Fläche von links auf (wie der Titel beim Laden), der Pfeil läuft ein
   Stück nach vorn.

   Die Grundfarbe bleibt beim Drüberfahren stehen (`--knopf-grund` für die
   Fälle ohne eigene Umgebungsregel). Die Umgebungen setzen nur, welche
   Fläche aufzieht: `--knopf-fuell` und die Schrift darauf. */
.knopf {
  --knopf-grund: var(--akzent);
  --knopf-fuell: var(--tinte);
  --knopf-fuell-tinte: var(--tinte-dunkel);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  gap: 0.7rem;
  padding: 1.05rem 1.5rem 1rem 1.6rem;
  border: 0;
  font-size: 1rem;
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1;
  white-space: nowrap;
  transition: color 0.3s var(--kurve);
}
.knopf::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  margin: 0;
  background: var(--knopf-fuell);
  scale: 0 1;
  transform-origin: left;
  transition: scale 0.4s var(--kurve);
}
/* Eigener Pfeil: kräftiger Schaft und Spitze in der Strichstärke der
   Plakatschrift statt des dünnen Standardpfeils. */
.knopf::after {
  width: 0.85em;
  height: 0.85em;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M2 10.4h14.6l-5-5L13.9 3l9 9-9 9-2.3-2.4 5-5H2z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M2 10.4h14.6l-5-5L13.9 3l9 9-9 9-2.3-2.4 5-5H2z'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: translate 0.4s var(--kurve);
}
.knopf:hover,
.knopf:focus-visible { background: var(--knopf-grund); color: var(--knopf-fuell-tinte); transform: none; box-shadow: none; }
.knopf:hover::before,
.knopf:focus-visible::before { scale: 1 1; }
.knopf:hover::after,
.knopf:focus-visible::after { translate: 0.25em 0; }
.knopf:active { transform: none; }
.knopf[disabled]::before { content: none; }
/* Ticketknopf: der Pfeil wie überall statt des Ticket-Emojis. */
.knopf-ticket::after { content: ''; }
.knopf-leer { --knopf-grund: var(--tinte); --knopf-fuell: var(--feld-rot); --knopf-fuell-tinte: var(--tinte); background: var(--tinte); color: var(--tinte-dunkel); }

/* Seitenköpfe der Unterseiten: die Plakatschrift in voller Größe, ohne
   Trennlinie darunter (der Bildwechsel trennt). */
.seitenkopf h1 { font-size: clamp(2.75rem, 11vw, 6rem); line-height: 1; }
/* Ein Wort mit 20 Zeichen: Es muss auf dem Telefon in eine Zeile passen. */
.seitenkopf--lang h1 { font-size: clamp(1.75rem, 7vw, 6rem); }
.seitenkopf { border-bottom: 0; }

/* Eventseite: der Name als Plakatzeile. */
.event h1 { font-size: var(--t-h1); line-height: 1; }

/* Nichts zum Lesen unter 14 px; Feldbeschriftungen in Textgröße. */
.karte-abriss { font-size: 0.875rem; }
.feld > span { font-size: 1rem; }

/* Eventkarten (/events/): flach, ohne gestanzte Kerben (die waren ein
   Verlauf), der Abriss als eigene Tonstufe. */
.karte { background: var(--karte); }
.karte-abriss { background: var(--box-hell); }

/* ---- Menü ------------------------------------------------------------ */

/* Kopfzeile gleitet beim Runterscrollen weg (ui.js setzt data-weg).
   `transform` nur im weggeglittenen Zustand: Eine Transformation an
   `.kopf` machte sie zum Bezugsrahmen des festen Telefon-Menüs. */
.kopf { transition: background 0.25s ease, translate 0.4s var(--kurve); }
.kopf[data-weg='ja'] { translate: 0 -100%; }

/* Schreibtisch: Wörter rollen. Das sichtbare Wort steigt aus dem Bild,
   die zweite Fassung (data-text) kommt von unten nach. */
.menu--plakat > ul > li:not(.menu-aktion) > a {
  position: relative;
  display: inline-block;
  overflow: hidden;
  padding-block: 0.15rem;
  line-height: 1.15;
  text-decoration: none;
}
.menu--plakat > ul > li:not(.menu-aktion) > a > span { position: relative; z-index: 1; display: block; transition: translate 0.38s var(--kurve); }
/* Dazu zieht ein gefüllter Block von links hinter dem Wort auf: schwarz
   über dem roten Hero und den Bildköpfen, rot auf der deckenden Zeile. */
@media (min-width: 900px) {
  /* Kein negativer Rand: Der Link ragte sonst aus seinem li (Sichtprüfung). */
  .menu--plakat > ul > li:not(.menu-aktion) > a { padding-inline: 0.4rem; }
  .menu--plakat > ul > li:not(.menu-aktion) > a::before {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--tinte-dunkel);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform 0.38s var(--kurve);
  }
  .kopf[data-fest='ja'] .menu--plakat > ul > li:not(.menu-aktion) > a::before { background: var(--feld-rot); }
  .menu--plakat > ul > li:not(.menu-aktion) > a:hover::before,
  .menu--plakat > ul > li:not(.menu-aktion) > a:focus-visible::before { transform: scaleX(1); }
  /* Höhere Spezifität: Die Grundregel mit `left: 0` steht weiter unten. */
  .menu.menu--plakat > ul > li:not(.menu-aktion) > a::after { left: 0.4rem; z-index: 1; }
}
.menu--plakat > ul > li:not(.menu-aktion) > a::after {
  content: attr(data-text);
  position: absolute;
  left: 0;
  top: 100%;
  padding-block: 0.15rem;
  transition: translate 0.38s var(--kurve);
}
.menu--plakat > ul > li:not(.menu-aktion) > a:hover > span,
.menu--plakat > ul > li:not(.menu-aktion) > a:focus-visible > span,
.menu--plakat > ul > li:not(.menu-aktion) > a:hover::after,
.menu--plakat > ul > li:not(.menu-aktion) > a:focus-visible::after { translate: 0 -100%; }
/* Der aktuelle Punkt: ein gefüllter Balken darunter, der beim Laden
   aufzieht. Kein Unterstrich, keine Akzentschrift (läge rot auf rot). */
.menu--plakat a[aria-current='page'] { text-decoration: none; }
.menu--plakat a[aria-current='page'] > span { box-shadow: inset 0 -4px 0 var(--tinte); }
.menu--plakat a:hover { text-decoration: none; }

.menu--plakat .menu-aktion .knopf {
  padding: 0.6rem 1.15rem;
  font-size: 1.125rem;
  line-height: 1.15;
}
/* Über dem roten Hero und auf den Bildköpfen ist der Knopf schwarz, auf
   der deckenden Kopfzeile rot. */
.kopf:not([data-fest='ja']) .menu--plakat .menu-aktion .knopf { background: var(--tinte-dunkel); color: var(--tinte); }
/* Die Schrift folgt beim Drüberfahren der aufziehenden Fläche; die Regeln
   oben setzen sie fest und schlügen sonst die allgemeine Hover-Farbe. */
.menu--plakat .menu-aktion .knopf:hover,
.kopf:not([data-fest='ja']) .menu--plakat .menu-aktion .knopf:hover { color: var(--knopf-fuell-tinte); }
.menu-abzug { display: none; }

@media (prefers-reduced-motion: reduce) {
  .kopf, .menu--plakat a > span, .menu--plakat a::after, .menu--plakat a::before { transition: none; }
}

/* Telefon und Tablet: rotes Vollbild, das vom Menüknopf aus aufgeht. */
@media (max-width: 899px) {
  .kopf[data-offen='ja'] { background: transparent; }
  .kopf-innen .logo, .menu-knopf { position: relative; z-index: 2; }

  .menu.menu--plakat {
    inset: 0;
    z-index: 1;
    justify-content: space-between;
    padding: calc(var(--kopf-hoehe) + 1.5rem) var(--gutter) 2rem;
    background: var(--feld-rot);
    background-image: none;
    opacity: 1;
    transform: none;
    clip-path: circle(0 at calc(100% - var(--gutter) - 22px) 40px);
    transition: clip-path 0.6s var(--kurve), visibility 0s linear 0.6s;
  }
  .kopf[data-offen='ja'] .menu.menu--plakat {
    clip-path: circle(150vmax at calc(100% - var(--gutter) - 22px) 40px);
    transition: clip-path 0.7s var(--kurve), visibility 0s;
  }

  .menu--plakat ul { align-items: flex-start; gap: 0; }
  .menu--plakat li { justify-content: flex-start; overflow: hidden; }
  .menu--plakat > ul > li:not(.menu-aktion) > a {
    font-size: clamp(4rem, 19vw, 8rem);
    line-height: 0.95;
    letter-spacing: -0.005em;
    padding-block: 0;
  }
  .menu--plakat > ul > li:not(.menu-aktion) > a::after { padding-block: 0; }
  .menu--plakat > ul > li:not(.menu-aktion) > a::before { content: none; }
  .menu--plakat a[aria-current='page'] > span { box-shadow: inset 0 -0.08em 0 var(--tinte); }

  /* Jeder Punkt schiebt sich aus seiner Zeile hoch, nacheinander. Die
     Grundregel der Vorlage blendete ein; hier bewegt nur die Maske. */
  .menu--plakat li,
  .kopf[data-offen='ja'] .menu--plakat li { opacity: 1; transform: none; }
  .menu--plakat li > a { translate: 0 105%; transition: translate 0.55s var(--kurve); }
  .kopf[data-offen='ja'] .menu--plakat li > a { translate: 0 0; }
  .kopf[data-offen='ja'] .menu--plakat li:nth-child(1) > a { transition-delay: 0.12s; }
  .kopf[data-offen='ja'] .menu--plakat li:nth-child(2) > a { transition-delay: 0.18s; }
  .kopf[data-offen='ja'] .menu--plakat li:nth-child(3) > a { transition-delay: 0.24s; }
  .kopf[data-offen='ja'] .menu--plakat li:nth-child(4) > a { transition-delay: 0.30s; }
  .kopf[data-offen='ja'] .menu--plakat li:nth-child(5) > a { transition-delay: 0.38s; }

  .menu--plakat .menu-aktion { margin-top: 1.75rem; overflow: visible; }
  .menu--plakat .menu-aktion .knopf,
  .kopf:not([data-fest='ja']) .menu--plakat .menu-aktion .knopf {
    padding: 1rem 1.75rem;
    font-size: 1.375rem;
    background: var(--tinte-dunkel);
    color: var(--tinte);
  }
  .menu--plakat .menu-aktion .knopf:hover,
  .kopf:not([data-fest='ja']) .menu--plakat .menu-aktion .knopf:hover { color: var(--knopf-fuell-tinte); }

  /* Ein Abzug fliegt schräg von unten rechts ein. */
  .menu-abzug {
    display: block;
    position: absolute;
    right: -6vw;
    bottom: 9svh;
    z-index: -1;
    width: min(46vw, 300px);
    margin: 0;
    padding: 8px 8px 1.75rem;
    background: var(--feld-weiss);
    rotate: 14deg;
    translate: 20% 60%;
    opacity: 0;
    transition: rotate 0.7s var(--kurve), translate 0.7s var(--kurve), opacity 0.3s ease;
  }
  .menu-abzug img { width: 100%; height: auto; aspect-ratio: 3 / 4; object-fit: cover; }
  .kopf[data-offen='ja'] .menu-abzug {
    rotate: 6deg;
    translate: 0 0;
    opacity: 1;
    transition-delay: 0.3s;
  }

  .menu--plakat .menu-fuss {
    justify-items: start;
    text-align: left;
    max-width: 55%;
    margin-top: 2rem;
  }
  .menu--plakat .menu-fuss p,
  .menu--plakat .menu-fuss a { color: var(--tinte); font-size: 1rem; }
  .menu--plakat .menu-fuss .fuss-social a { color: var(--tinte); }

  /* Der Knopf wird zum Kreuz und dreht sich dabei einmal. */
  .menu-knopf { transition: rotate 0.45s var(--kurve); }
  .kopf[data-offen='ja'] .menu-knopf { rotate: 180deg; }

  @media (prefers-reduced-motion: reduce) {
    .menu.menu--plakat, .kopf[data-offen='ja'] .menu.menu--plakat { transition: visibility 0s; }
    .menu--plakat li > a { translate: 0 0; transition: none; }
    .menu-abzug { transition: none; }
    .menu-knopf { transition: none; }
  }
}

/* ---- Hero ----------------------------------------------------------- */
/* Hero 06H (Betreiber, 03.11.2026): die Plakatzeile auf Balken in Schwarz
   und Rot, darunter „Willkommen im Velvet" auf Weiß, dahinter eine Diashow.
   Die Balken tragen die Schrift selbst — kein Schleier über den Fotos. */

.hero--plakat {
  height: auto;
  min-height: max(640px, 100svh);
  align-items: end;
  place-items: end stretch;
  text-align: left;
}
.hero--plakat::after { content: none; }
.hero-schau { margin: 0; overflow: hidden; }
.hero-schau picture,
.hero-schau img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero-schau picture + picture { opacity: 0; }
.hero--plakat .hero-text {
  display: grid;
  gap: 1.5rem;
  justify-items: start;
  padding-top: calc(var(--kopf-hoehe) + 2rem);
  padding-bottom: clamp(2.5rem, 9svh, 6.5rem);
}
.hero--plakat .hero-titel {
  margin: 0;
  /* Gedeckelt, damit der Knopf bei 1440 × 900 noch im ersten Bild steht. */
  letter-spacing: -0.04em;
  font-size: min(7.5vw, 7rem, 10.5svh);
  font-weight: 800;
  line-height: 1;
}
/* Vier Zeilen, jede ein eigener Balken auf Textbreite: Schwarz trägt
   „Take more / chances,", Rot „dance more / dances.". Innerhalb einer Farbe
   stoßen die Balken aneinander (Treppe), zwischen Schwarz und Rot bleibt
   eine Lücke (Betreiber, 03.11.2026: „trenn Rot und Schwarz, dass die sich
   nicht berühren"). Als Blöcke statt Inline-Text: So folgt der Balken der
   Zeile und nicht dem Unterlängenraum der Schrift, der Text sitzt mittig. */
.hero--plakat .hero-titel span {
  display: block;
  width: fit-content;
  line-height: 0.9;
  /* Oben 0,1 em mehr als unten: gemessen saß die Schrift sonst hoch im
     Balken (390 px: 4 zu 9 px, 1440 px: 9 zu 23 px über/unter den
     Versalien). Das Komma von „chances,“ bleibt im unteren Polster. */
  padding: 0.14em 0.14em 0.1em;
}
.hero--plakat .hero-titel span:nth-child(-n + 2) { background: var(--nacht); }
.hero--plakat .hero-titel span:nth-child(n + 3) { background: var(--feld-rot); }
.hero--plakat .hero-titel span:nth-child(3) { margin-top: 0.22em; }
.hero-gruss {
  margin: 0;
  padding: 0.3em 0.45em 0.2em;
  background: var(--tinte);
  color: var(--tinte-dunkel);
  font-family: var(--schrift-display);
  font-weight: 800;
  font-size: clamp(1.375rem, 2.2vw, 2rem);
  line-height: 1;
  text-transform: uppercase;
}
.hero--plakat .hero-text .knopf {
  --knopf-fuell: var(--feld-rot);
  --knopf-fuell-tinte: var(--tinte);
  /* Größe wie überall; `.hero-text .knopf` der Vorlage setzt sie kleiner. */
  padding: 1.05rem 1.5rem 1rem 1.6rem;
  font-size: 1.1875rem;
  background: var(--tinte-dunkel);
}
@media (max-width: 899px) {
  .hero--plakat .hero-titel { font-size: 12vw; }
}

/* ---- Felder ---------------------------------------------------------- */

.abschnitt--rot { background: var(--feld-rot); color: var(--tinte); }
.abschnitt--schwarz { background: var(--nacht); }
/* Abschnittsabstand der Plakat-Fassung: deutlich größer als jeder Abstand
   innerhalb eines Abschnitts (120–190 px auf dem Schreibtisch). */
.abschnitt.abschnitt--schwarz,
.abschnitt.abschnitt--rot { padding-block: clamp(8.5rem, 13vw, 12rem); }
.abschnitt--rot .knopf { background: var(--tinte-dunkel); border-color: var(--tinte-dunkel); color: var(--tinte); }
.abschnitt--rot .knopf:hover { color: var(--knopf-fuell-tinte); }

/* ---- Plakatzeile mit Abzügen ------------------------------------- */

.abzuege {
  /* Plakatzeile oben, die Abzüge darunter wie hingeworfen. Sie liegen
     neben der Schrift, nie darauf (Prüfregel „covered-text"). */
  display: grid;
  gap: clamp(2.5rem, 5vw, 4.5rem);
  padding-block: clamp(8rem, 13vw, 12rem) clamp(5rem, 8vw, 8rem);
  overflow: hidden;
}
.abzuege h2 {
  /* Die längere Zeile („WHO SAID NIGHTS") ist kürzer als die frühere
     Plakatzeile (8,1 em): Sie passt in die Hülle (1200 px) und auf das
     Telefon, ohne ein drittes Mal umzubrechen. */
  font-size: clamp(2rem, 8.5vw, 8rem);
  line-height: 1;
}
/* Vier Wortgruppen, die je nach Breite anders zu Zeilen werden: auf dem
   Schreibtisch „Who said nights / were for sleep?", auf dem Telefon
   „Who said / nights were / for sleep?" — drei kurze Zeilen tragen dort
   eine deutlich größere Schrift (Betreiber, 03.11.2026: „mobil größer"). */
.abzuege h2 span { display: inline; }
.abzuege h2 span:nth-child(2)::after { content: '\A'; white-space: pre; }
@media (max-width: 699px) {
  .abzuege h2 { font-size: min(15vw, 6rem); }
  .abzuege h2 span:nth-child(2)::after { content: none; }
  .abzuege h2 span:nth-child(1)::after,
  .abzuege h2 span:nth-child(3)::after { content: '\A'; white-space: pre; }
}
.abzuege-stapel {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  /* Die Reihe läuft über beide Ränder und schneidet selbst ab (sonst
     liefe sie formal über, auch wenn der Abschnitt nichts scrollen lässt).
     Polster oben und unten, damit Drehung, Versatz und Hover-Vergrößerung
     nicht gekappt werden. */
  padding-block: 2rem 4.5rem;
  margin-block: -2rem -4.5rem;
  overflow: hidden;
}
.abzug {
  position: relative;
  z-index: 1;
  margin: 0 -1.2vw;
  padding: 10px 10px 2.25rem;
  background: var(--feld-weiss);
  color: var(--tinte-dunkel);
  width: 21.5vw;
  /* Weich und lang statt 0,25 s (Betreiber, 03.11.2026: „so ruckartig").
     Alle Abzüge sind von vornherein positioniert; vorher wechselte beim
     Drüberfahren auch die Positionierung, und der Abzug sprang. */
  transition: rotate 0.7s var(--kurve-weich), scale 0.7s var(--kurve-weich), translate 0.7s var(--kurve-weich), opacity 0.6s ease, transform 0.8s var(--kurve);
}
.abzug img { width: 100%; height: auto; aspect-ratio: 3 / 4; object-fit: cover; }
/* `rotate`/`translate` statt `transform`: Die Einblendung setzt danach
   `transform: none` und hätte die Drehung sonst mitgelöscht. */
.abzug:nth-child(1) { rotate: -7deg; }
.abzug:nth-child(2) { z-index: 2; rotate: 4deg; translate: 0 3rem; }
.abzug:nth-child(3) { rotate: -2deg; translate: 0 1rem; }
.abzug:nth-child(4) { z-index: 2; rotate: 6deg; translate: 0 2.5rem; }
.abzug:nth-child(5) { rotate: -5deg; translate: 0 0.5rem; }
@media (hover: hover) {
  .abzug:hover { z-index: 3; rotate: 0deg; scale: 1.04; }
}
.abzug:focus-within { z-index: 3; rotate: 0deg; scale: 1.04; }
/* Telefon: die drei ersten nebeneinander wie auf dem Schreibtisch, kleiner
   versetzt; vier und fünf entfallen. Der Hover-Effekt gilt nur für Geräte
   mit Maus, beim Antippen springt nichts. */
@media (max-width: 899px) {
  .abzug:nth-child(n + 4) { display: none; }
  .abzuege-stapel { padding-block: 1.5rem 3rem; margin-block: -1.5rem -3rem; }
  .abzug { width: 37vw; margin: 0 -2.5vw; padding: 6px 6px 1.25rem; }
  .abzug:nth-child(2) { translate: 0 1.5rem; }
  .abzug:nth-child(3) { translate: 0 0.5rem; }
}

/* ---- Das Velvet: Treppe ---------------------------------------------- */
/* Variante `.ueber--treppe` des Systembausteins `.ueber`: fünf Porträts
   steigen randlos nach rechts an, Titel und Text stehen im frei werdenden
   Winkel (Fassung L, Betreiber 04.11.2026). Auf dem Telefon wären fünf
   Spalten nur 75 Pixel breit, dort steigen drei an, der Text steht darunter. */
.ueber-block { padding-top: clamp(5rem, 9vw, 8rem); }
.ueber--treppe {
  position: relative;
  display: flex;
  gap: 6px;
  align-items: flex-end;
  height: min(70vw, 1000px);
}
.ueber-kopf {
  position: absolute;
  top: 0;
  left: max(var(--gutter), calc((100vw - 1200px) / 2 + var(--gutter)));
  width: 50vw;
}
.ueber-titel { font-size: clamp(3rem, 7vw, 6.5rem); line-height: 1; margin-bottom: 1.25rem; }
.ueber-kopf .ueber-text p { max-width: 46ch; color: var(--tinte); font-size: 0.9375rem; line-height: 1.55; text-align: left; }
.portraet { flex: 1 1 0; min-width: 0; margin: 0; overflow: hidden; }
.portraet img { width: 100%; height: 100%; object-fit: cover; }
.portraet:nth-of-type(1) { height: 32%; }
.portraet:nth-of-type(2) { height: 46%; }
.portraet:nth-of-type(3) { height: 62%; }
.portraet:nth-of-type(4) { height: 80%; }
.portraet:nth-of-type(5) { height: 100%; }
/* Schmaler Schreibtisch: Der Text bricht öfter um und läge sonst auf der
   dritten Spalte. */
@media (min-width: 900px) and (max-width: 1279px) {
  .ueber--treppe { height: 88vw; }
}
@media (max-width: 899px) {
  .ueber--treppe { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; align-items: end; height: auto; }
  .ueber-kopf { display: contents; }
  .ueber-titel { position: absolute; top: 0; left: var(--gutter); width: min-content; margin: 0; font-size: 15vw; line-height: 1; }
  .ueber-text { grid-column: 1 / -1; order: 1; padding: 1.5rem var(--gutter) 4rem; }
  .portraet:nth-of-type(2), .portraet:nth-of-type(3) { display: none; }
  .portraet:nth-of-type(1) { height: 60vw; }
  .portraet:nth-of-type(4) { height: 92vw; }
  .portraet:nth-of-type(5) { height: 142vw; }
}

/* ---- Sprachwahl im Menü ----------------------------------------------- */
.menu-sprachen { display: flex; gap: 2px; align-items: center; }
.menu--plakat .menu-sprachen a { padding: 0.3rem 0.35rem 0.25rem; color: var(--tinte); font-size: 0.875rem; line-height: 1; text-decoration: none; }
.menu--plakat .menu-sprachen a:hover { text-decoration: underline; }
.menu--plakat .menu-sprachen a[aria-current] { background: var(--tinte); color: var(--tinte-dunkel); }
@media (max-width: 899px) {
  .menu--plakat .menu-sprachen a { padding: 0.5rem 0.6rem 0.45rem; font-size: 1.125rem; }
}

/* ---- Fotos ------------------------------------------------------------ */
/* Die Alben als Plakate: Deckblatt 2:3, Titel im Balken wie im Hero, darunter
   Datum und Anzahl im hellen Balken wie „Willkommen im Velvet“. */
.alben-raster {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
  gap: 6px;
}
.album-karte { position: relative; display: block; overflow: hidden; container-type: inline-size; aspect-ratio: 2 / 3; background: var(--box); color: var(--tinte); text-decoration: none; }
.album-karte:focus-visible { outline: 2px solid var(--tinte); outline-offset: 3px; }
.album-bild { position: absolute; inset: 0; }
.album-bild img { display: block; width: 100%; height: 100%; object-fit: cover; transition: scale 0.7s var(--kurve-weich); }
.album-karte:hover .album-bild img { scale: 1.04; }
.album-text { position: absolute; left: 0; right: 0; bottom: 1.25rem; display: grid; justify-items: start; }
/* Am Kartenmaß statt am Fenster: „TRIP2NOSTALGIA“ muss in die Karte passen. */
.album-titel { max-width: 100%; margin: 0; padding: 0.14em 0.2em 0.1em; background: var(--feld-rot); font-size: 10.2cqw; line-height: 0.9; overflow-wrap: anywhere; transition: background 0.3s ease; }
.album-karte:hover .album-titel { background: var(--nacht); }
.album-zeile { margin: 0; padding: 0.45em 0.8em 0.4em; background: var(--feld-weiss); color: var(--tinte-dunkel); font-size: var(--t-klein); font-weight: 700; }

.alben .zurueck { justify-content: flex-start; margin: 0 0 1.5rem; }
.album-kopf { margin-bottom: clamp(1.5rem, 3vw, 2.5rem); }
.album-kopf h2 { font-size: clamp(2.5rem, 7vw, 6rem); line-height: 1; }
.album-kopf p { margin: 0.75rem 0 0; color: var(--tinte); }

/* Spalten statt Raster: Jedes Bild behält sein Format, Hoch- und Querformat
   stehen ohne Beschnitt nebeneinander. */
.fotoraster { column-count: 2; column-gap: 6px; }
@media (min-width: 600px) { .fotoraster { column-count: 3; } }
@media (min-width: 900px) { .fotoraster { column-count: 4; } }
.fotoraster figure { margin: 0 0 6px; overflow: hidden; background: var(--box); break-inside: avoid; cursor: zoom-in; }
.fotoraster img { display: block; width: 100%; height: auto; transition: scale 0.7s var(--kurve-weich); }
.fotoraster figure:hover img { scale: 1.04; }
.fotoraster figure:focus-visible { outline: 2px solid var(--tinte); outline-offset: -2px; }

.lightbox { position: fixed; inset: 0; z-index: 200; display: none; place-items: center; padding: clamp(1rem, 5vw, 3rem); background: rgb(0 0 0 / 92%); }
.lightbox[data-offen='ja'] { display: grid; }
.lb-bild { max-width: 100%; max-height: 82vh; object-fit: contain; }
.lb-zaehler { position: absolute; bottom: 1.25rem; left: 50%; translate: -50% 0; margin: 0; color: var(--tinte); font-size: var(--t-klein); }
.lb-knopf { position: absolute; display: grid; place-items: center; width: 48px; height: 48px; border: 0; background: var(--feld-rot); color: var(--tinte); cursor: pointer; transition: background 0.2s ease, color 0.2s ease; }
.lb-knopf:hover { background: var(--tinte); color: var(--tinte-dunkel); }
.lb-zu { top: 1rem; right: 1rem; }
.lb-original { top: 1rem; right: calc(1rem + 54px); }
.lb-melden { top: 1rem; right: calc(1rem + 108px); display: flex; gap: 0.45rem; align-items: center; width: auto; padding-inline: 0.9rem; font-family: var(--schrift-display); font-size: 1rem; font-weight: 800; letter-spacing: 0.01em; text-decoration: none; text-transform: uppercase; }
.lb-rueck { left: 1rem; top: 50%; translate: 0 -50%; }
.lb-vor { right: 1rem; top: 50%; translate: 0 -50%; }

/* ---- Newsletter ---------------------------------------------------- */

.newsletter--leiste h2 { font-size: var(--t-h2); margin-bottom: 2.5rem; }
.newsletter--leiste .form { display: block; padding: 0; background: none; border: 0; }
.newsletter--leiste .newsletter-zeile {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 8px;
  max-width: none;
  height: auto;
  border: 0;
  border-radius: 0;
  background: none;
  overflow: visible;
}
.newsletter--leiste .newsletter-zeile input {
  height: 96px;
  padding: 0 1.5rem;
  background: rgb(0 0 0 / 22%);
  color: var(--tinte);
  font-size: 1.25rem;
  border-radius: 0;
}
.newsletter--leiste .newsletter-zeile input::placeholder { color: rgb(255 255 255 / 75%); }
.newsletter--leiste .newsletter-zeile input:focus { background: rgb(0 0 0 / 40%); }
.newsletter--leiste .newsletter-zeile .knopf {
  height: 96px;
  border-radius: 0;
  font-size: 1.125rem;
  background: var(--tinte);
  border-color: var(--tinte);
  color: var(--tinte-dunkel);
  --knopf-fuell: var(--tinte-dunkel);
  --knopf-fuell-tinte: var(--tinte);
  /* Plakatschrift wie alle Knöpfe; `.newsletter-zeile .knopf` der Vorlage
     setzte die Textschrift. */
  font-family: var(--schrift-display);
}
.newsletter--leiste .newsletter-zeile .knopf:hover { color: var(--knopf-fuell-tinte); }
.newsletter--leiste .zustimmung { max-width: 60ch; margin-top: 1rem; color: var(--tinte); font-size: 1rem; }
@media (max-width: 699px) {
  .newsletter--leiste .newsletter-zeile { grid-template-columns: 1fr; }
  .newsletter--leiste .newsletter-zeile input,
  .newsletter--leiste .newsletter-zeile .knopf { height: 60px; }
}

/* ---- Fuß: erste Fassung als helles Feld ---------------------------- */
/* Aufbau der ersten Fassung (Betreiber, 03.11.2026: „die alte Version,
   mit neuer Schrift"): Marke und Rechtslinks links, Anfahrt rechts. Das
   Logo ist weiß geliefert und wird auf dem hellen Feld umgekehrt. */

.fuss--hell { background: var(--feld-weiss); color: var(--tinte-dunkel); }
.fuss--hell p, .fuss--hell li { color: var(--tinte-dunkel); font-size: 1rem; }
.fuss--hell a { color: var(--tinte-dunkel); }
.fuss--hell a:hover { color: var(--feld-rot); }
.fuss-logo { width: clamp(110px, 30%, 180px); margin-bottom: 1.25rem; }
.fuss--hell .fuss-logo,
.fuss--hell .clubinio img { filter: invert(1); }
.fuss--hell .fuss-recht a { color: var(--tinte-dunkel); font-weight: 600; }
.fuss-anfahrt h2 { font-size: var(--t-h3); margin-bottom: 1rem; color: var(--tinte-dunkel); }
.fuss--hell .fuss-social a { color: var(--tinte-dunkel); }
.fuss--hell .fuss-social a:hover { color: var(--feld-rot); }

/* ---- Bewegung der Plakat-Fassung ----------------------------------- */

/* Signatur: die Diashow im Hero. Fünf Bilder zu je 7 s, jedes zoomt
   langsam auf (Ken Burns) und blendet in das nächste über. Die Bewegung
   läuft über `scale`/`translate` und `opacity` im Compositor.

   Die Verzögerung ist je Bild um 1,4 s vorgezogen: So steht das erste Bild
   vom ersten Moment an voll da (4 % von 35 s), statt erst einzublenden.
   Aus dem Bild geht es bei 20–24 %, genau dann blendet das nächste ein. */
@keyframes schau-a {
  0%   { opacity: 0; scale: 1.02; translate: 0 0; }
  4%   { opacity: 1; }
  20%  { opacity: 1; }
  24%  { opacity: 0; scale: 1.14; translate: -2% -1%; }
  100% { opacity: 0; scale: 1.14; translate: -2% -1%; }
}
@keyframes schau-b {
  0%   { opacity: 0; scale: 1.14; translate: 2% 1%; }
  4%   { opacity: 1; }
  20%  { opacity: 1; }
  24%  { opacity: 0; scale: 1.02; translate: 0 0; }
  100% { opacity: 0; scale: 1.02; translate: 0 0; }
}
html.anim .hero-schau picture { animation: schau-a 35s linear infinite both; }
html.anim .hero-schau picture:nth-child(even) { animation-name: schau-b; }
html.anim .hero-schau picture:nth-child(1) { animation-delay: -1.4s; }
html.anim .hero-schau picture:nth-child(2) { animation-delay: 5.6s; }
html.anim .hero-schau picture:nth-child(3) { animation-delay: 12.6s; }
html.anim .hero-schau picture:nth-child(4) { animation-delay: 19.6s; }
html.anim .hero-schau picture:nth-child(5) { animation-delay: 26.6s; }

/* Die Balken ziehen beim Laden von links auf. Am ganzen Titel, nicht je
   Zeile: `clip-path` an einem umbrechenden Inline-Element schneidet alles
   ab der zweiten Zeile weg („CHANCES," fehlte in der ersten Runde). */
@keyframes balken-auf { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0); } }
html.anim .hero--plakat .hero-titel { animation: balken-auf 0.8s var(--kurve) both; opacity: 1; }
html.anim .hero-gruss { animation: balken-auf 0.6s var(--kurve) 0.36s both; }
html.anim .hero--plakat .hero-text .knopf { animation: hero-auf 0.7s var(--kurve) 0.5s both; }

/* Teile eines Abschnitts laufen nacheinander ein: Text, dann die Porträts. */
html.anim .portraet[data-reveal]:nth-of-type(2) { transition-delay: 0.08s; }
html.anim .portraet[data-reveal]:nth-of-type(3) { transition-delay: 0.16s; }
html.anim .portraet[data-reveal]:nth-of-type(4) { transition-delay: 0.24s; }
html.anim .portraet[data-reveal]:nth-of-type(5) { transition-delay: 0.32s; }
/* Die allgemeine Einblendung (`html.anim [data-reveal]`) setzt ihre eigene
   Übergangsliste und schlägt `.abzug` — Drehung und Vergrößerung sprangen
   dadurch ohne Übergang (das „Ruckartige"). Hier beides zusammen; die
   gestaffelte Verzögerung unten gilt nur fürs Einblenden, nicht fürs
   Drüberfahren. */
html.anim .abzug[data-reveal] {
  transition: rotate 0.7s var(--kurve-weich), scale 0.7s var(--kurve-weich), translate 0.7s var(--kurve-weich), opacity 0.55s ease, transform 0.75s var(--kurve);
}
html.anim .abzug[data-reveal]:nth-child(2) { transition-delay: 0s, 0s, 0s, 0.1s, 0.1s; }
html.anim .abzug[data-reveal]:nth-child(3) { transition-delay: 0s, 0s, 0s, 0.2s, 0.2s; }
html.anim .abzug[data-reveal]:nth-child(4) { transition-delay: 0s, 0s, 0s, 0.3s, 0.3s; }
html.anim .abzug[data-reveal]:nth-child(5) { transition-delay: 0s, 0s, 0s, 0.4s, 0.4s; }
.portraet img { transition: transform 0.6s var(--kurve); }
.portraet:hover img { transform: scale(1.03); }


/* ------------------------------------------------------------- Bewegung -- */

/* **Alles haengt an `html.anim`.** Diese Klasse setzt `assets/js/anim.js`,
   und zwar nur, wenn das Modul wirklich laeuft und `prefers-reduced-motion`
   nicht gesetzt ist. Faellt das Skript aus, bleibt die Klasse weg — und
   damit auch jede Regel, die etwas unsichtbar macht. Die Seite steht dann
   vollstaendig da, nur ohne Bewegung.

   Bewegt wird ausschliesslich `transform` und `opacity`. Beides laeuft im
   Compositor; alles andere (Hoehe, Position, Filter) erzwingt eine
   Neuberechnung des Layouts und ruckelt auf dem Telefon. */

html.anim [data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.55s ease, transform 0.75s var(--kurve);
}
html.anim [data-reveal][data-sichtbar='ja'] {
  opacity: 1;
  transform: none;
}

/* Karten laufen versetzt ein, statt als Block aufzutauchen. Die
   Verzoegerung steht je Position im CSS, weil ein Inline-Style unter
   `style-src 'self'` nicht erlaubt waere. */
html.anim .karten [data-reveal]:nth-child(2) { transition-delay: 0.09s; }
html.anim .karten [data-reveal]:nth-child(3) { transition-delay: 0.18s; }
html.anim .karten [data-reveal]:nth-child(4) { transition-delay: 0.27s; }
html.anim .karten [data-reveal]:nth-child(5) { transition-delay: 0.36s; }
html.anim .karten [data-reveal]:nth-child(6) { transition-delay: 0.45s; }

/* Der Flyer zieht beim Darueberfahren leicht an. Die Karte selbst hebt
   schon ab — zusammen wirkt es, als laege das Bild tiefer in der Karte. */
.karte-bild { overflow: hidden; }
.karte-bild img { transition: transform 0.55s var(--kurve); }
.karte:hover .karte-bild img { transform: scale(1.05); }

/* Der Hero laeuft beim Laden auf: Logo, Titel, Knopf nacheinander. Kein
   Scroll-Ausloeser noetig — er steht ohnehin sofort im Bild. */
@keyframes hero-auf {
  from { opacity: 0; transform: translateY(26px); }
  to   { opacity: 1; transform: none; }
}
html.anim .hero-titel,
html.anim .hero-text .knopf {
  animation: hero-auf 0.9s var(--kurve) both;
}
html.anim .hero-titel       { animation-delay: 0.22s; }
html.anim .hero-text .knopf { animation-delay: 0.40s; }

/* ---------------------------------------------------------------- Fehler -- */

.fehlerseite {
  min-height: 70svh;
  display: grid;
  place-items: center;
  text-align: center;
  padding-block: 4rem;
}
.fehlerseite .kennzahl {
  font-size: clamp(5rem, 18vw, 10rem);
  font-weight: 800;
  line-height: 1;
  color: var(--akzent);
}
.knopf-reihe[data-mitte] { justify-content: center; }

/* Der Knopf unter den Eventkarten steht mittig und mit Abstand — ohne das
   klebt er linksbuendig an der Unterkante der ersten Karte. */
#events .knopf-reihe {
  justify-content: center;
  margin-top: clamp(1.75rem, 4vw, 2.75rem);
}

