/* ============================================================================
   Lange Events — Design und Layout
   ----------------------------------------------------------------------------
   Übernahme von lange-events.com (WordPress + Elementor) auf den
   Clubinio-Stack. Gerüst vom System (Vorlage beachhouse-hp, darin baggi-hp;
   Hero, Eventkarte und Fuß aus dem Systemkanon cosmopolar/top10-singen),
   Marke vom Original: Farben, Schriften und Größen sind an der laufenden
   Seite gemessen (referenz/), nicht aus dem Elementor-Kit abgeschrieben.

   Zwei Marken auf einer Seite: Lange Events hell, Weiß und Rot (#bf1322);
   der Flash Club auf /flash-club/ dunkel mit Cyan (`.thema-flash`, eine
   Variante über die Token). Titillium für Text und Überschriften, NEXA für
   den Hero, die Verleihkacheln und die Kartentitel.

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

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

/* **Zwei Familien wie im Original**, unverändert übernommen (dort unter
   wp-content/uploads/2025/09 und 2025/12), Familiennamen wie dort:

   „Titillium" (Titillium Web) trägt Text, Überschriften, Menü und Knöpfe:
   400 und 700. **Die Regeln fordern teils 800/900 an wie im Original** —
   geladen ist nur 700, der Browser nimmt diese Datei, ohne künstlich zu
   verfetten (gemessen über `document.fonts`: „Titillium 700").

   „NEXA" (Nexa Text Black) trägt die lauten Zeilen: Hero, Verleihkacheln,
   Kartentitel. Das Original deklariert die Black-Datei als `bold`; hier
   steht sie für 700 bis 900, damit eine Anforderung von 800/900 sie trifft.

   **Lizenz:** Titillium Web — SIL OFL. Nexa Text — kommerziell
   (Fontfabric), siehe assets/fonts/LIZENZEN.md.

   Vorgeladen werden Inter (Fließtext) und Titillium Bold (Überschriften). Wer die Familien tauscht,
   muss die `<link rel="preload">` in allen Seiten **und** in
   `tools/build.py` mitziehen. */
@font-face {
  font-family: 'Titillium';
  src: url('../fonts/titillium-regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Titillium';
  src: url('../fonts/titillium-bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* Inter variabel, dieselbe Datei wie im Systemkanon (md5 e990806d…).
   Bereich 400–700 wie bei Titillium davor: Anfragen nach
   800/900 klemmen auf 700, Inter wird nicht schwerer als die Schrift davor. */
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-var.woff2') format('woff2');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'NEXA';
  src: url('../fonts/nexa-text-black.woff2') format('woff2');
  font-weight: 700 900;
  font-style: normal;
  font-display: swap;
}

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

:root {
  /* Flächen. Gemessen auf lange-events.com: Seitengrund Weiß, Flash-Leiste
     und Fuß #242424, Eventkarten #1a1a1a, Flyerrahmen #0a0a0a. */
  --nacht:        #ffffff;   /* Seitengrund (Name aus dem System) */
  --box:          #f4f4f4;   /* Kästen */
  --box-hell:     #0a0a0a;   /* Fläche hinter dem Flyer — gemessen */
  --flaeche:      #f4f4f4;   /* Abschnittsgrund, wo er sich abheben soll */
  --karte:        #1a1a1a;   /* Eventkarten — gemessen, auf beiden Seiten */
  --kopf:         #242424;   /* Flash-Leiste und Fuß — gemessen */
  --dunkel:       #242424;   /* dunkle Abschnittsfläche (Termine) */
  --linie:        #e3e3e3;   /* Trenner und Rahmen auf Weiß */

  /* Schrift: drei Rollen. Überschriften in Titillium wie im Original,
     Fließtext in Inter (Betreiber 01.11.; im Original Titillium), NEXA nur
     für die lauten Zeilen (`--schrift-marke`). */
  --schrift-display: 'Titillium', 'Titillium Web', system-ui, sans-serif;
  --schrift-text:    'Inter', system-ui, sans-serif;
  --schrift-marke:   'NEXA', 'Titillium', system-ui, sans-serif;

  /* Schrift. Überschriften schwarz, Fließtext im Grau des Originals
     (#54595f, 7,0:1 auf Weiß). */
  --tinte:        #000000;
  --tinte-leise:  #54595f;
  --tinte-still:  #6b6b6b;   /* 5,3:1 auf Weiß; Original #888 (3,5:1) */
  --tinte-rgb:    0 0 0;

  /* Akzent der Marke: gemessen an jeder Fläche rgb(191, 20, 34) = #bf1422.
     Clubinio führt #bf1322 — eine Stufe Grün weniger; es gilt die Messung
     (R1). Weiß darauf 6,6:1. */
  --akzent:       #bf1422;
  --akzent-tinte: #ffffff;
  --akzent-flaeche: #bf1422;
  --akzent-rgb:   191 20 34;
  /* Akzent als Schrift **auf Weiß**: derselbe Wert, 6,6:1. Auf dunklen
     Flächen (Fuß, Karten) reicht er nicht — dort setzt der Abschnitt
     „Dunkle Flächen" unten ein angehobenes Rot. */
  --akzent-text:  #bf1422;

  /* Rundungen: Knöpfe eckig wie im Original (0 bzw. 3px), Karten 12px,
     Formularfelder und Absendeknopf 10px — gemessen. */
  --r-knopf:      3px;
  --r-feld:       10px;
  --r-karte:      12px;
  /* Höhe des Abrisses unter der Perforation; die Kerben rechnen damit. */
  --abriss:       46px;
  --r-klein:      0;

  /* Weiche Schatten statt Rahmen, wo etwas abheben soll. */
  --schatten:     0 1px 2px rgb(0 0 0 / 12%), 0 8px 24px rgb(0 0 0 / 14%);
  --schatten-hoch: 0 2px 4px rgb(0 0 0 / 16%), 0 16px 40px rgb(0 0 0 / 22%);

  /* Deckung des Schleiers über dem Bildabschnitt (Flash „Next Events"). */
  --bild-schleier: 60%;

  /* Erfolgsmeldung der Formulare. Grün, nicht im Akzent — das Rot wäre
     vom Fehlerfall nicht zu unterscheiden. Weiß darauf 5,13:1. */
  --erfolg:       #2e7d32;

  /* Kein Leuchten um Überschriften — das Original setzt keins. */
  --leuchten:     none;

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

  /* Haken und Ausrufezeichen für Kästchen und Rückmeldung — weiß, weil
     sie auf Rot bzw. Grün stehen. */
  --ausruf: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23ffffff' d='M7 2h2v7H7zM7 11h2v2H7z'/%3E%3C/svg%3E");
  --haken: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23ffffff' 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. Inhaltsspalte 1140px wie Elementor „boxed" — gemessen: Inhalt
     ab x = 150 bei 1440, x = 20 bei 390. */
  --breite:       1180px;
  --breite-schmal: 904px;    /* Einleitungstexte: 864px Text + Rand */
  --gutter:       20px;
  /* Die Kopfzeile scrollt mit (`.kopf--zweizeilig`), nichts liegt darunter.
     Der Token bleibt, weil Anker und Menü im System damit rechnen. */
  --kopf-hoehe:   0px;

  /* Typografie in Stufen an den Elementor-Grenzen 767/1024px.
     Gemessen (390 / 768 / 1440):
       Hero (NEXA) 51 / 90 / 90 · Abschnitt 35 / 50 / 50
       Einleitung 15 / 20 / 20 · Fließtext 16 */
  --t-hero:   5.625rem;     /* 90px */
  --t-h1:     2.5rem;       /* 40px — Eventtitel */
  --t-h2:     3.125rem;     /* 50px */
  --t-h2-text: 3.0625rem;   /* 49px — Flash „Place to be" */
  --t-h3:     1.5625rem;    /* 25px — Kartentitel */
  --t-text:   1rem;         /* 16px */
  --t-einl:   1.25rem;      /* 20px — Einleitungsabsätze */
  --t-klein:  0.875rem;
  --t-fuss:   1rem;         /* 16px */
  --t-fuss-recht: 1rem;
}

@media (max-width: 1024px) {
  :root {
    --t-h2-text: 2.5rem;
  }
}

@media (max-width: 767px) {
  :root {
    --t-hero:     3.1875rem;/* 51px */
    --t-h2:       2.1875rem;/* 35px */
    --t-h2-text:  1.875rem;
    --t-einl:     0.9375rem;/* 15px */
    --t-fuss:     0.9375rem;
    --t-fuss-recht: 0.9375rem;
  }
}

/* --------------------------------------------------------------- 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);
  /* 24px auf 16px — gemessen. */
  line-height: 1.5;
  -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);
  /* 700 — der einzige geladene fette Schnitt (siehe @font-face). */
  font-weight: 700;
  /* Zeilenhöhe = Schriftgröße, keine Sperrung — gemessen an allen
     Überschriften des Originals (50/50, 56/56, 75/75). Keine Versalien:
     Lange schreibt gemischt, Versalien setzen die Varianten selbst. */
  line-height: 1;
  text-transform: none;
  letter-spacing: normal;
}

/* **Kurze, laute Zeilen tragen die Displayschrift** (Titillium), nicht
   nur h1 bis h4: die Datumszeile der Eventseite, die Beschriftung im
   Infokasten, die FAQ-Frage, der Zurück-Verweis, die Kennzahl der
   Fehlerseite, der Sprunglink. Die Werte im Infokasten (`dd`) bleiben in
   der Textschrift — das sind ganze Wörter, keine Etiketten. */
.event-datum,
.infokasten dt,
.faq summary,
.zurueck,
.fehlerseite .kennzahl,
.sprung {
  font-family: var(--schrift-display);
}

/* Gegenstueck dazu: Der Infokasten erbt seine Schrift sonst vom Etikett
   darueber, sobald jemand die Liste oben wieder ergaenzt. */
.infokasten dd { font-family: var(--schrift-text); }

/* 20px zwischen Absaetzen. */
p { margin: 0 0 1.25rem; }
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-flaeche);
  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);
}
/* Schmale Hülle — Systemkanon (fehlte in beachhouse-hp, aus baggi-hp). */
.huelle-schmal { max-width: var(--breite-schmal); }

/* 100px oben und unten — gemessen (Einleitung, Bewertungen, Kontakt). Das
   Original setzt je Abschnitt eigene Werte; die Abweichungen stehen als
   Varianten unten, nicht als Seitenregeln. */
.abschnitt { padding-block: 100px; }
@media (max-width: 767px) { .abschnitt { padding-block: 70px; } }


/* Variante: 50px statt 80px — die Rechtsseiten, gemessen. */
.abschnitt--knapp { padding-block: 50px; }


/* 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. */
.abschnitt-bild {
  position: relative;
  /* 100px oben und unten — gemessen (Flash „Next Events"). */
  padding-block: 100px;
  /* Clubfoto des Originals (bg-quer-1-1.webp), nur hier verwendet. */
  background: url('../img/banner/flash-events.webp') center center / cover no-repeat;
  isolation: isolate;
}
.abschnitt-bild::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgb(0 0 0 / var(--bild-schleier));
}

/* Abschnittskopf: Ueberschrift plus Unterzeile, zentriert. */
/* 35px bis zu den Karten, am Telefon 40px — gemessen. */
.kopfzeile { text-align: center; margin-bottom: 35px; }
@media (max-width: 767px) { .kopfzeile { margin-bottom: 40px; } }
.kopfzeile h2 { font-size: var(--t-h2); line-height: 1; text-shadow: var(--leuchten); }
.kopfzeile p {
  /* Unterzeile ohne Abstand direkt unter der Überschrift — gemessen
     (h2 endet bei 1795, die Zeile beginnt bei 1795). */
  margin: 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-text); font-weight: 400; }

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

.knopf {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Pfeil 15px + 5px Abstand = 20px — gemessen (205 − 137 Text − 48 Polster). */
  gap: 5px;
  /* 12px/24px Polster, Zeilenhöhe 15px, **kein Rahmen** — alles gemessen.
     Zusammen ergibt das die 39px Höhe des Originals.

     Die beiden helleren Varianten unten brauchen trotzdem eine Kante. Die
     bekommen sie als `box-shadow: inset` statt als `border` — ein Rahmen
     wuerde sie wieder hoeher machen als den gefuellten Knopf daneben, und
     dann stehen zwei Knoepfe einer Reihe nicht mehr auf einer Linie. */
  padding: 0.75rem 1.5rem;
  border: 0;
  border-radius: var(--r-knopf);
  background: var(--akzent-flaeche);
  color: var(--akzent-tinte);
  font: inherit;
  font-family: var(--schrift-display);
  /* **Nach `font: inherit`, nicht davor.** Die Kurzschreibweise setzt
     `line-height` mit zurück — davor notiert, erbte der Knopf die
     Zeilenhöhe des Fließtexts. */
  font-size: 0.9375rem;      /* 15px — gemessen */
  line-height: 15px;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: normal;
  cursor: pointer;
  transition: transform 0.25s var(--kurve), box-shadow 0.25s var(--kurve),
              background 0.2s ease, color 0.2s ease;
}
/* **Beim Ueberfahren nur abdunkeln, nicht entleeren.**

   Die Vorlage nimmt dem Knopf die Fuellung und laesst einen Umriss
   stehen. Auf dieser durchgehend dunklen Seite heisst das: Aus einem
   roten Knopf wird fast-schwarz mit duennem Rand — der Betreiber hat es
   als „grau auf grau" beschrieben, und das trifft es.

   Die bestehende Seite setzt `hover:bg-accent/90`, dunkelt also
   dieselbe Farbe leicht ab. `filter: brightness(0.9)` macht genau das
   und gilt zugleich fuer alle Spielarten — rot, gruen, weiss —, ohne
   dass jede ihren eigenen Hoverwert braucht.

   Die beiden helleren Varianten bringen ihre eigenen Regeln mit: Auf
   einer fast durchsichtigen Flaeche richtet Abdunkeln nichts aus. */
.knopf:hover {
  filter: brightness(0.9);
  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.

   **Der Schaft braucht Fläche.** Der Pfad im System lief auf y=12 hin und
   auf derselben Linie zurück — Schaft null breit, sichtbar blieb nur die
   Spitze („›" statt „→"). Gefunden am Bildschirmfoto gegen das Original
   (beachhouse-hp); jetzt Schaft von y=11 bis 13. Gleicher Fehler im
   Zurück-Pfeil unten. */
.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='M4 11h12.17l-5.58-5.59L12 4l8 8-8 8-1.41-1.41L16.17 13H4v-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='M4 11h12.17l-5.58-5.59L12 4l8 8-8 8-1.41-1.41L16.17 13H4v-2Z'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* **Zwei Stufen unter dem Hauptknopf, nicht eine.**

   Vorher trugen beide Zweitknoepfe dieselbe getoente Akzentflaeche. Auf
   der hellen Eventseite standen „Lounge reservieren" und „U18-Formular"
   damit nebeneinander in demselben blassen Ton — als Flaeche zu schwach,
   als Umriss zu unruhig, und ununterscheidbar.

   Jetzt: grau gefuellt fuer die zweite Handlung, reiner Umriss fuer die
   dritte. Beide aus `--tinte-rgb`, also tonabhaengig — auf hellem Grund
   ein helles Grau, auf dunklem ein aufgehelltes. */
/* **Deckend, nicht durchscheinend.** Gemessen am Lounge-Knopf der
   bestehenden Eventseite: `#1e1e1e` als volle Flaeche, Rahmen in
   derselben Farbe. Eine Flaeche aus 10 % Weiss nimmt die Farbe dessen
   an, was dahinter liegt — auf einem Flyerbild sah derselbe Knopf anders
   aus als auf dem Seitengrund.

   Die Kante kommt als `box-shadow: inset`, nicht als `border` — sonst
   waeren diese Knoepfe 3px hoeher als der gefuellte daneben. Siehe
   `.knopf`. */
.knopf-leer {
  background: #1e1e1e;
  color: var(--tinte);
  box-shadow: inset 0 0 0 1px rgb(var(--tinte-rgb) / 12%);
}
.knopf-leer:hover {
  filter: none;
  background: #2a2a2a;
  color: var(--tinte);
  box-shadow: inset 0 0 0 1px rgb(var(--tinte-rgb) / 24%);
}

/* Dritte Stufe: nur Umriss. Fuer Wege, die daneben stehen duerfen, ohne
   um Aufmerksamkeit zu werben — das U18-Formular etwa, das nur eine
   Minderheit der Gaeste braucht. */
.knopf-umriss {
  background: transparent;
  color: var(--tinte);
  box-shadow: inset 0 0 0 1px rgb(var(--tinte-rgb) / 28%);
}
.knopf-umriss:hover {
  filter: none;
  background: rgb(var(--tinte-rgb) / 7%);
  color: var(--tinte);
  box-shadow: inset 0 0 0 1px rgb(var(--tinte-rgb) / 45%);
}

/* **Der Ticketknopf ist der einzige mit Rundung.**

   Gemessen auf der Eventseite der bestehenden Seite: volle Spaltenbreite,
   16px Polster oben und unten (52px hoch), `rounded-lg` = 8px, Sperrung
   0,1em. Die Klasse stand bisher im Markup, ohne dass irgendeine Regel
   daran hing — `tools/build.py` setzt sie seit jeher, das Stylesheet
   kannte sie nicht. */
.knopf-ticket {
  width: 100%;
  padding-block: 1rem;
  /* Scharfkantig wie jeder Knopf hier — die 8px stammten aus baggi-hp. */
  border-radius: var(--r-knopf);
  letter-spacing: 0.1em;
}

.knopf[disabled] { opacity: 0.5; cursor: not-allowed; }
.knopf[disabled]:hover { filter: none; background: var(--akzent-flaeche); 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 --- */

/* **Kopfzeile übernommen** [cosmopolar-Optik, Betreiber 31.10.]: klebend und
   durchsichtig, sie steht über Hero und Banner frei im Bild und bekommt
   erst beim Scrollen einen Grund. Vorher stand hier die deckende, feste
   Leiste des Originals (#161616, Hero ab y = 100).

   `sticky` belegt ihren Platz im Fluss — deshalb ziehen Hero und
   Seitenkopf sich mit negativem Rand darunter (`--kopf-hoehe`). */
.kopf {
  position: sticky;
  top: 0;
  z-index: 50;
  background: transparent;
  isolation: isolate;
  transition: background 0.25s ease;
}

/* Sobald gescrollt wird, bekommt die Zeile einen Grund — darunter liegen
   Text und Karten. **Nur die Farbe aendert sich, nicht die Hoehe**, sonst
   ruckte der Inhalt darunter. Grund ist `--nacht` (#0a0a0a) zu 92 %. */
.kopf[data-fest='ja'] {
  background: rgb(10 10 10 / 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 Kopfzeile, und der Seiteninhalt schiene darunter durch —
   aber nur im gescrollten Zustand, weil `data-fest` erst dort gesetzt wird. */
.kopf[data-offen='ja'] {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* Luft nach oben, oben mehr als unten: Die Zeile rueckt vom Fensterrand
   weg, statt sich mit einer Flaeche vom Bild abzusetzen. Gescrollt sitzt
   sie mittig (unten). **Die Summe bleibt gleich** (28+8 oben, 18+18
   gescrollt — beides 36px), sonst ruckte der Inhalt beim Umschalten. */
.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;
}
.kopf[data-fest='ja'] .kopf-innen {
  padding-top: 1.125rem;
  padding-bottom: 1.125rem;
}

/* `.huelle` begrenzt die Breite, die Zeile laeuft aber ueber die ganze
   Fensterbreite. Das Polster uebernimmt die Zentrierung — so breit wie der
   Rand neben der Inhaltsspalte, nie unter dem Seitenabstand. Ohne
   `+ var(--gutter)`: Die frei stehende Zeile sitzt
   bewusst weiter aussen als der Inhalt. */
.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. 46 / 34px. */
.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); }

/* Abstand zwischen den Punkten, keine Trennstriche [cosmopolar-Optik, Betreiber 31.10.]. Die
   roten Striche des Originals gaben einer deckenden Vollbreitenleiste
   Halt; in der frei stehenden Zeile zerhacken sie nur. */
.menu ul {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.2vw, 1.75rem);
  margin: 0; padding: 0;
  list-style: none;
}

@media (min-width: 900px) {
  /* Punkte rechtsbuendig. Die Grundregel traegt das bereits
     (`justify-content: space-between` mit Marke und Navigation als
     einzigen Kindern). */
  .menu li { display: flex; align-items: center; }
}

/* **`.menu ul a`, nicht `.menu a`.**

   Der Menuefuss mit Anschrift und Social-Symbolen liegt im Markup
   innerhalb von `.menu`. Mit dem weiteren Selektor bekamen auch seine
   Verweise das Polster der Menuepunkte (8px/16px) — und weil die
   Symbolkreise 40px breit sind, blieben davon 8px Innenbreite uebrig.
   Das 20px-Symbol lief ueber, und Chrome setzte es wie beim Hero auf
   linksbuendig statt mittig: alle drei Zeichen sassen 6 Pixel zu weit
   rechts in ihrem Kreis.

   Derselbe Mechanismus, derselbe Tag — es lohnt, danach zu suchen, wenn
   etwas „verschoben" aussieht statt falsch bemessen. */
/* Systemmaß der Menüpunkte (16px, 0.04em Sperrung). Die Lange-Leisten
   setzen ihr eigenes Maß in `.kopf--zweizeilig` (unten). */
.menu ul 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 ul a:hover { color: var(--akzent-text); }
.menu ul a[aria-current='page'] { color: var(--akzent-text); }


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

@media (max-width: 899px) {
  /* Menügrenze 899px (vorher 767px wie das Original). Die
     Kopfhöhe dieser Stufe steht bei den Token. */

  /* 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 ul 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. */


  /* Ein sehr leiser Schein in der Markenfarbe nimmt der Flaeche das
     Tafelhafte, ohne sie einzufaerben. */
  .menu {
    background-image: radial-gradient(70% 40% at 50% 0%,
      rgb(var(--akzent-rgb) / 7%), transparent 70%);
  }

  /* 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. */
  /* Höhe und Unterlauf unter die Kopfzeile übernommen
     [cosmopolar-Optik, Betreiber 31.10.]; vorher 700px fest wie das Original. */
  height: clamp(500px, 71svh, 790px);
  margin-top: calc(var(--kopf-hoehe) * -1);
  display: grid;
  place-items: center;
  overflow: hidden;
  /* Grundbild des Heros. Das Festzeltfoto der Startseite; der Flash-Hero
     setzt sein Videostandbild (`.hero--flash`). */
  background: url('../img/hero-festzelt.webp') center / cover no-repeat;
  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 Kopfzeile und Schrift auf dem Video
   tragen — oben und unten dunkler. Das Original legte keinen; mit der
   durchsichtigen Kopfzeile stuende das Menue sonst ungeschuetzt im hellen
   Bild. */
.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%);
}

/* Inhalt beginnt unter der Kopfzeile, die ueber dem Hero liegt. */
.hero-text {
  position: relative;
  z-index: 2;
  padding-top: var(--kopf-hoehe);
}


/* 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: normal;
  text-shadow: var(--leuchten);
}
.hero-titel span { display: block; }

/* Knapper als die uebrigen Knoepfe: Unter einer sehr
   grossen Ueberschrift muss der Knopf sie nicht noch einmal ueberbieten. */
.hero-text .knopf {
  padding: 0.7rem 1.4rem;
  font-size: 0.8125rem;
}

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

/* `minmax(0, 1fr)`, nicht `1fr`: Sonst zieht das längste Wort der 50px-
   Überschrift die Textspalte breiter (bei 768px 398 statt 324px). */
/* Rand: keiner ab 1025px (1080 = Inhalt), darunter 30px — gemessen. Die
   Hülle bringt ihren eigenen Gutter mit; der wird hier ersetzt. */

/* Rotes Logo über der Überschrift, 148px breit (155px am Telefon).
   **Auf dem Tablet ausgeblendet** — so im Original (Elementor-Schalter
   „auf Tablet verbergen"), nachgemessen bei 768px. */
.ueber-logo { width: 148px; margin-bottom: 1.25rem; }
@media (max-width: 767px) { .ueber-logo { width: 155px; } }
@media (min-width: 768px) and (max-width: 1024px) { .ueber-logo { display: none; } }

.ueber-text h2 {
  font-size: var(--t-h2-text);
  text-shadow: var(--leuchten);
  margin-bottom: 1.25rem;    /* 20px — gemessen */
}
/* Absätze mit 15px Abstand, Knopf 19px darunter — gemessen. */
.ueber-text p { margin: 0 0 15px; color: var(--tinte-leise); }
/* Kein Blocksatz, obwohl das Original ihn setzt: Auf schmalen Spalten
   reißt er Löcher zwischen die Wörter (in der Vorlage bis zu 45px am
   Telefon). Entscheidung im Bericht vorgelegt. */
.ueber-text .knopf-reihe { margin-top: 19px; }

/* Der Knopf bleibt links, auch einspaltig — gemessen (x = 30 bei 390px). */

/* --------------------------------------------------------------- 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));
}
/* Ab Tablet abwärts eine Spalte, **höchstens 400px breit und mittig** —
   gemessen: 400px bei 768, volle Breite bei 390. */

/* 3 × 387 + 2 × 20 = 1201px, mittig — gemessen. Schmaler als die Hülle. */
@media (min-width: 1025px) {
  .karten { max-width: 1201px; margin-inline: auto; }
}
@media (max-width: 1024px) {
  .karten { grid-template-columns: minmax(0, 400px); justify-content: center; }
}

/* **Karte wie im Kanon** [cosmopolar-Optik, Betreiber 31.10.]: gestanzt
   wie eine Eintrittskarte. Vorher die schlichte Fläche des Originals
   (Clubinio-Plugin), ohne Perforation und Schatten. Kartenfläche und
   Rundung kommen aus den Token (`--karte`, `--r-karte`).

   Die Kerben sind **Aussparungen im Kartenhintergrund**, keine farbigen
   Kreise. Der Eventabschnitt der Startseite liegt auf einem Foto — zwei
   Kreise in der Grundfarbe stünden dort als dunkle Punkte. So stanzen sie
   wirklich, und es zeigt sich, was immer dahinterliegt. */
.karte {
  display: flex;
  flex-direction: column;
  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 übernimmt. */
  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;
}
.karte-titel {
  font-size: var(--t-h3);
  line-height: 1.2;
  /* Wie in Clubinio geschrieben, nicht in Versalien (Betreiber, 31.10.). */
  text-transform: none;
}
/* Ortszeile in der Akzentfarbe, Versalien. */
.karte-ort {
  margin: 0;
  color: var(--akzent-text);
  font-size: var(--t-klein);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
/* Termin in der Schrift des Abrisses — im Kanon steht er dort (so auch
   hier, cards.js). */
.karte-termin {
  margin: 0;
  color: var(--tinte-leise);
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  white-space: nowrap;
}
/* Der Abschnitt unter der Perforation, wie bei einer Eintrittskarte.

   Feste Höhe aus `--abriss`, damit die Trennlinie genau dort sitzt, wo die
   Kerben im Kartenhintergrund ausgespart sind. Wüchse der Abschnitt mit
   seinem Inhalt, wanderte die Linie und die Stanzung passte 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;
  border-top: 2px dashed var(--linie);
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
/* Einstiegspreis, darunter klein „zzgl. Systemgebühr". Fehlt ein
   kaufbares Ticket, bleibt das Feld leer (siehe cards.js). */
.karte-preis {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.25;
}
.karte-preis strong { font-weight: 700; }
.karte-preis small {
  font-size: 9px;
  font-weight: 400;
  letter-spacing: 0.02em;
  text-transform: none;
  white-space: nowrap;
  color: var(--tinte-leise);
}
.karte-infos {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  color: var(--akzent-text);
  transition: gap 0.22s var(--kurve);
}
/* Der Pfeil rückt beim Darüberfahren ein Stück weiter — die Karte ist
   ein Link, und das zeigt sie damit. */
.karte:hover .karte-infos { gap: 0.6rem; }

/* Monatsueberschrift der Eventliste. */
/* Zentriert und weiss, ohne Trennlinie — wie im Original. */

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

/* ------------------------------------------------------- Schieberegler -- */

/* Ersetzt Swiper. Das Band wird verschoben, die Folien teilen sich die
   Breite — wie viele gleichzeitig zu sehen sind, sagt `data-zeigen`. */
.slider { position: relative; }

/* Die Spur umfasst **nur das Band**, nicht die Punktreihe. Daran haengen
   zwei Dinge: Das Beschneiden (frueher am Regler) und die senkrechte Mitte
   fuer die Pfeile — die sassen vorher auf der Mitte von Bild plus Punkten
   und damit zu tief.

   `touch-action: pan-y` gibt das senkrechte Scrollen an die Seite weiter
   und behaelt die waagerechte Geste fuer das Blaettern. Ohne das verschluckt
   der Browser entweder das Wischen oder das Scrollen. */
.slider-spur {
  position: relative;
  overflow: hidden;
  touch-action: pan-y;
}
.slider-band {
  display: flex;
  /* `transition` setzt slider.js, damit eine Strecke ohne JavaScript nicht
     erst leer dasteht und dann springt. */
}
.slider-band > figure {
  margin: 0;
  flex: 0 0 100%;
  padding-inline: 0.3125rem;
  box-sizing: border-box;
}
.slider-band img {
  width: 100%;
  object-fit: cover;
  background: var(--box);
  /* Bilder eckig, nur die Eventkarten rund — gemessen. */
  border-radius: var(--r-klein);
}



/* Die Einblick-Strecke zeigt Querformate und laesst sich vergroessern. */
/* Die Über-uns-Strecke zeigt Hochformate 4:5 (Quellen 1080×1350), Folien
   ohne Zwischenraum — gemessen: 510×638, Abstand von Folie zu Folie genau
   510px. */
/* Ohne Platzhaltergrund: Das Original zeigt keinen, und die Fläche hinter
   einem geladenen Bild sieht ohnehin niemand. */
/* Punktreihe 28px unter dem Bild — gemessen über die Mitte der Textspalte,
   die das Raster an der Höhe von Bild plus Punkten ausrichtet. */

.slider-pfeil {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  display: grid;
  place-items: center;
  width: 42px; height: 42px;
  border: 0;
  border-radius: 50%;
  background: rgb(0 0 0 / 45%);
  backdrop-filter: blur(8px);
  color: var(--akzent-text);
  cursor: pointer;
  transition: background 0.15s ease;
}
.slider-pfeil:hover { background: rgb(0 0 0 / 75%); }
.slider-rueck { left: 0.3125rem; }
.slider-vor { right: 0.3125rem; }

.slider-punkte {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 1rem;
}
.slider-punkt {
  width: 8px; height: 8px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  /* Im Original: aktiver Punkt in der Akzentfarbe, die uebrigen weiss. */
  background: var(--tinte);
  opacity: 0.45;
  cursor: pointer;
  transition: background 0.15s ease, opacity 0.15s ease;
}
.slider-punkt[aria-current='true'] { background: var(--akzent); opacity: 1; }


/* Grösse übernommen: rund 51px bei 390, bis 72px. */
/* Unterzeile in der Markenfarbe, Abstand und Grösse übernommen. */

/* Telefon: festes Seitenverhaeltnis 3:2 statt Mindesthoehe — sonst
   klemmt die Schrift zwischen Kopfzeile und Kante. */

/* ------------------------------------------------------------------ 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. */
  /* 672px — gemessen; die Vorlage fuehrt 640. */
  .kontakt-raster[data-ohne-faq='ja'] {
    grid-template-columns: minmax(0, 672px);
    justify-content: center;
  }
}


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

/* 672px — gemessen, auf beiden Formularseiten gleich. Mittig in der
   Huelle, nicht ueber deren volle Breite. */
.form {
  display: grid;
  gap: 1.125rem;
  max-width: 672px;
  margin-inline: auto;
}

/* **`align-content: start` ist nicht kosmetisch.**

   Die Felder einer Reihe sind Rasterzellen und werden auf gleiche Hoehe
   gestreckt. Ohne diese Zeile wachsen die Zeilen darin mit — und weil
   das Altersfeld einen Hinweis darunter traegt (drei Zeilen) und das
   Namensfeld nicht (zwei), verteilte sich der Ueberschuss links auf
   Beschriftung und Eingabefeld: Das linke Feld war **60px hoch statt
   46** und begann 13px tiefer als das rechte.

   Mit `start` behalten die Zeilen ihre Inhaltshoehe, und der Ueberschuss
   bleibt unten stehen, wo er niemanden stoert. */
.feld {
  display: grid;
  gap: 0.5rem;
  align-content: start;
}
/* Systemwert der Feldbeschriftung (Versalien, 12px). Die Marke überschreibt
   ihn unten im Abschnitt „Marke: Formular". */
.feld > span {
  font-size: 0.75rem;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--tinte);
}
/* Pflichtfelder tragen einen roten Stern — wie im Original. */
.feld-pflicht { color: var(--akzent-text); }

/* **Rahmen, Rundung und eine deckende Flaeche** — alles an der
   bestehenden Seite gemessen: `#212121` mit `1px solid #383838`, Radius
   8px, 12/16 Polster, 46px hoch. Die Vorlage faehrt rahmenlose, fast
   durchsichtige Felder; der Kommentar dazu stand hier noch und ist jetzt
   falsch, deshalb weg.

   Die 8px sind dieselbe Ausnahme wie beim Ticketknopf und den
   Bereichskacheln — `--r-feld` bleibt 0, sonst wandert die Rundung
   durchs ganze Projekt. */
input[type='text'], input[type='email'], input[type='tel'],
input[type='number'], input[type='file'], textarea, select {
  width: 100%;
  padding: 0.75rem 1rem;
  border: 1px solid #383838;
  border-radius: 8px;
  background: #212121;
  color: var(--tinte);
  font: inherit;
  /* **Nach `font: inherit`.** Die Kurzschreibweise setzt `line-height`
     zurueck — dieselbe Falle wie beim Knopf. 12+20+12 plus Rahmen ergibt
     die 46px des Originals; mit der geerbten Zeilenhoehe des Fliesstexts
     waren es 66. */
  line-height: 20px;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
:is(input[type='text'], input[type='email'], input[type='tel'],
    input[type='number'], textarea, select):hover:not(:focus) {
  border-color: #4a4a4a;
}
textarea {
  min-height: 150px;
  resize: vertical;
  border-radius: 8px;
}
/* Fokus als schmaler Ring aussen. Er liegt ueber dem Rand, nicht darin,
   und verschiebt deshalb nichts. */
input:focus, textarea:focus, select:focus {
  outline: 0;
  border-color: var(--akzent);
  box-shadow: 0 0 0 2px rgb(var(--akzent-rgb) / 45%);
}
/* **Eigener Wert, nicht `--tinte-still`.** Die Eingabefelder haben jetzt
   einen helleren Grund (`#212121` statt fast durchsichtig); darauf
   erreicht das stille Grau nur 3,91:1. `#8a8a8a` traegt mit 4,66:1 und
   bleibt trotzdem erkennbar leiser als der eingegebene Text. */
::placeholder { color: #8a8a8a; opacity: 1; }

/* 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;
  border-radius: 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: var(--r-klein);
  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-flaeche) 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); 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;
}

/* **Die Erfolgsmeldung war eine rote Textzeile.**

   Rot ist auf dieser Seite die Akzentfarbe — und zugleich die Farbe, in
   der jeder Fehler steht. Wer eine Bewerbung abgeschickt hatte, las
   „Danke! Wir haben deine Bewerbung" in derselben Farbe wie „Bitte
   stimme der Datenschutzerklaerung zu", in derselben Groesse, an
   derselben Stelle. Das ist im besten Fall uebersehbar und im
   schlechteren beunruhigend.

   Jetzt ein eigener Kasten mit Flaeche, Rahmen und Zeichen. Eine
   Einsendung ist der Moment, in dem jemand etwas aus der Hand gibt —
   dort gehoert die deutlichste Rueckmeldung der ganzen Seite hin, nicht
   die leiseste.

   Im Ruhezustand nimmt die Meldung keinen Platz ein: `min-height` auf
   einer leeren Zeile haette sonst dauerhaft eine Luecke ueber dem Knopf
   hinterlassen. */
.rueckmeldung {
  margin: 0;
  font-size: var(--t-klein);
}
.rueckmeldung:empty { display: none; }

.rueckmeldung[data-state='ok'],
.rueckmeldung[data-state='fehler'] {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.875rem;
  align-items: center;
  padding: 1.125rem 1.25rem;
  border-radius: 8px;
  font-size: 1rem;
  line-height: 1.5;
}
/* Das Zeichen als ::before, damit es nicht vorgelesen wird — der Text
   sagt bereits, was los ist. */
.rueckmeldung[data-state='ok']::before,
.rueckmeldung[data-state='fehler']::before {
  content: '';
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background-position: center;
  background-repeat: no-repeat;
  background-size: 15px 15px;
}

/* Gruen, nicht in der Akzentfarbe: Der Akzent ist hier rot und waere
   vom Fehlerfall nicht zu unterscheiden. #2e7d32 traegt weisse Schrift
   mit 5,13:1 (Token `--erfolg`). */
.rueckmeldung[data-state='ok'] {
  background: rgb(46 125 50 / 18%);
  box-shadow: inset 0 0 0 1px var(--erfolg);
  color: var(--tinte);
  font-weight: 500;
}
.rueckmeldung[data-state='ok']::before {
  background-color: var(--erfolg);
  background-image: var(--haken);
}

.rueckmeldung[data-state='fehler'] {
  background: rgb(204 32 38 / 16%);
  box-shadow: inset 0 0 0 1px var(--akzent);
  color: var(--tinte);
}
.rueckmeldung[data-state='fehler']::before {
  background-color: var(--akzent-flaeche);
  background-image: var(--ausruf);
}

.rueckmeldung[data-state='laeuft'] { color: var(--tinte-still); }

/* --- Formular: Systemgestaltung ---------------------------------------------
   Die Marke setzt ihre Abweichungen als `.form--karte` (Abschnitt
   „Bausteine Lange Events"). */
#kontaktformular > p { margin: 0 0 20px; }

/* Felder in der Art von cosmopolar [cosmopolar-Optik, Betreiber 31.10.]
   (Formular 01.11.): Fläche statt Rahmen, gerundet, Name und E-Mail
   nebeneinander, Knopf als Pille über die volle Breite. Schrift und
   Akzent kommen aus den Token. */
.form { max-width: none; gap: 1.125rem; }
.form-reihe {
  display: grid;
  gap: 1.125rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
}
.feld { gap: 0.4rem; }
.feld > span {
  justify-self: start;
  font-size: var(--t-klein);
  line-height: 1.4;
  text-transform: none;
  letter-spacing: normal;
}
input[type='text'], input[type='email'], input[type='tel'], textarea, select {
  padding: 0.95rem 1.05rem;
  border: 0;
  border-radius: 14px;
  background: rgb(var(--tinte-rgb) / 6%);
  line-height: 1.4;
  transition: box-shadow 0.2s ease, background 0.2s ease;
}
:is(input[type='text'], input[type='email'], input[type='tel'], textarea, select):hover:not(:focus) {
  background: rgb(var(--tinte-rgb) / 8%);
}
input:focus, textarea:focus, select:focus {
  background: rgb(var(--tinte-rgb) / 10%);
  box-shadow: 0 0 0 2px rgb(var(--akzent-rgb) / 45%);
}
textarea { min-height: 150px; border-radius: 14px; }
.zustimmung { font-size: var(--t-klein); color: var(--tinte-still); }
.zustimmung input { border-radius: 6px; background: rgb(var(--tinte-rgb) / 6%); }
.form .knopf-reihe { margin-top: 0.75rem; }
.form .knopf-voll {
  width: 100%;
  min-height: 52px;
  border-radius: 999px;
}

/* ------------------------------------------------------------- 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;
}

/* **Untereinander, jeder ueber die volle Breite.**

   Die Vorlage legt Ticket- und Lounge-Knopf nebeneinander (`flex: 1 1
   260px`). Die bestehende Seite stapelt sie: beide 896 Pixel breit, der
   Lounge-Knopf unter dem Ticketknopf. Das ist auch die richtige
   Rangfolge — der zweite Knopf ist kein gleichwertiger Weg, sondern ein
   Zusatz fuer einen Teil der Gaeste, und nebeneinander lesen sie sich
   als Alternative. */
.event .knopf-reihe {
  flex-direction: column;
  margin-bottom: 2rem;
}
.event .knopf-reihe .knopf { width: 100%; }

/* 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-text);
  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-text); }
.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='M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-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='M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-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-text); }

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

/* Rechtsseiten wie im Original: 1140px Spalte, Titel rot und links, kein
   Seitenkopf-Balken. Zwischenüberschriften in der Textschrift, fett —
   die erste Ebene unterstrichen (gemessen im Impressum). */
.rechtstext { max-width: calc(1140px + 2 * var(--gutter)); }
/* 20px Rand unter 1025px, auch auf dem Tablet — gemessen. */
@media (max-width: 1024px) { .rechtstext { padding-inline: 20px; } }
.rechtstext h1 {
  margin-bottom: 20px;
  font-weight: 700;
  color: var(--akzent-text);
  font-size: 2rem;           /* 32px — gemessen */
}
/* **Variante `.rechtstext--schlicht`** (Systemvariante): Titel in der
   Textschrift, wie geschrieben statt in Versalien. */
.rechtstext--schlicht h1 { font-family: var(--schrift-text); text-transform: none; }
.rechtstext h2,
.rechtstext h3 {
  font-family: var(--schrift-text);
  font-size: var(--t-text);
  font-weight: 700;
  line-height: 1.5;
  text-transform: none;
}
.rechtstext h2 { margin: 2rem 0 0; text-decoration: underline; }
.rechtstext h3 { margin: 1.25rem 0 0; }
.rechtstext p, .rechtstext li { color: var(--tinte-leise); }
.rechtstext a { color: var(--akzent-text); text-decoration: underline; }
.rechtstext ul { padding-left: 1.25rem; }
.rechtstext address { font-style: normal; margin-bottom: 1.5rem; }

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

/* Systemfuß (cosmopolar/top10-singen): links Marke und Rechtsverweise,
   rechts Social und Clubinio-Zeichen. Die Vorlage baggi-hp hatte hier
   einen eigenen Fuß mit „Quick Links" und Schlusszeile — der Aufbau des
   Originals entspricht aber dem Kanon.
   Gemessen: Grund #0c0c0c, Polster 72px (61px Tablet, 78px Telefon). */
/* Das untere Polster sitzt an der Hülle, nicht am Fuß: Darunter kommt
   noch die Standzeile auf Seitengrund [roxy-Standzeile, Betreiber 01.11.]. */
.fuss {
  --fuss-polster: 72px;
  background: var(--kopf);
  padding-top: var(--fuss-polster);
}
.fuss > .huelle { padding-bottom: var(--fuss-polster); }
@media (max-width: 1024px) { .fuss { --fuss-polster: 61px; } }
@media (max-width: 767px)  { .fuss { --fuss-polster: 78px; } }

/* Standzeile ganz unten — Maße [roxy-Standzeile, Betreiber 01.11.] (11px, 0.3px
   Sperrung, 10px/16px Polster); Farben aus den Token. */
.stand {
  margin: 0;
  padding: 10px 16px;
  background: var(--nacht);
  font-family: var(--schrift-text);
  font-size: 11px;
  line-height: 1.5;
  letter-spacing: 0.3px;
  text-align: center;
  color: var(--tinte-still);
}

/* 70/30 ab 1025px — die rechte Spalte beginnt bei 962px im 1440er
   Fenster. Darunter eine Spalte, **Social und Clubinio zuerst**: so stapelt
   das Original (gemessen bei 768 und 390). */
.fuss-raster {
  display: grid;
  gap: 56px;
  grid-template-columns: 1fr;
}
@media (min-width: 1025px) {
  .fuss-raster { grid-template-columns: 7fr 3fr; gap: 0; }
}
@media (max-width: 767px) { .fuss-raster { gap: 70px; } }

/* Logo 194px breit (180 Tablet, 140 Telefon) — gemessen. */
.fuss-logo { width: 194px; margin-bottom: 26px; }
@media (max-width: 1024px) { .fuss-logo { width: 180px; } }
@media (max-width: 767px)  { .fuss-logo { width: 140px; margin-bottom: 6px; } }

.fuss-marke p {
  max-width: 484px;
  margin: 0;
  color: var(--tinte-leise);
  font-size: var(--t-fuss);
  line-height: 1.5;
}
@media (max-width: 1024px) { .fuss-marke p { max-width: 449px; } }

/* Rechtsverweise untereinander, rot — gemessen 15px/22,5px (11px am
   Telefon), 20px unter dem Text. */
.fuss .fuss-recht {
  display: flex;
  flex-direction: column;
  max-width: 484px;
  margin-top: 20px;
  font-size: var(--t-fuss-recht);
}
/* Ab Tablet abwärts 30px unter dem Text; am Telefon so breit wie der
   längste Verweis (160px), nicht spaltenbreit — gemessen. */
@media (max-width: 1024px) { .fuss .fuss-recht { max-width: 449px; margin-top: 30px; } }
@media (max-width: 767px)  { .fuss .fuss-recht { width: max-content; } }
.fuss-recht a { color: var(--akzent-text); }
.fuss a:hover { color: var(--tinte); }

/* Symbole frei, rot, 23px (18px unter 1025px), 20px Abstand — so stehen
   sie im Original. */
.fuss-social { display: flex; gap: 20px; margin: 0 0 20px; }
.fuss-social a { display: grid; place-items: center; color: var(--akzent); }
.fuss-social a:hover { color: var(--tinte); }
.fuss-social svg { width: 23px; height: 23px; }
@media (max-width: 1024px) { .fuss-social svg { width: 18px; height: 18px; } }

/* `flex`, nicht `inline-block`: Als Zeileninhalt hängt das Bild sonst 6px
   Unterlänge unter sich an (gemessen bei 768px). */
.clubinio { display: flex; width: max-content; }
.clubinio img { width: 100px; height: auto; }

/* ------------------------------------------------------------- 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-text);
}
/* Der Knopf unter einem Kartenblock steht mittig und mit Abstand — ohne
   das klebt er linksbuendig an der Unterkante der ersten Karte.

   **Ausdrueckliche Kennzeichnung im Markup, nicht ueber die Struktur.** An
   der Abschnitts-ID zu haengen war falsch (die heisst je Projekt anders),
   aber `.abschnitt > .huelle > .knopf-reihe` war zu weit: Auf den
   Eventseiten stehen die Knopfreihen in derselben Struktur und bekamen
   dadurch 44 Pixel Abstand nach oben — zwischen Ticket- und U18-Reihe klaffte
   eine Luecke, und das negative Mass an `.knopf-reihe-u18` war ueberschrieben. */
/* **Die beiden Formulare handhaben ihren Absendeknopf verschieden.**

   Gemessen: Auf /kontakt/ steht er links und nur so breit wie sein Text
   (242px), auf /jobs/ laeuft er ueber die volle Formularbreite (672px).
   Das ist kein Versehen des Originals — das Bewerbungsformular ist
   laenger, und ein schmaler Knopf am Ende einer langen Spalte wird
   uebersehen. Deshalb zwei Faelle statt einer Regel. */
.form .knopf-reihe { justify-content: flex-start; }
.form .knopf-reihe .knopf { width: auto; }
.form .knopf-reihe .knopf-voll { width: 100%; }

.knopf-reihe[data-mitte] {
  justify-content: center;
  margin-top: 40px;          /* gemessen: Karten bis „All Events" */
}
/* Auf dem Tablet 65px — eine Elementor-Stufe, gemessen bei 768px. */
@media (min-width: 768px) and (max-width: 1024px) {
  .knopf-reihe[data-mitte] { margin-top: 65px; }
}

/* ===================================================== Bausteine Lange Events ==
   Alles hier ist entweder eine **Variante** einer Systemklasse (`--…`) oder
   ein **neuer** Baustein, den das System nicht hat. Jeder geht mit einer
   Zeile in docs/ von baggi-hp zurück in die Vorlage (R9). Benannt nach der
   Aufgabe, nie nach Schrift, Farbe oder Pixelzahl.
   ========================================================================== */

/* --- Dunkle Flächen: angehobenes Rot als Schrift ------------------------
   #bf1322 erreicht auf #1a1a1a nur 2,8:1, auf #242424 2,5:1 — nötig sind
   4,5:1. Das Original setzt es trotzdem (Kartendatum, „QUICK LINKS"). Hier
   derselbe Farbton, angehoben: #ff4d5a, 5,4:1 bzw. 4,7:1. Flächen bleiben
   #bf1422. */
.karte, .fuss, .abschnitt--dunkel, .infokasten {
  --akzent-text: #ff4d5a;
  --tinte: #ffffff;
  --tinte-leise: #ffffff;
  --tinte-rgb: 255 255 255;
  --linie: #333333;
  /* Die Schriftfarbe selbst neu setzen: `color` ist am body schon aus dem
     hellen `--tinte` berechnet und wird vererbt — eine geänderte Variable
     allein färbt geerbten Text nicht um. */
  color: var(--tinte);
}

/* --- Kopf: zwei Leisten (Variante von .kopf) ------------------------------
   Oben die Flash-Leiste (#242424), darunter Lange Events auf Weiß, dann der
   rote Eventbalken — gemessen 100 / 100 / 48px bei 1440, 85 / 85 / 85 bei
   768, 65 / 65 / 50 bei 390. **Scrollt mit** wie im Original; die
   Systemkopfzeile klebt und liegt durchsichtig über dem Hero. */
.kopf--zweizeilig,
.kopf--zweizeilig[data-fest='ja'],
.kopf--zweizeilig[data-offen='ja'] {
  position: relative;
  background: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.kopf-leiste { position: relative; background: #ffffff; }
.kopf-leiste--flash { background: var(--kopf); --akzent-text: #06c0ff; --akzent: #06c0ff; }
.kopf--zweizeilig .kopf-innen,
.kopf--zweizeilig[data-fest='ja'] .kopf-innen {
  min-height: 100px;
  padding-block: 0;
  /* Inhalt der Leisten ab x = 144 bei 1440 — gemessen. */
  padding-inline: max(var(--gutter), calc((100% - 1152px) / 2));
}
.kopf--zweizeilig .logo img { height: 35px; }
.kopf--zweizeilig .logo--flash img { height: 57px; }
@media (max-width: 1024px) {
  .kopf--zweizeilig .kopf-innen,
  .kopf--zweizeilig[data-fest='ja'] .kopf-innen { min-height: 85px; padding-inline: 38px; }
  /* Breiten gemessen (198px / 85px) — über die Breite, nicht die Höhe,
     sonst rundet das Seitenverhältnis 4px daneben. */
  .kopf--zweizeilig .logo img { width: 198px; height: auto; }
  .kopf--zweizeilig .logo--flash img { width: 85px; height: auto; }
}
@media (max-width: 767px) {
  .kopf--zweizeilig .kopf-innen,
  .kopf--zweizeilig[data-fest='ja'] .kopf-innen { min-height: 65px; padding-inline: var(--gutter); }
  .kopf--zweizeilig .logo img { width: 214px; height: auto; }
  .kopf--zweizeilig .logo--flash img { width: 153px; height: auto; }
}

/* Menüpunkte: Titillium 20px, Versalien, Trennstriche in der Akzentfarbe
   der Leiste — gemessen (Home 85px breit bei 54,8px Text → 15px Polster). */
.kopf--zweizeilig .menu ul { gap: 0; }
.kopf--zweizeilig .menu ul a {
  display: block;
  padding: 15px;
  font-family: var(--schrift-display);
  font-size: 1.25rem;
  font-weight: 900;
  line-height: 20px;
  letter-spacing: normal;
  color: var(--tinte-leise);
}
.kopf-leiste--flash .menu ul a { color: #ffffff; }
.kopf--zweizeilig .menu ul a:hover,
.kopf--zweizeilig .menu ul a[aria-current='page'] { color: var(--akzent-text); }
@media (min-width: 768px) {
  .kopf--zweizeilig .menu li + li::before {
    content: '';
    width: 2px;
    height: 20px;
    background: var(--akzent);
  }
}
.kopf--zweizeilig .menu-knopf span { background: var(--akzent); }

/* Das System klappt das Menü unter 900px als Vollbild auf. Das Original
   zeigt die Punkte bis 768px in der Leiste (gemessen) — dazwischen hier die
   Leiste zurück. */
@media (min-width: 768px) and (max-width: 899px) {
  .kopf--zweizeilig .menu {
    position: static;
    inset: auto;
    padding: 0;
    background: none;
    opacity: 1;
    transform: none;
    visibility: visible;
    overflow: visible;
    display: block;
  }
  .kopf--zweizeilig .menu ul { flex-direction: row; }
  .kopf--zweizeilig .menu li { opacity: 1; transform: none; display: flex; align-items: center; }
  .kopf--zweizeilig .menu ul a { font-size: 1.25rem; }
  .kopf--zweizeilig .menu-knopf { display: none; }
}
/* Unter 768px: jedes Menü klappt **unter seiner Leiste** auf, nicht als
   Vollbild — der Kopf scrollt mit, ein festes Vollbild hätte keinen
   Bezug zur Leiste, zu der der Knopf gehört. Offen ist nur das Menü mit
   `data-offen="ja"` (ui.js). */
@media (max-width: 767px) {
  .kopf--zweizeilig .menu {
    position: absolute;
    inset: 100% 0 auto;
    z-index: 60;
    display: block;
    padding: 0.5rem var(--gutter) 1.25rem;
    background: inherit;
    background-color: #ffffff;
    background-image: none;
    box-shadow: var(--schatten);
    overflow: visible;
  }
  .kopf-leiste--flash .menu { background-color: var(--kopf); }
  .kopf--zweizeilig .menu:not([data-offen='ja']) {
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
  }
  .kopf--zweizeilig .menu[data-offen='ja'] { opacity: 1; visibility: visible; transform: none; }
  .kopf--zweizeilig .menu ul { align-items: flex-start; gap: 0; }
  .kopf--zweizeilig .menu li { justify-content: flex-start; }
  .kopf--zweizeilig .menu:not([data-offen='ja']) li { opacity: 0; }
  .kopf--zweizeilig .menu ul a { font-size: 1.25rem; padding: 12px 0; letter-spacing: normal; }
}
@media (max-width: 899px) {
  html.menu-offen:has(.kopf--zweizeilig) { overflow: visible; }
}

/* Roter Balken „Alle Events ansehen" unter den Leisten (neu). Die Fläche
   läuft über die Breite, der Link ist so breit wie sein Text — gemessen
   (366px bei 32px Schrift). 48px hoch bei 1440, 85 bei 768, 50 bei 390. */
.eventbalken {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding-inline: var(--gutter);
  background: var(--akzent-flaeche);
}
.eventbalken a {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  min-height: 48px;
  color: var(--akzent-tinte);
  font-family: var(--schrift-display);
  font-size: 2rem;
  font-weight: 800;
  line-height: 1;
  text-transform: uppercase;
}
.eventbalken a:hover { text-decoration: underline; text-underline-offset: 4px; }
/* Pfeil wie am Knopf (gezeichnet, nicht gesetzt — Titillium führt „➔"
   nicht, das Original fiel auf eine Systemschrift zurück). */
.eventbalken a::after {
  content: '';
  width: 0.9em;
  height: 0.9em;
  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='M4 11h12.17l-5.58-5.59L12 4l8 8-8 8-1.41-1.41L16.17 13H4v-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='M4 11h12.17l-5.58-5.59L12 4l8 8-8 8-1.41-1.41L16.17 13H4v-2Z'/%3E%3C/svg%3E") center / contain no-repeat;
}
@media (max-width: 1024px) { .eventbalken { min-height: 85px; } }
@media (max-width: 767px)  {
  .eventbalken { min-height: 50px; }
  .eventbalken a { min-height: 31px; font-size: 1.25rem; }
}

/* --- Knöpfe ---------------------------------------------------------------
   Größenvarianten (neu): Das Original setzt denselben Knopf in drei
   Größen — 15px (Hero), 20px (Verleih), 30px (Über uns); Flash: 19 / 25px.
   Gemessen 39 / 44 / 54px hoch bei 12/24px Polster. Unter 768px alle 15px. */
.knopf--mittel { font-size: 1.25rem; line-height: 20px; }
.knopf--gross  { font-size: 1.875rem; line-height: 30px; }
.thema-flash .knopf { padding: 10px 20px; font-size: 1.1875rem; line-height: 1.5; }
.thema-flash .knopf--gross { font-size: 1.5625rem; font-weight: 800; }
@media (max-width: 767px) {
  .knopf--mittel, .knopf--gross { font-size: 0.9375rem; line-height: 15px; }
  .thema-flash .knopf { font-size: 0.9375rem; }
  .thema-flash .knopf--gross { font-size: 1.25rem; }
}

/* Zweitknopf auf hellem Grund: Die Systemfläche #1e1e1e ist für dunkle
   Seiten gesetzt; auf Weiß trüge sie schwarze Schrift (1,3:1). Hier hell. */
.knopf-leer { background: #ececec; color: var(--tinte); box-shadow: none; }
.knopf-leer:hover { background: #dedede; color: var(--tinte); box-shadow: none; }

/* -------------------------------------------------------------------------
   Lange Events: Titillium 900 15px, gemischt geschrieben, 12/24px Polster,
   3px Rundung, 39px hoch — gemessen am Hero-Knopf. **Ein Maß für alle**:
   Das Original setzt denselben Knopf in drei Größen (15/20/30px Schrift);
   hier gilt das Systemmaß, vorgelegt im Bericht. */
.knopf { text-transform: none; }
.knopf-ohne-pfeil::after { content: none; }

/* --- Hero ------------------------------------------------------------------
   Variante `.hero--links`: Text linksbündig, 802px hoch auf allen Breiten,
   unten eine schräge Kante (Elementor-Form „tilt", 31px) — gemessen. */
.hero--links {
  height: 802px;
  place-items: center start;
  text-align: left;
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 calc(100% - 31px));
}
.hero--links::after {
  background: linear-gradient(90deg, rgb(0 0 0 / 55%) 0%, rgb(0 0 0 / 30%) 55%, rgb(0 0 0 / 10%) 100%);
}
/* Textblock 36px unter der Mitte, 10px weiter innen als die Hülle —
   gemessen (Elementor-Container mit 10px Polster). */
.hero--links .hero-text { padding-top: 72px; }
@media (min-width: 1025px) { .hero--links .hero-text { padding-inline: 30px; } }
@media (min-width: 768px) and (max-width: 1024px) { .hero--links .hero-text { padding-top: 12px; } }
.hero--links .hero-titel {
  margin-bottom: 20px;
  font-family: var(--schrift-marke);
  font-weight: 800;
  line-height: 1;
  color: #ffffff;
}
.hero--links .hero-titel { max-width: 550px; }
.hero-satz {
  max-width: 550px;
  margin: 0 0 22px;
  color: #ffffff;
  font-size: var(--t-einl);
  line-height: 1.5;
}
@media (max-width: 767px) { .hero-satz { font-size: 1.25rem; } }
.hero--links .hero-text .knopf { padding: 0.75rem 1.5rem; font-size: 0.9375rem; }

/* Variante `.hero--flash`: Video, Text mittig, 775px — gemessen. Unten ein
   Cyan-Streifen in Wellenform wie im Original. */
.hero--flash {
  height: 775px;
  background-image: url('../img/flash-still.webp');
}
.hero--flash::before {
  content: '';
  position: absolute;
  inset: auto 0 -1px;
  z-index: 2;
  height: 40px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 40' preserveAspectRatio='none'%3E%3Cpath fill='%2306c0ff' d='M0 30 Q250 0 500 22 T1000 14 V40 H0Z'/%3E%3Cpath fill='%23141414' d='M0 36 Q250 10 500 30 T1000 24 V40 H0Z'/%3E%3C/svg%3E") bottom / 100% 100% no-repeat;
}
.hero--flash::after { background: rgb(0 0 0 / 45%); }
.hero--flash .hero-text { padding-top: 0; }
.hero--flash .hero-titel { font-size: 3.9375rem; font-weight: 800; color: #ffffff; }
@media (max-width: 767px) {
  .hero--flash { height: 810px; }
  .hero--flash .hero-titel { font-size: 2.25rem; }
}
/* Kennzeile über dem Hero-Titel (neu, Gegenstück zu `.ueber-marke`). */
.hero-marke {
  margin: 0 0 10px;
  color: var(--akzent-text);
  font-family: var(--schrift-display);
  font-size: 1.5625rem;
  font-weight: 700;
  line-height: 1;
  text-transform: uppercase;
}

/* --- Über-Block mittig (Variante von .ueber-text) ---------------------------
   Zentrierter Block aus Logo, Überschrift, Absatz und Knopf — zweimal auf
   der Startseite (Über uns, Verleih). Systemblock `.ueber-text` mit
   `.ueber-logo`, hier ohne Bildstrecke und mittig. (Zuerst als eigenes
   `.einleitung` gebaut — eine Parallelsprache, im Abgleich D2 gefunden.)
   Gemessen: Text 864px breit, h2 50/50px schwarz, Absatz 20/30px #54595f,
   40px darunter die Liste bzw. der Knopf. */
.ueber-text--mitte { text-align: center; }
.ueber-text--mitte h2 { font-size: var(--t-h2); line-height: 1; margin-bottom: 40px; }
.ueber-text--mitte p { margin: 0 0 20px; font-size: var(--t-einl); line-height: 1.5; color: var(--tinte-leise); }
.ueber-text--mitte p:last-child { margin-bottom: 0; }
.ueber-text--mitte .knopf-reihe[data-mitte] { margin-top: 40px; }
.ueber-text--mitte .ueber-logo,
.kontakt-text .ueber-logo { display: block; width: 388px; max-width: 100%; margin: 0 auto 40px; }
/* Variante: 20px statt 40px unter Überschrift und Absatz (Verleih) —
   gemessen. */
.ueber-text--knapp h2 { margin-bottom: 20px; }
.ueber-text--knapp .knopf-reihe[data-mitte] { margin-top: 20px; }
/* Tablet: Das Original setzt den Block in eine 461px schmale Spalte
   (x = 154 bei 768) — gemessen. */
@media (min-width: 768px) and (max-width: 1024px) {
  .ueber-text--mitte { max-width: calc(461px + 2 * var(--gutter)); }
}
/* Der feste Umbruch gilt nur auf dem Schreibtisch — darunter bricht die
   Überschrift frei (gemessen: drei statt vier Zeilen bei 768). */
@media (max-width: 1024px) { .ueber-text--mitte br { display: none; } }
@media (max-width: 767px) {
  .ueber-text--mitte { text-align: left; }
  .ueber-text--mitte .knopf-reihe[data-mitte] { justify-content: flex-start; }
  .ueber-text--mitte .ueber-logo { width: 200px; margin: 0 0 30px; }
}

/* Liste mit Haken in der Akzentfarbe (neu). 16px #54595f, Haken 18px. */
.haken-liste {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  margin: 20px 0 0;
  padding: 0;
  list-style: none;
  text-align: left;
  color: var(--tinte-leise);
}
.haken-liste li { display: flex; align-items: center; margin-right: 20px; }
.haken-liste li span { padding-left: 5px; }
.haken-liste li::before { margin-right: 5px; }
.haken-liste li::before {
  content: '';
  width: 13px;
  height: 13px;
  background: var(--akzent);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23000' 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") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23000' 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") center / contain no-repeat;
}
@media (max-width: 767px) { .haken-liste { flex-direction: column; font-size: 0.9375rem; } }

/* --- Abschnittsvarianten ---------------------------------------------------- */
/* Akzentfläche („Kleiner Einblick"): Rot, Schrift weiß — gemessen. */
.abschnitt--akzent {
  background: var(--akzent-flaeche);
  --tinte: #ffffff;
  --tinte-rgb: 255 255 255;
}
.abschnitt--akzent .kopfzeile h2 {
  color: #ffffff;
  font-size: 2.5rem;
  font-weight: 800;
  text-transform: uppercase;
}
@media (max-width: 767px) { .abschnitt--akzent .kopfzeile h2 { font-size: 1.5625rem; } }
.abschnitt--akzent .slider-pfeil { color: #ffffff; }
.abschnitt--akzent .slider-punkt[aria-current='true'] { background: #ffffff; }
#einblick .slider-band img { aspect-ratio: 4 / 3; }
#einblick .kopfzeile { margin-bottom: 30px; }

/* Anschluss an den Abschnitt davor: 20px statt 100px (Verleihkacheln). */
.abschnitt--anschluss { padding-block: 20px; }
/* Ohne unteres Polster — die Karte auf /flash-club/ schließt randlos an. */
.abschnitt--ohne-unten { padding-bottom: 0; }

/* Dunkle Fläche mit schrägen Kanten (Termine der Startseite). Das Original
   legt zwei Elementor-Formen („tilt") über eine graue Fläche; hier eine
   Fläche mit `clip-path`. */
.abschnitt--dunkel { background: var(--dunkel); color: #ffffff; }
.abschnitt--schraeg {
  padding-block: 100px 50px;
  clip-path: polygon(0 0, 100% 60px, 100% 100%, 0 calc(100% - 60px));
}
@media (max-width: 767px) {
  .abschnitt--schraeg {
    padding-block: 100px;
    clip-path: polygon(0 0, 100% 40px, 100% 100%, 0 calc(100% - 40px));
  }
}

/* Abschnittskopf linksbündig (Variante von .kopfzeile). */
.kopfzeile--links { text-align: left; padding-inline: 30px 0; margin-bottom: 20px; }
@media (max-width: 767px) {
  .kopfzeile--links { padding-inline: 20px; }
  .kopfzeile--links h2 { font-size: 1.875rem; }
}

/* Karten linksbündig statt mittig (Variante von .karten). */
@media (min-width: 1025px) {
  .karten--links { max-width: none; margin-inline: 0; }
}

/* --- Eventkarte in der Marke ----------------------------------------------
   Titel in NEXA, Versalien, höchstens zwei Zeilen; Ort in Rot — gemessen.
   Gerüst (Perforation, Abriss) bleibt das der Systemkarte. */
.karte { color: #ffffff; }
.karte-bild { padding-block: 7px; }
.karte-titel {
  font-family: var(--schrift-marke);
  font-weight: 900;
  font-size: var(--t-h3);
  line-height: 1.25;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.karte-ort { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.05em; }
.karte-termin { color: var(--akzent-text); font-size: 0.8125rem; letter-spacing: 0.03em; }
.karte-infos { color: #ffffff; font-weight: 900; }

/* --- Verleihkacheln (neu) --------------------------------------------------
   Drei Spalten à 357px mit 20px Abstand, Kacheln 300px hoch, Titel NEXA
   16px in Versalien links unten (30px Rand) — gemessen. Die Beschreibung
   erscheint beim Darüberfahren und bei Tastaturfokus. */
.kacheln {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
  max-width: calc(1112px + 2 * var(--gutter));
  align-items: start;
}
.kachel-spalte { display: grid; gap: 20px; align-content: start; }
.kachel {
  position: relative;
  height: 300px;
  overflow: hidden;
  background: #6a6a6a;
  isolation: isolate;
}
.kachel img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -2;
  transition: transform 0.6s var(--kurve);
}
.kachel::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgb(0 0 0 / 0%) 40%, rgb(0 0 0 / 70%) 100%);
  transition: background 0.5s ease;
}
.kachel-text {
  position: absolute;
  inset: auto 0 0;
  padding: 0 30px 20px;
  color: #ffffff;
}
.kachel h3 {
  font-family: var(--schrift-marke);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.5;
  text-transform: uppercase;
}
.kachel p {
  max-height: 0;
  margin: 0;
  overflow: hidden;
  opacity: 0;
  font-size: 0.9375rem;
  line-height: 1.45;
  transition: max-height 0.5s ease, opacity 0.5s ease, margin 0.5s ease;
}
.kachel:hover p, .kachel:focus-within p, .kachel:focus p {
  max-height: 12em;
  margin-top: 8px;
  opacity: 1;
}
.kachel:hover::before, .kachel:focus::before { background: rgb(0 0 0 / 70%); }
.kachel:hover img { transform: scale(1.04); }
.kachel:focus-visible { outline: 2px solid var(--akzent); outline-offset: 3px; }
/* Tablet: drei Spalten à 178px, mittig — gemessen bei 768. */
@media (min-width: 768px) and (max-width: 1024px) {
  .kacheln { max-width: calc(574px + 2 * var(--gutter)); }
}
@media (max-width: 767px) {
  .kacheln { grid-template-columns: minmax(0, 1fr); }
}

/* --- Bewertungen (neu) ------------------------------------------------------
   Weiße Karten mit Rahmen, Google-Zeichen, Name, Herkunft, Zitat, Sterne —
   zentriert, 360px breit, 30px Abstand (Folienpolster 15px). */
#stimmen .kopfzeile h2 { font-weight: 800; }
/* Unter den Karten 144px bis zum nächsten Abschnitt (Punkte + Polster) —
   gemessen. */
#stimmen { padding-bottom: 130px; }
/* Karten 360px mit 30px Abstand ab x = 150 — gemessen. Die Folien tragen
   je 15px Polster; die Strecke greift dafür 15px über die Hülle. */
#stimmen .slider-band > figure { padding-inline: 15px; }
#stimmen .slider { margin-inline: -15px; }
.stimme {
  position: relative;
  margin: 0;
  text-align: center;
}
.stimme > * { position: relative; }
.stimme::before {
  content: '';
  position: absolute;
  inset: 0 15px;
  border: 1px solid var(--linie);
  border-radius: 5px;
  background: #ffffff;
}
.stimme img { width: 60px; margin: 30px auto 15px; background: none; }
.stimme figcaption { display: grid; }
.stimme strong { font-weight: 800; }
.stimme figcaption span { color: #6b6b6b; }
.stimme blockquote { margin: 20px 30px 0; color: #6b6b6b; }
/* Sterne: Gold des Originals (#e7a400) misst auf Weiß 2,2:1 — hier
   derselbe Ton dunkler, #a06a00, 4,6:1. */
.stimme-sterne { margin: 15px 0 30px; color: #a06a00; letter-spacing: 2px; }
#stimmen .slider-pfeil { background: none; color: var(--tinte); backdrop-filter: none; }

/* --- Kontakt (Startseite) --------------------------------------------------
   Links Text und Kontaktwege, rechts das Formular in einer Karte —
   gemessen: Überschrift 75/75px Versalien, Absatz 18/27px. */
.kontakt-raster { align-items: center; }
/* Zwei Spalten à 525px, 70px Abstand, Inhalt ab x = 160 — gemessen. */
@media (min-width: 1025px) {
  #kontakt .kontakt-raster {
    grid-template-columns: 525px 525px;
    justify-content: space-between;
    padding-inline: 10px;
  }
}
.kontakt-text h2 {
  font-size: 4.6875rem;
  text-transform: uppercase;
  margin-bottom: 20px;
}
.kontakt-text p { font-size: 1.125rem; line-height: 1.5; }
@media (max-width: 767px) { .kontakt-text h2 { font-size: 2.5rem; } }

/* Kontaktwege: Systembaustein `.zeile` (Symbol + Text, aus dem Kanon
   cosmopolar/top10-singen; in beachhouse-hp fehlte er). Vorher stand hier
   ein eigenes `.kontaktweg` — eine Dublette, im Abgleich D2 gefunden.
   `.kontaktwege` ist nur der Block um die Zeilen (20px Abstand). */
.zeile {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
  color: var(--tinte-leise);
}
.zeile .icon { color: var(--akzent); margin-top: 0.2rem; }
.zeile a:hover { color: var(--akzent); }
/* Variante `.zeile--knapp`: Symbol 13px, Text 5px daneben mit 5px Polster,
   10px Zeilenabstand — gemessen (Text bei x = 178 an Inhaltskante 160). */
.zeile--knapp {
  align-items: center;
  gap: 5px;
  margin-bottom: 10px;
  color: inherit;
}
.zeile--knapp .icon { width: 13px; height: 13px; margin-top: 0; color: var(--akzent-text); }
.zeile--knapp > :not(.icon) { padding-left: 5px; }
.kontaktwege { margin: 20px 0; }
/* `.kontakt-text p` (18px) und `.fuss-marke p` (Rand 0) sind spezifischer
   als die Variante allein — deshalb hier über den Block. */
.kontaktwege > .zeile--knapp { margin: 0 0 10px; font-size: 1rem; line-height: 1.5; }
.kontakt-text .ueber-logo { width: 263px; margin: 10px 0 0; }

/* Formular als Karte (Variante von .form): Felder 40px, leicht getönt, 3px
   Rundung; Nachricht 144px mit 10px; Absenden 52px, 10px, Versalien —
   gemessen am Clubinio-Formular des Originals. */
.form--karte {
  padding: 32px;
  border: 1px solid var(--form-rand, transparent);
  border-radius: 16px;
  gap: 1.1rem;
}
@media (max-width: 767px) { .form--karte { padding: 20px; } }
.form--karte .feld > span { font-size: 0.85rem; font-weight: 700; line-height: 1; color: var(--tinte); }
.form--karte :is(input[type='text'], input[type='email'], input[type='tel']) {
  height: 40px;
  padding: 0 12px;
  border-radius: 3px;
  background: rgb(29 29 29 / 5%);
}
.form--karte textarea { min-height: 144px; padding: 12px; border-radius: 10px; background: rgb(29 29 29 / 5%); }
.form--karte .form-reihe { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
.form--karte .knopf-voll {
  min-height: 52px;
  border-radius: 10px;
  font-size: 1rem;
  font-weight: 800;
  text-transform: uppercase;
}
.form--karte .zustimmung { font-size: 0.8rem; color: var(--tinte); }
.form--karte .zustimmung input { background-color: rgb(29 29 29 / 8%); }
.feld-pflicht { font-style: normal; }
#kontaktformular { padding-top: 0; }

/* --- Fuß ---------------------------------------------------------------------
   Zwei gleiche Spalten: links Logo, Text, Kontaktwege, Clubinio; rechts
   „Quick Links" rechtsbündig — gemessen (40px Polster oben). */
.fuss { --fuss-polster: 40px; }
@media (max-width: 1024px) { .fuss { --fuss-polster: 40px; } }
@media (max-width: 767px)  { .fuss { --fuss-polster: 40px; } }
/* Inhaltskante x = 160 bei 1440 (Container mit 10px Polster), 10 bei 768,
   30 bei 390; zwei Spalten à 550 / 364px mit 20px Abstand, am Telefon
   eine — gemessen. */
.fuss > .huelle { padding-inline: calc(var(--gutter) + 10px); }
@media (max-width: 1024px) { .fuss > .huelle { padding-inline: 10px; } }
@media (max-width: 767px)  { .fuss > .huelle { padding-inline: 30px; } }
.fuss-raster { grid-template-columns: 1fr 1fr; gap: 20px; }
@media (max-width: 767px) { .fuss-raster { grid-template-columns: 1fr; gap: 20px; } }
.fuss-logo { width: 388px; margin-bottom: 20px; }
@media (max-width: 767px)  { .fuss-logo { width: 330px; } }
.fuss-marke p { max-width: 550px; color: #ffffff; }
@media (max-width: 767px) { .fuss-marke p { text-align: justify; } }
.fuss .kontaktwege { font-size: 1rem; }
.fuss .clubinio img { width: 114px; }
.fuss .fuss-recht {
  max-width: none;
  margin-top: 0;
  align-items: stretch;
  text-align: right;
  font-size: var(--t-fuss-recht);
}
.fuss-recht h2 {
  margin-bottom: 20px;
  color: var(--akzent-text);
  font-size: 1.6875rem;
}
.fuss-recht a { color: #ffffff; }
.fuss a:hover, .fuss-recht a:hover { color: var(--akzent-text); }
@media (min-width: 768px) and (max-width: 1024px) {
  .fuss .fuss-recht a { font-size: 0.875rem; line-height: 1.5; }
  .fuss .clubinio img { width: 131px; }
}
@media (max-width: 767px) {
  .fuss .fuss-recht { text-align: left; width: auto; }
  .fuss-recht h2 { font-size: 1.25rem; margin-bottom: 5px; }
  .fuss .clubinio img { width: 119px; }
  .fuss { --fuss-polster: 30px; }
  .fuss > .huelle { padding-bottom: 106px; }
}

/* --- Flash Club: Thema (Variante über die Token) ---------------------------
   Dunkel (#141414), Akzent Cyan #06c0ff — gemessen. **Schrift auf Cyan ist
   schwarz, nicht weiß:** Weiß auf #06c0ff misst 2,1:1 (so im Original),
   Schwarz 10,0:1. Vorgelegt im Bericht. */
.thema-flash {
  --nacht: #141414;
  --tinte: #ffffff;
  --tinte-leise: #ffffff;
  --tinte-still: #a6a6a6;
  --tinte-rgb: 255 255 255;
  --akzent: #06c0ff;
  --akzent-flaeche: #06c0ff;
  --akzent-tinte: #000000;
  --akzent-rgb: 6 192 255;
  --akzent-text: #06c0ff;
  --linie: #2a2a2a;
  --form-rand: #2a2a2a;
  background: var(--nacht);
  color: var(--tinte);
}
.thema-flash .knopf { text-transform: uppercase; font-weight: 700; border-radius: 0; }
.thema-flash h2 { text-transform: uppercase; }
.thema-flash .kopfzeile h2 { font-size: 3.5rem; }
@media (max-width: 767px) { .thema-flash .kopfzeile h2 { font-size: 2.5rem; } }

/* Überschrift mit kurzem Strich darunter in der Akzentfarbe (neu). */
.mit-strich::after {
  content: '';
  display: block;
  width: 110px;
  height: 3px;
  margin-top: 20px;
  background: var(--akzent);
}
.kopfzeile .mit-strich::after { margin-inline: auto; }

/* Über-uns des Flash Club: Systemblock `.ueber-text` ohne Bildstrecke.
   Spalte 1040px mit 27px Polster, Text 843px — gemessen (x = 227 bei
   1440); das Original lässt rechts Raum für ein ausgeblendetes Bild. */
.thema-flash .ueber-text { max-width: 1040px; padding-inline: 27px; }
/* Tablet: 200px Rand wie auf dem Schreibtisch, die Spalte wird dadurch
   schmal (267px bei 768) — gemessen. Telefon: 20px Rand. */
@media (min-width: 768px) and (max-width: 1024px) {
  .thema-flash .ueber-text { padding-inline: 227px; }
}
@media (max-width: 767px) { .thema-flash .ueber-text { padding-inline: 20px; } }
/* Überschrift 49px auf allen Breiten — gemessen (390 / 768 / 1440). */
.thema-flash .ueber-text h2 { font-size: 3.0625rem; }
/* Logo 57px hoch mit Abstand, Abschnitt unten 127px — gemessen. */
.thema-flash #ueber { padding-bottom: 127px; }
.thema-flash .ueber-text > p { max-width: 843px; }
.thema-flash .ueber-text > h2 { max-width: 839px; }
.thema-flash .ueber-text h2 { font-size: var(--t-h2-text); margin-bottom: 30px; }
.thema-flash .ueber-text p { font-size: 1.125rem; line-height: 1.5; }
.thema-flash .ueber-logo { width: 91px; margin-bottom: 37px; }
@media (min-width: 768px) and (max-width: 1024px) { .thema-flash .ueber-logo { display: block; } }
.thema-flash .ueber-text .fuss-social { margin: 30px 0 0; }
.thema-flash .ueber-text .fuss-social svg { width: 23px; height: 23px; }

.unterzeile--adresse { color: #ffffff; text-transform: uppercase; margin-top: 15px; }
.thema-flash .kopfzeile p.unterzeile--adresse { margin-top: 15px; color: #ffffff; text-transform: uppercase; }

/* --- Zwei-Klick-Karte (neu) ------------------------------------------------
   Platzhalter in Kartenhöhe (500px, gemessen), erst der Klick lädt den
   Rahmen von Google (karte.js). */
.zwei-klick {
  position: relative;
  height: 500px;
  margin-top: 50px;
  background: #1e1e1e;
  display: grid;
  place-items: center;
}
.zwei-klick-hinweis { max-width: 560px; padding: 0 var(--gutter); text-align: center; }
.zwei-klick-hinweis a:not(.knopf) { color: var(--akzent-text); text-decoration: underline; }
.zwei-klick-hinweis .knopf-reihe[data-mitte] { margin-top: 20px; }
.zwei-klick-rahmen { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
@media (max-width: 767px) { .zwei-klick { height: 400px; } }

/* Formular des Flash Club: dunkle Felder, Beschriftung hellgrau. */
.thema-flash .form--karte :is(input[type='text'], input[type='email'], input[type='tel'], textarea) {
  background: #1d1d1d;
  color: #ffffff;
}
.thema-flash .form--karte .feld > span { color: #cfd6e0; }
.thema-flash .form--karte .zustimmung { color: #9aa6b5; }
.thema-flash .form--karte .zustimmung input { background-color: rgb(255 255 255 / 14%); }

/* --- Eventseite in der Marke ------------------------------------------------
   Hell wie das Original: Text schwarz ohne Kasten, Datumszeile rot, Titel in
   Versalien; Infokasten dunkel (#181818, 14px). Ticketknopf 50px, 10px
   Rundung, 14px mit 1px Sperrung — gemessen. */
.event h1 { font-size: var(--t-h1); font-weight: 800; line-height: 1.1; text-transform: uppercase; }
.event-datum { font-size: 1.25rem; font-weight: 700; }
.event-text {
  padding: 0;
  background: none;
  border-radius: 0;
  color: var(--tinte);
  font-size: 0.9375rem;
  line-height: 1.8;
}
.event .knopf-ticket {
  min-height: 50px;
  border-radius: 10px;
  font-size: 0.875rem;
  font-weight: 900;
  letter-spacing: 1px;
  text-transform: uppercase;
}
.infokasten { background: #181818; border: 0; border-radius: 14px; color: #ffffff; }
.infokasten h2 { text-transform: uppercase; font-size: 1rem; }
.infokasten dt { color: #9a9a9a; }
@media (max-width: 767px) { .event h1 { font-size: 1.75rem; } }

/* --- Rechtsseiten: Titel schwarz statt im Akzent (Original: schwarz). ------ */
.rechtstext h1 { color: var(--tinte); }
