/* ============================================================================
   Palacio Granada — Design und Layout
   ----------------------------------------------------------------------------
   Übernahme der bestehenden palacio-granada.de (WordPress mit Elementor).
   Struktur und Klassen kommen vom System (Vorlage baggi-hp), Farben, [restesuche: bewusst, Herkunft]
   Texte, Bilder und Abschnittsfolge vom Original, gemessen in referenz/.

   Schwarzer Grund, weiße Schrift, ein Akzent (#e12753), Überschriften in
   Versalien. Montserrat statt der kommerziellen Nexa Text des Originals
   (Betreiberentscheidung 31.10.).

   Neu im System, aus sundayfunday-hp übernommen (gleicher Elementor- [restesuche: bewusst, Herkunft]
   Baukasten): `.hero--diashow`, `.hero--welle`. Neu hier: `.fuss-zeile--akzent`.
   Alles in docs/README.md.

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

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

/* **Zwei Familien mit klarer Aufgabenteilung**, beide variabel, zusammen
   105 KB.

   Montserrat ist als geometrische Display-Schrift gezeichnet und traegt
   grosse Versalien — Ueberschriften, Knoepfe, Navigation und die fetten
   Etiketten. Inter ist als Oberflaechenschrift gezeichnet und bleibt im
   Absatz ruhig; Montserrat wirkt dort auf Dauer unruhig, weil ihre runden
   Formen und weiten Punzen fuer grosse Grade gemacht sind.

   Die bestehende WordPress-Seite nennt im `body` die Familie „Titillium",
   laedt aber nie eine passende Datei — gerendert wird dort ueberall
   Montserrat, auch im Fliesstext.

   **Beide Dateien werden vorgeladen.** Fliesstext und Hero-Titel stehen
   gleichzeitig ueber der Falz; eine der beiden nachzuladen hiesse, dass
   genau dort umgebrochen wird. Wer die Familien tauscht, muss die
   `<link rel="preload">` in allen Seiten **und** in `tools/build.py`
   mitziehen — sonst laedt die Seite eine Datei vor, die sie nicht nutzt,
   und die, die sie braucht, erst spaet.

   Nicht enthalten sind Emoji; die kommen ohnehin aus der Systemschrift.
   Ebenso wenig der Pfeil U+2192, deshalb zeichnet das CSS ihn selbst
   (siehe `.knopf::after`). Kyrillisch fehlt in beiden Dateien gleichermassen
   — einzelne Eventtexte aus Clubinio fallen dort auf die Systemschrift,
   wie bisher schon. */
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-var.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Montserrat';
  src: url('../fonts/montserrat.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

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

:root {
  /* Flächen. Alle Werte gemessen auf palacio-granada.de (referenz/). */
  /* Seitengrund **reines Schwarz** — anders als die Vorlage (#0d0d0d). Die
     bestehende Seite setzt `rgb(0, 0, 0)` auf Körper und Abschnitte. */
  --nacht:        #000000;
  --box:          #1a1a1a;   /* Karten, Kästen — gemessen an den Eventkarten */
  --box-hell:     #0a0a0a;   /* Bildfläche der Karte, solange der Flyer lädt */
  --flaeche:      #111111;   /* abgesetzter Abschnitt */
  --karte:        #1a1a1a;   /* Eventkarten */
  --kopf:         #111111;   /* Kopfzeile — im Original immer deckend */
  --fuss:         #111111;   /* Fuß */
  --event-grund:  #0f0f0f;   /* Eventseite — gemessen rgb(15, 15, 15) */
  --event-kasten: #181818;   /* Infokasten der Eventseite, Rand #262626 */
  --linie:        #2a2a2a;   /* Trenner und Rahmen */

  /* Schrift: zwei Ebenen mit klarer Aufgabe. Das Original setzt durchgehend
     Nexa Text (Fontfabric, kommerziell). Der Betreiber hat am 31.10. die
     freie Systemschrift gewählt — Montserrat für Überschriften, Menü und
     Knöpfe, Inter für den Fließtext. Siehe assets/fonts/LIZENZEN.md. */
  --schrift-display: 'Montserrat', system-ui, sans-serif;
  --schrift-text:    'Inter', system-ui, -apple-system, sans-serif;

  /* Schrift. */
  --tinte:        #ffffff;
  --tinte-leise:  #cccccc;   /* gemessen: Fließtext in Kästen rgb(204,204,204) */
  --tinte-still:  #9a9a9a;   /* gemessen: rgb(154,154,154) */
  /* Dieselbe Tinte als Zahlentripel. Getönte Flächen — der graue
     Zweitknopf, Eingabefelder — mischen sich daraus mit Alpha, statt
     festes Weiß zu nennen. */
  --tinte-rgb:    255 255 255;

  /* Akzent der Marke. **Gemessen auf der Seite `rgb(225, 39, 83)`**, nicht
     der Clubinio-Wert `#e02151` — Farben kommen vom Original (.auftrag.md).
     Weiß darauf: 4,55:1, knapp über AA. */
  --akzent:       #e12753;
  --akzent-tinte: #ffffff;
  /* Derselbe Akzent als Zahlentripel, für Verläufe und Fokusringe mit Alpha. */
  --akzent-rgb:   225 39 83;

  /* **Derselbe Akzent als Schriftfarbe — und das ist nicht derselbe Wert.**
     Als kleine Schrift auf den Karten (`#1a1a1a`) erreicht `#e12753` nur
     3,83:1, im Fuß (`#111`) 4,15:1 — unter den 4,5:1 für Fließtext. Das
     Original setzt dort die Datumszeile und „Mehr erfahren" in 12–13 px.
     Gleicher Farbton (346°), gleiche Sättigung, nur angehoben: 4,59:1 auf
     der Karte, 4,98:1 im Fuß, 5,54:1 auf Schwarz. Wer eine Fläche färbt,
     nimmt `--akzent`; wer Schrift färbt, `--akzent-text`. */
  --akzent-text:  #e6496e;

  /* **Wellenkante unter dem Hero** (`.hero--welle`). Als Token, weil die
     Farben Marke sind und die Regel System: hinten blau, vorn pink, darunter
     der Seitengrund — gemessen `rgb(6, 192, 255)` und `rgb(225, 39, 83)`. */
  /* Drei Bänder, je für sich nahtlos kachelbar (Anfang und Ende auf derselben
     Höhe, gleiche Steigung) — so können sie seitlich laufen, ohne Naht. */
  --welle-hinten: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 90' preserveAspectRatio='none'%3E%3Cpath fill='%2306c0ff' d='M0 34C360 4 360 4 720 34S1080 64 1440 34V90H0z'/%3E%3C/svg%3E");
  --welle-mitte:  url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 90' preserveAspectRatio='none'%3E%3Cpath fill='%23e12753' d='M0 58C360 36 360 36 720 58S1080 80 1440 58V90H0z'/%3E%3C/svg%3E");
  --welle-vorn:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 90' preserveAspectRatio='none'%3E%3Cpath fill='%23000000' d='M0 78C360 64 360 64 720 78S1080 92 1440 78V90H0z'/%3E%3C/svg%3E");

  /* Erfolgsmeldung der Formulare. Grün, weil der Akzent hier rot ist und
     vom Fehlerfall nicht zu unterscheiden wäre. Weiß darauf 5,13:1. */
  --erfolg:       #2e7d32;

  /* Rundungen. Das Original setzt Knöpfe und Felder kantig, die
     Eventkarten gerundet — gemessen 12px. */
  --r-knopf:      0;
  --r-feld:       0;
  --r-karte:      12px;
  --r-klein:      0;

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

  /* Deckung des dunklen Schleiers über dem Bildabschnitt — projekteigen,
     weil das Foto es ist. Gemessen im Elementor-CSS: 0,53 (Farbe dort
     #161616, hier das Schwarz der Systemregel). */
  --bild-schleier: 53%;

  /* Übergang mit leichtem Überschwingen — nicht linear, nicht träge. */
  --kurve:        cubic-bezier(0.32, 0.72, 0, 1);

  /* Haken und Ausruf für eigene Kästchen und Meldungen. Als data:-Adresse:
     200 Byte sind keinen zweiten Abruf wert. */
  --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");

  /* Maße. **Gemessen:** Seitenkopf und Kontaktspalten stehen bei 1440 px
     Fensterbreite zwischen x = 144 und 1296, innen also 1152 px. Mit 32 px
     Polster je Seite ergibt das 1216. */
  --breite:       1216px;
  --breite-schmal: 760px;
  --gutter:       clamp(1rem, 4vw, 2rem);
  /* Höhe der Kopfzeile. Hero, Bannerversatz, Menü und Ankersprung rechnen
     damit. Gemessen: 100 px auf dem Schreibtisch, 112 px auf dem Telefon
     (Elementor-Polster um das Logo) — hier das Systemmaß 80 px, siehe
     docs/README.md „Vorgelegt". */
  --kopf-hoehe:   80px;

  /* Typografie. Skala des Originals (gemessen bei 1440 / 390 px):
     Hero 85 / 55, Seitentitel 75 / 55, Abschnitt 56 / 35–50,
     Augenbraue 25 / 16–20, Kartentitel 25, Fließtext 16. */
  /* Kurve wie cosmopolar (Betreiber 31.10.): 44px auf dem Telefon, bis 85px. [restesuche: bewusst, Betreiber] */
  --t-hero:   clamp(2.75rem, 9vw, 5.3125rem);
  --welle-hoehe: clamp(50px, 8vw, 110px);
  --t-h1:     clamp(3.4375rem, 7.4vw, 4.6875rem); /* 55 → 57 (768) → 75px */
  /* 56px schon ab 768 (gemessen), 35px auf dem Telefon. */
  --t-h2:     clamp(2.1875rem, 7.3vw, 3.5rem);    /* 35 → 56px */
  /* Zweite H2-Größe für Überschriften im Fließtext: „Die Event Location im
     Herzen der Edelstein Region!" steht im Original auf 49 / 39 px. */
  --t-h2-text: clamp(2.4375rem, 6.4vw, 3.0625rem); /* 39 → 49px, 49 ab 768 */
  --t-h3:     1.5625rem;   /* 25px — Kartentitel, auf allen Breiten gleich */
  --t-text:   1rem;        /* 16px — gemessen */
  --t-klein:  0.875rem;
}

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

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


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

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

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

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

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

body {
  margin: 0;
  background: var(--nacht);
  color: var(--tinte);
  font-family: var(--schrift-text);
  font-size: var(--t-text);
  /* 26px auf 16px — gemessen. Vorher 1,7, was bei 15px 25,5px ergab und
     den Text zugleich kleiner und luftiger machte als im Original. */
  line-height: 1.625;
  -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);
  /* **900, so kräftig wie das Menü** — Betreiber 31.10. (gemessen hatte
     das Original 700). Ohne Sperrung. */
  font-weight: 900;
  /* **Zwei Zeilenhoehen, nach Aufgabe getrennt.**

     Grosse Ueberschriften stehen im Original auf **1,0** — „EVENTS" mit
     72px/72px, „DEMNÄCHST" mit 60px/60px. Das sind ein bis zwei Woerter,
     die als Block wirken sollen.

     Ueberschriften im Fliesstext stehen auf **1,25** (36px/45px), ebenso
     die Kartentitel (20px/25px). Das sind ganze Saetze, und auf 1,0
     kleben ihre Zeilen aneinander.

     Die Vorlage fuhr pauschal 1,08 — zu eng fuer die Saetze und zu weit
     fuer die Schlagworte. Der Grundwert hier ist die kleine Stufe; die
     grossen setzen ihn bei sich auf 1 zurueck. */
  line-height: 1.25;
  text-transform: uppercase;
  /* **Keine Sperrung** — gemessen „normal" an allen Überschriften des
     Originals. Die Vorlage sperrte auf 0,05em (Baggis Marke). [restesuche: bewusst, Herkunft] */
  letter-spacing: 0;
}

/* **Fette Etiketten tragen ebenfalls Montserrat.**

   Die Ueberschriftenregel oben deckt nur h1 bis h4. Alles andere, was fett
   und in Versalien steht, haengt sonst am Fliesstext und faellt auf Inter —
   still, weil es weiter fett bleibt und nur die Formen wechseln.

   **`.infokasten dd` gehoert nicht dazu.** Das sind die Werte — „21.
   November 2026", „Einlass ab 18 Jahren", die Anschrift —, also
   Fliesstext in ganzen Woertern. Die bestehende Seite setzt sie in
   Inter; nur die Beschriftung darueber ist Montserrat. Mit der
   Vorlagenregel standen hier drei Zeilen Anschrift in einer Schrift, die
   fuer kurze Versalien gezeichnet ist.

   Was bleibt: der Termin und der Ort auf der Eventkarte, die Datumszeile
   der Eventseite, die Feldbeschriftung im Infokasten, die FAQ-Frage, der
   Zurueck-Verweis, die Kennzahl der Fehlerseite und der Sprunglink.
   Alles kurze, laute Zeilen — genau das, wofuer Montserrat gezeichnet
   ist. */
.karte-abriss,
.karte-ort,
.event-datum,
.infokasten dt,
.faq summary,
.zurueck,
.fehlerseite .kennzahl,
.sprung {
  font-family: var(--schrift-display);
}

/* Die Werte im Infokasten stehen im Original ebenfalls in der Display-
   Schrift (Plugin-CSS: Montserrat 800, 15px) — anders als in der Vorlage,
   die sie auf die Textschrift zwang. Die Anschriftzeile darunter bleibt
   Textschrift (siehe `.infokasten dd span`). */
.infokasten dd { font-family: var(--schrift-display); }
.infokasten dd span { font-family: var(--schrift-text); }

/* 20px zwischen Absaetzen — gemessen. Die Vorlage fuhr 16px; bei drei
   Absaetzen untereinander summiert sich das sichtbar. */
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);
  color: var(--akzent-tinte);
  font-weight: 700;
}
.sprung:focus { left: 1rem; top: 1rem; }

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

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

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

/* Der Eventabschnitt liegt im Original auf einem Clubfoto mit dunklem
   Schleier (Deckung 0,48). Das Bild steht im CSS und nicht als <img> im
   Markup, weil es Zierde ist und keinen Inhalt traegt. */
.abschnitt-bild {
  position: relative;
  padding-block: clamp(3.5rem, 9vw, 6.25rem);
  /* Wie im Original das zweite Bild der Hero-Diashow (s7) — eine Datei,
     zwei Verwendungen. */
  background: url('../img/hero/hero-2.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));
}

/* **Strich unter einer Überschrift** — neu im System (`.strich`). Das
   Original setzt unter „Next Events" und „Dein neuer Job!" einen Balken in
   der Akzentfarbe (Elementor-Trenner). **Geschlossen, nicht gemessen:**
   Breite und Abstand aus dem Bildschirmfoto (≈300px, 3px, ≈12px Luft) —
   der Trenner ist schmaler als 300px Fläche und fällt durch die Messung. */
.strich::after {
  content: '';
  display: block;
  width: min(300px, 60%);
  height: 3px;
  margin: 0.75rem auto 0;
  background: var(--akzent);
}

/* Abschnittskopf: Ueberschrift plus Unterzeile, zentriert. */
.kopfzeile { text-align: center; margin-bottom: clamp(2rem, 5vw, 3.5rem); }
.kopfzeile h2 { font-size: var(--t-h2); line-height: 1; }
.kopfzeile p {
  margin: 0.75rem 0 0;
  color: var(--tinte-leise);
  text-transform: none;
}
/* Die Unterzeilen unter „Next Events" und „Einblick" stehen im Original in
   der Akzentfarbe, nicht gedaempft. */
.kopfzeile .unterzeile { color: var(--akzent-text); font-weight: 400; }

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

.knopf {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  /* 12px/24px Polster, Zeilenhoehe 20px, **kein Rahmen** — alles gemessen.
     Zusammen ergibt das die 44px Hoehe des Originals; mit dem 1,5px-Rahmen
     der Vorlage waren es 50.

     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);
  color: var(--akzent-tinte);
  font: inherit;
  font-family: var(--schrift-display);
  /* **Nach `font: inherit`, nicht davor.** Die Kurzschreibweise setzt
     `line-height` mit zurueck — davor notiert, erbte der Knopf wieder die
     1,625 des Fliesstexts und war 47 statt 44 Pixel hoch. */
  line-height: 20px;
  /* 900 wie das Menü — Betreiber 31.10. (Original 700). */
  font-weight: 900;
  font-size: var(--t-klein);
  text-transform: uppercase;
  /* Weniger Sperrung als vorher: in der Pille wirkt enge Laufweite ruhiger. */
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: transform 0.25s var(--kurve), box-shadow 0.25s var(--kurve),
              background 0.2s ease, color 0.2s ease;
}
/* **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. */
.knopf::after {
  content: '';
  width: 1em;
  height: 1em;
  flex: none;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h12.2l-4.6-4.6L14 6l6 6-6 6-1.4-1.4 4.6-4.6H5v-2Z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h12.2l-4.6-4.6L14 6l6 6-6 6-1.4-1.4 4.6-4.6H5v-2Z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.knopf-ohne-pfeil::after { content: none; }

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

/* Knopf mit eigenem Symbol davor — dann entfaellt der Pfeil dahinter.
   Beides zusammen waere ein Knopf mit zwei Zeichen fuer eine Handlung. */
.knopf-ohne-pfeil::after { content: none; }

/* **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%;
  /* Gemessen: Polster 18/24px, Radius 10px, Stärke 900. */
  padding-block: 1.125rem;
  border-radius: 10px;
  font-weight: 900;
  letter-spacing: 0.1em;
}

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

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

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

.icon { flex: none; }

/* ---------------------------------------------------------------- Kopf --- */
/* Übernommen aus cosmopolar-hp [restesuche: bewusst, Herkunft] — Betreiber 31.10.:
   Kopf, Menü, Hero und Seitenkopf optisch wie cosmopolar.com. Farben über Palacio-Token. [restesuche: bewusst, Betreiber] */

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

}

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

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

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

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

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

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

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

     `min-height: 100%` ist raus — zusammen mit `flex: 1` zog es die Liste
     zusaetzlich auf und verstaerkte den Effekt. */
  .menu ul {
    flex-direction: column;
    align-items: center;
    /* Betreiber 31.10.: „deutlich weniger Abstand". Vorher 1.5rem Lücke
       plus Polster, 70px von Punkt zu Punkt; jetzt nur das Polster. */
    gap: 0;
  }
  .menu li { justify-content: center; }
  .menu a {
    padding-block: 0.25rem;
    font-size: clamp(1.75rem, 7vw, 2.25rem);
    letter-spacing: -0.01em;
  }
  /* U18 steht auf dem Telefon in der Kopfzeile neben der Marke, nicht im
     aufgeklappten Menue — es braucht dort also keine eigene Regel. */

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

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

/* Übernommen aus cosmopolar-hp [restesuche: bewusst, Herkunft] — Betreiber 31.10.:
   Kopf, Menü, Hero und Seitenkopf optisch wie cosmopolar.com. Farben über Palacio-Token. [restesuche: bewusst, Betreiber] */
.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.

     **Mindesthöhe statt fester Höhe, und höher** (Betreiber 31.10.: „muss
     bisschen höher, weil da mehr Text ist"). Gemessen vorher bei 1280×720:
     Knopf 21px unter der Welle, bei 360×640 Augenbraue unter dem Kopf.
     `min-height` lässt den Hero wachsen, wenn der Text mehr braucht; das
     Polster von `.hero-text` hält Kopf und Welle frei. */
  min-height: clamp(620px, 88svh, 920px);
  margin-top: calc(var(--kopf-hoehe) * -1);
  display: grid;
  place-items: center;
  overflow: hidden;
  background: var(--nacht);
  text-align: center;
}

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

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

.hero-text {
  position: relative;
  z-index: 2;
  padding: calc(var(--kopf-hoehe) + clamp(1.5rem, 4vw, 3rem)) var(--gutter)
           calc(var(--welle-hoehe) + clamp(1.5rem, 4vw, 3rem));
}

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

/* Knapper als die uebrigen Knoepfe. Die bestehende Seite macht es ebenso —
   im Hero steht der Knopf unter einer sehr grossen Ueberschrift und muss
   sie nicht noch einmal ueberbieten. */
.hero-text .knopf {
  padding: 0.7rem 1.4rem;
  font-size: 0.8125rem;
  /* Pille wie cosmopolar — nur im Hero; die übrigen Knöpfe bleiben kantig. [restesuche: bewusst, Betreiber] */
  border-radius: 980px;
}

/* Im Hero ist die Augenbraue auf dem Telefon größer: gemessen 20px
   (im Zweispalter 16px), ab 768 beide 25px. Stand vor dem cosmopolar- [restesuche: bewusst, Betreiber]
   Austausch hier und fiel mit ihm heraus — der Abgleich hat es gemeldet. */
.hero-text .augenbraue { font-size: clamp(1.25rem, 3.3vw, 1.5625rem); }

/* **Diashow** — neu im System (`.hero--diashow`), unverändert aus
   sundayfunday-hp (gleicher Elementor-Baukasten). Nur `--dauer` ist hier [restesuche: bewusst, Herkunft]
   projekteigen: Das Original steht 3 s je Bild (sundayfunday 6 s). [restesuche: bewusst, Herkunft]

   Mehrere Bilder in `.hero-medium`, eines nach dem anderen sichtbar, mit
   langsamem Zoom. **Reines CSS, kein Skript.** Die Bilder liegen
   übereinander; jedes läuft dieselbe Animation über die ganze Runde und ist
   nur in seinem Drittel sichtbar. Die Verzögerung je Bild steht hier — als
   Inline-Style wäre sie unter `style-src 'self'` nicht erlaubt.

   Wer Bewegung abbestellt hat, sieht das erste Bild still. */
.hero--diashow { --bilder: 3; --dauer: 3s; }
.hero--diashow .hero-medium img {
  position: absolute;
  inset: 0;
  opacity: 0;
  animation: hero-dia calc(var(--bilder) * var(--dauer)) linear infinite;
}
.hero--diashow .hero-medium img:nth-child(1) { opacity: 1; }
.hero--diashow .hero-medium img:nth-child(2) { animation-delay: calc(var(--dauer) * 1); }
.hero--diashow .hero-medium img:nth-child(3) { animation-delay: calc(var(--dauer) * 2); }
/* Ein Drittel sichtbar (33,3 %), 0,5 s Überblendung = 5,6 % von 9 s. In
   sundayfunday 2,8 % von 18 s — dieselbe halbe Sekunde. [restesuche: bewusst, Herkunft] */
@keyframes hero-dia {
  0%     { opacity: 0; transform: scale(1); }
  5.6%   { opacity: 1; }
  33.3%  { opacity: 1; }
  38.9%  { opacity: 0; transform: scale(1.15); }
  100%   { opacity: 0; transform: scale(1.15); }
}
@media (prefers-reduced-motion: reduce) {
  .hero--diashow .hero-medium img { animation: none; }
}

/* **Welle am unteren Rand** — neu im System (`.hero--welle`), aus
   sundayfunday-hp. **Geändert:** Das Bild kommt aus dem Token `--welle` [restesuche: bewusst, Herkunft]
   statt fest aus der Regel. Die Farben der Welle sind Marke, die Regel ist
   System — so trägt jedes Projekt seine Farben, ohne die Regel zu kopieren.
   Diese Fassung gehört in die Vorlage (docs/README.md).

   **Bewegt** (Betreiber 31.10., wie das Elementor-Widget des Originals):
   drei Bänder in einem Element, jedes 1440px breit gekachelt, laufen
   seitlich — das hintere langsam nach links, das mittlere gegenläufig, das
   vordere schneller. Nur `background-position`, also keine Layout-Arbeit.
   Wer Bewegung abbestellt hat, sieht sie still. */
.hero--welle::before {
  content: '';
  position: absolute;
  inset: auto 0 -1px;
  z-index: 3;
  height: var(--welle-hoehe);
  background-image: var(--welle-vorn), var(--welle-mitte), var(--welle-hinten);
  background-size: 1440px 100%;
  background-repeat: repeat-x;
  background-position: 0 100%, 0 100%, 0 100%;
  animation: hero-welle 18s linear infinite;
  pointer-events: none;
}
@keyframes hero-welle {
  to { background-position: -2880px 100%, 1440px 100%, -1440px 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .hero--welle::before { animation: none; }
}

/* **Augenbraue** — Kicker über einer Überschrift, in der Akzentfarbe.
   Neu im System als `.augenbraue`, nach ihrer Aufgabe benannt: In der
   Vorlage hieß dasselbe `.hero-augenbraue` (Hero) und `.seitenkopf-marke`
   (Unterseiten), sundayfunday führt `.hero-augenbraue` — drei Namen für [restesuche: bewusst, Herkunft]
   einen Baustein. Hier steht sie im Hero und im Zweispalter. */
.augenbraue {
  margin: 0 0 0.5rem;
  font-family: var(--schrift-display);
  /* Gemessen: 25px auf dem Schreibtisch, 20px auf dem Telefon, 700,
     Versalien, keine Sperrung. Im Zweispalter 25 / 16px. */
  font-size: clamp(1rem, 3.3vw, 1.5625rem);   /* 16 → 25px, 25 ab 768 */
  font-weight: 900;   /* wie das Menü — Betreiber 31.10. */
  line-height: 1;
  text-transform: uppercase;
  /* Akzent als Schrift, nicht als Fläche — siehe `--akzent-text`. */
  color: var(--akzent-text);
}

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

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

/* Logo ueber der Ueberschrift, linksbuendig — 20 % im Original. */
.ueber-logo { width: 20%; min-width: 80px; margin-bottom: 1.25rem; }
@media (max-width: 767px) { .ueber-logo { width: 21%; } }

.ueber-text h2 {
  /* Die kleinere Stufe — siehe `--t-h2-text`. */
  font-size: var(--t-h2-text);
  letter-spacing: normal;
  /* 32px — gemessen. Mit den 20px der Vorlage war der ganze Textblock
     12 Pixel kuerzer, und weil das Raster ihn senkrecht mittig setzt,
     sass er dadurch 20 Pixel tiefer als im Original. Ein Abstand, zwei
     sichtbare Folgen. */
  margin-bottom: 2rem;
}
/* Blocksatz wie im Original. */
/* Kein Blocksatz. Auf schmalen Spalten reisst er Loecher zwischen die
   Woerter — auf dem Telefon bis zu 45 Pixel in einer Zeile. */
.ueber-text p { color: var(--tinte); }   /* gemessen: weiß */
/* Die Augenbraue ist auch ein <p> — ohne diese Zeile gewönne die Regel
   darüber und färbte sie grau. */
.ueber-text .augenbraue { color: var(--akzent-text); }
.ueber-text .knopf-reihe { margin-top: 2rem; }

/* **Auf dem Telefon richtet sich der Abschnitt nach den anderen.**

   Sobald `.ueber` einspaltig steht, sitzt diese Ueberschrift direkt ueber
   „Next Events" und „Get the Vibe" — und war mit 22px sichtbar kleiner als
   deren 28px. Auf der bestehenden Seite sind alle drei gleich gross
   (gemessen: je 35px bei 390px Breite).

   Der Knopf steht aus demselben Grund mittig: In den anderen Abschnitten
   macht das `[data-mitte]`, hier geht es nicht ueber das Markup, weil der
   Knopf auf dem Schreibtisch in der linken Spalte bleiben soll.

   Der Haltepunkt ist derselbe wie der des Rasters oben — zwei Werte, die
   zusammengehoeren. Wer einen aendert, muss den anderen mitziehen. */
@media (max-width: 899px) {
  .ueber-text .knopf-reihe { justify-content: center; }
}

@media (max-width: 899px) {
}


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

/* Drei Spalten, Abstand 20px — gemessen auch noch bei 768px; erst darunter
   eine Spalte. (Die Vorlage schaltete bei 1024px — Baggis Wert.) [restesuche: bewusst, Herkunft] */
.karten {
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (max-width: 767px) {
  .karten { grid-template-columns: 1fr; }
}

/* Systemkarte: Flyer, Text, darunter der Abriss mit Termin und Weg zur
   Veranstaltung. Gemessen am Original: Grund #1a1a1a, Radius 12px, Polster
   24px, kein Schatten. */
.karte {
  display: flex;
  flex-direction: column;
  background: var(--karte);
  border-radius: var(--r-karte);
  /* Damit der Flyer nicht ueber die Kante haengt, wenn `--r-karte` einmal
     nicht null ist, und fuer das Heranfahren des Bildes beim Ueberfahren. */
  overflow: hidden;
  transition: transform 0.3s var(--kurve), background 0.3s var(--kurve);
}
.karte:hover {
  transform: translateY(-6px);
  background: var(--box-hell);
}
.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.5rem;
  /* Gemessen: 24px seitlich und oben. Unten trägt der Abriss. */
  padding: 1.5rem 1.5rem 0.5rem;
  flex: 1;
}

/* Gemessen: 25px, Stärke 900, Versalien, Sperrung −0,25px, Zeile 1,25. */
.karte-titel {
  font-size: var(--t-h3);
  font-weight: 900;
  line-height: 1.25;
  letter-spacing: -0.01em;
}

/* Ortszeile in der Akzentfarbe. Gemessen: 12px, 700, Versalien, 0,6px. */
.karte-ort {
  margin: 0;
  color: var(--akzent-text);
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* **Abriss** — unten an der Karte, links der Termin, rechts der Weg zur
   Veranstaltung (Systemkanon, wie cosmopolar). `margin-top: auto` hält ihn [restesuche: bewusst, Herkunft]
   in allen Karten einer Reihe auf derselben Linie, auch bei verschieden
   langen Titeln. Schrift und Farbe die des Originals: 12–13px, Akzent,
   Versalien. Die Trennlinie ist System; das Original hat keine (vorgelegt). */
.karte-abriss {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin: auto 0 0;
  padding: 1rem 1.5rem 1.25rem;
  border-top: 1px dashed var(--linie);
  font-size: 0.75rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.karte-termin { color: var(--akzent-text); font-size: 0.8125rem; font-weight: 700; white-space: nowrap; }
.karte-infos {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  color: var(--akzent-text);
  font-weight: 900;   /* gemessen */
  transition: gap 0.22s var(--kurve);
}
.karte:hover .karte-infos { gap: 0.6rem; }

/* Monatsueberschrift der Eventliste. */
/* Zentriert und weiss, ohne Trennlinie — wie im Original. */
.monat {
  /* Bis 32px. `--t-h3` (bis 24px) war zu leise fuer eine Zeile, die eine
     ganze Kartengruppe eroeffnet. */
  font-size: clamp(1.5rem, 3.5vw, 2rem);
  color: var(--tinte);
  text-align: center;
  margin: clamp(2.5rem, 5vw, 3.5rem) 0 1.5rem;
}
.monat:first-child { margin-top: 0; }

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

/* ------------------------------------------------------- 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);
  border-radius: var(--r-karte);
}
/* Die Einblick-Strecke zeigt Querformate und laesst sich vergroessern. */
/* An der Klasse, nicht an der Abschnitts-ID. Die ID heisst je Projekt
   anders (`einblick`, `fotos`); haengt die Regel daran, faellt sie beim
   Umbenennen lautlos aus — dann folgt die Folienbreite dem Bild statt der
   Spur und vom Nachbarbild schaut ein Streifen hervor. */
.slider-randlos .slider-band > figure { cursor: zoom-in; }
/* 16:9 — das Format der Dateien im Streifen (1400x788). Die Deckblaetter
   auf /fotos/ tragen 2:3, weil ihre Quellen Hochformate sind: Jede Flaeche
   folgt ihrer eigenen Quelle, statt beide auf ein gemeinsames Mass zu
   zwingen und eine davon zu beschneiden. */
.slider-randlos .slider-band img { aspect-ratio: 16 / 9; }
/* Die Ueber-uns-Strecke zeigt Hochformate. */
#ueber .slider-band img { aspect-ratio: 2 / 3; }

.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; }

/* Die Einblick-Strecke laeuft im Original randlos ueber die volle
   Fensterbreite. Sie steht im Markup trotzdem in der Huelle, damit die
   Ueberschrift darueber ausgerichtet bleibt — der negative Rand holt sie
   wieder heraus. `100vw` statt `100%`, weil die Huelle schmaler ist; der
   Ausgleich nach links ist die halbe Differenz. */
.slider-randlos {
  /* `--sb` ist die Breite der Scrollleiste, gesetzt von page-common.js.
     Ohne den Abzug ist die Flaeche auf dem Schreibtisch genau um diese
     Breite zu breit und die ganze Seite laesst sich quer schieben. */
  width: calc(100vw - var(--sb, 0px));
  margin-left: calc(50% - (100vw - var(--sb, 0px)) / 2);
}
.slider-randlos .slider-rueck { left: 0; }
.slider-randlos .slider-vor { right: 0; }

/* ------------------------------------------------------------ Lightbox -- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: none;
  place-items: center;
  background: rgb(0 0 0 / 92%);
  padding: clamp(1rem, 5vw, 3rem);
}
.lightbox[data-offen='ja'] { display: grid; }

.lb-bild {
  max-width: 100%;
  max-height: 82vh;
  object-fit: contain;
  border-radius: var(--r-karte);
}
.lb-zaehler {
  position: absolute;
  bottom: 1.25rem;
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  color: var(--tinte-still);
  font-size: var(--t-klein);
}

.lb-knopf {
  position: absolute;
  display: grid;
  place-items: center;
  width: 48px; height: 48px;
  border: 0;
  border-radius: 50%;
  background: rgb(255 255 255 / 10%);
  backdrop-filter: blur(8px);
  color: var(--tinte);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.lb-knopf:hover { background: var(--akzent); color: var(--akzent-tinte); }
.lb-zu    { top: 1rem; right: 1rem; }
.lb-rueck { left: 1rem;  top: 50%; transform: translateY(-50%); }
.lb-vor   { right: 1rem; top: 50%; transform: translateY(-50%); }

/* --------------------------------------------------------------- Anfahrt -- */

.anfahrt {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3rem);
}
@media (min-width: 760px) {
  .anfahrt { grid-template-columns: 1fr 1fr; }
}
.anfahrt h2 { font-size: var(--t-h3); margin-bottom: 1rem; }

.zeile {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
  color: var(--tinte-leise);
}
.zeile .icon { color: var(--akzent-text); margin-top: 0.2rem; }
.zeile a:hover { color: var(--akzent-text); }

/* ------------------------------------------------------- Seitenkopf (Unter) -- */
/* Übernommen aus cosmopolar-hp [restesuche: bewusst, Herkunft] — Betreiber 31.10.:
   Kopf, Menü, Hero und Seitenkopf optisch wie cosmopolar.com. Farben über Palacio-Token. [restesuche: bewusst, Betreiber] */

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

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

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

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

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

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

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

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

.kontakt-raster {
  display: grid;
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: start;
}
/* Zweispaltig ab 768px — gemessen (die Vorlage: 900px). */
@media (min-width: 768px) {
  .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;
  }
}

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

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

/* Im Original steht die Ansprache linksbuendig und in normaler Schriftlage,
   nicht als zentrierte Versalueberschrift. */
.abschnitt-oben { padding-block: clamp(2.5rem, 6vw, 4rem) 0; }

/* **Als letzter Abschnitt braucht er sein Polster zurueck.**

   Die Zeile darueber setzt es auf 0 — richtig fuer einen Abschnitt, der
   an den naechsten anschliesst, falsch fuer den letzten vor dem Fuss.
   Auf /kontakt/ stiessen die Social-Symbole direkt an die Fusskante, auf
   /events/ die letzte Kartenreihe.

   **Zielgenau auf diese Klasse, nicht auf `section:last-of-type`.** Mein
   erster Versuch war die allgemeine Regel — sie ist aber spezifischer
   als `.abschnitt` und haette auf /business/, /jobs/, /impressum/ und
   /datenschutz/ das Polster von 112 auf 80 gesenkt. Vier Seiten
   veraendert, um zwei zu reparieren. `.abschnitt-oben` ist die einzige
   Klasse im Stylesheet, die unten auf 0 geht; damit ist der Fall
   vollstaendig abgedeckt.

   80px — gemessen am Original. */
.abschnitt-oben:last-of-type {
  padding-bottom: clamp(3.5rem, 9vw, 5rem);
}
/* Ansprache und Formular gehoeren zusammen. Ohne das hier stossen zwei
   volle Abschnittspolster aneinander und reissen eine Luecke zwischen
   Einleitung und erstem Feld. Die zweite Zeile ueberspringt die
   ausgeblendeten Stellen. */
.abschnitt-oben + .abschnitt,
.abschnitt-oben + [hidden] + .abschnitt { padding-top: clamp(1.75rem, 4vw, 2.75rem); }

.jobs-ansprache {
  font-size: var(--t-h3);
  text-transform: none;
  margin-bottom: 1rem;
}
/* Kanon wie cosmopolar/top10. Gemessen am Original: weiß, 16px, mittig. [restesuche: bewusst, Herkunft] */
.jobs-intro {
  color: var(--tinte);
  max-width: 70ch;
  margin: 0 auto 2.5rem;
  text-align: center;
}

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

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

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

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

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

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

/* **`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;
}
/* Feldbeschriftung. Gemessen auf palacio-granada.de: 16px, Stärke 700,
   Versalien, weiß, keine Sperrung. Gilt auch für die Legende einer
   Gruppe („Bereich", „Datenschutz"). */
.feld > span,
.feld > legend > span {
  font-family: var(--schrift-display);
  font-size: 1rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0;
  color: var(--tinte);
}
.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;
}

/* Mehrfachauswahl der Bereiche auf der Jobseite. Keine Pillen mehr: sieben
   Umrisse mit je einem Kreis darin ergeben eine Wand aus Rahmen. Hier steht
   nur das Kaestchen und der Text daneben, in Spalten gesetzt, damit die
   unterschiedlich langen Bezeichnungen untereinander ausgerichtet bleiben. */
.auswahl {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr));
  gap: 0.9rem 1.5rem;
  margin-top: 0.3rem;
}
.auswahl label {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  color: var(--tinte);   /* gemessen: weiß */
  cursor: pointer;
  transition: color 0.2s ease;
}
.auswahl label:hover,
.auswahl label:has(input:checked) { color: var(--tinte); }

/* 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: 1rem;   /* gemessen 16px, weiß */
  color: var(--tinte);
}
.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) 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;
}

/* Grün, nicht in der Akzentfarbe — siehe `--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(var(--akzent-rgb) / 16%);
  box-shadow: inset 0 0 0 1px var(--akzent);
  color: var(--tinte);
}
.rueckmeldung[data-state='fehler']::before {
  background-color: var(--akzent);
  background-image: var(--ausruf);
}

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

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

/* Inhaltsspalte ~820px und Titel ~40px — Originalwerte. Der Abschnitt
   um die Spalte trägt den eigenen Grund der Eventseite (#0f0f0f). */
.event { max-width: 820px; margin-inline: auto; }
.abschnitt:has(> .event) { background: var(--event-grund); }
.event h1 { font-size: clamp(1.625rem, 4.17vw, 2.5rem); font-weight: 900; }   /* 26 / 32 / 40px; 900 wie das Menü (Original 800) */

.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);
  /* Gemessen: 20px, 700, Versalien — Datum und Uhrzeit beide in Akzent. */
  font-size: 1.25rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0;
  margin-bottom: 0.625rem;
}
.event h1 { margin-bottom: 1.5rem; }
/* Die Beschreibung steht wie im Original frei auf dem Grund, ohne
   Absetzung (gemessen: keine Fläche, kein Polster). */
.event-text a { color: var(--akzent-text); }
.event-text {
  margin-top: 0.5rem;
  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;
  /* Gemessen: #181818, Rand 1px #262626, Radius 14px, Polster 24px. */
  padding: 1.5rem;
  background: var(--event-kasten);
  border: 1px solid #262626;
  border-radius: 14px;
}
.infokasten h2 { font-size: 1rem; font-weight: 900; letter-spacing: 1px; 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-size: 0.9375rem;   /* gemessen 15px, 800 */
  font-weight: 800;
  margin-top: 0.25rem;
}
/* Anschrift unter dem Ort: gemessen 14px, 400, #9a9a9a, keine Versalien. */
.infokasten dd span {
  display: block;
  margin-top: 0.375rem;
  color: var(--tinte-still);
  font-size: var(--t-klein);
  font-weight: 400;
  text-transform: none;
}
.infokasten dt {
  color: var(--tinte-still);
  font-size: 0.6875rem;   /* gemessen 11px, 600, 1px gesperrt */
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1px;
}
.infokasten dd { margin: 0; }

.lounges {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr));
}
.lounge {
  background: var(--karte);
  border-radius: var(--r-karte);
  overflow: hidden;
  box-shadow: var(--schatten);
}
.lounge img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.lounge-text { padding: 1rem 1.125rem 1.25rem; }
.lounge-text h3 { font-size: 1.0625rem; margin-bottom: 0.375rem; }
.lounge-wert { margin: 0; color: var(--tinte-leise); font-size: var(--t-klein); }
.lounge-hinweis {
  grid-column: 1 / -1;
  margin: 0;
  color: var(--tinte-still);
  font-size: var(--t-klein);
}

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

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

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

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

/* Zwei Spalten wie im Original: links Marke, Kurztext und Social-Symbole,
   rechts „Quick Links" rechtsbündig. Darunter die Schlusszeile in der
   Akzentfarbe (`.fuss-zeile--akzent`). Gemessen ab 768px zweispaltig,
   darunter einspaltig und linksbündig. */
.fuss {
  background: var(--fuss);
  padding-top: clamp(2.5rem, 4vw, 2.5rem);
}
.fuss-raster {
  display: grid;
  gap: 2.5rem 1.25rem;
  grid-template-columns: 1fr;
  padding-bottom: 2.5rem;
}
@media (min-width: 768px) {
  .fuss-raster { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.fuss-marke p { max-width: 550px; }

/* Gemessen: 198px breit auf dem Schreibtisch, 131px ab Tablet abwärts. */
.fuss-logo {
  width: clamp(131px, 14vw, 198px);
  margin-bottom: 1.25rem;
}

.fuss p { color: var(--tinte); font-size: clamp(0.875rem, 2.1vw, 1rem); }   /* 14 → 16px, 16 ab 768 */
.fuss a:hover { color: var(--akzent-text); }

/* **„Quick Links" ist `.fuss-recht`** (Systemkanon), nicht der Eigenbau
   `.fuss-links` der Vorlage. Hier als eigene Spalte, rechtsbündig ab 768px
   — wie das Original. Überschrift 27 / 20px in der Akzentfarbe, Verweise
   weiß, 16 / 14px. */
.fuss-recht {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
}
.fuss-recht h2 {
  margin: 0 0 1.25rem;
  font-size: clamp(1.25rem, 3.5vw, 1.6875rem);   /* 20 → 27px, 27 ab 768 */
  font-weight: 900;
  text-transform: uppercase;
  color: var(--akzent-text);
}
.fuss-recht a {
  color: var(--tinte);
  font-size: clamp(0.875rem, 1.2vw, 1rem);
  line-height: 1.5;
}
@media (min-width: 768px) {
  .fuss-recht { align-items: flex-end; text-align: right; }
}

/* **Schlusszeile.** `.fuss-zeile` stammt aus der Vorlage (baggi: Linie und [restesuche: bewusst, Herkunft]
   Seitenverweise). **Neu als Variante `--akzent`:** volle Breite in der
   Akzentfarbe, Firmierung mittig, Versalien — gemessen 30px hoch,
   16 / 14 / 12px. */
.fuss-zeile {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 2.5rem;
  padding-top: 1.75rem;
  border-top: 1px solid rgb(var(--tinte-rgb) / 10%);
}
.fuss-zeile p { margin: 0; }
.fuss-zeile--akzent {
  justify-content: center;
  margin: 0;
  padding: 0.3rem var(--gutter);
  border: 0;
  background: var(--akzent);
}
.fuss-zeile--akzent p {
  color: var(--akzent-tinte);
  font-family: var(--schrift-display);
  font-size: clamp(0.75rem, 1.1vw, 1rem);
  font-weight: 700;
  text-transform: uppercase;
}

/* **Runde Flaechen, nicht freie Symbole.**

   Der Kommentar hier behauptete das Gegenteil und stammte aus der
   Vorlage. An der bestehenden Seite gemessen: ein Kreis von 40px (im
   Fuss 36) mit Weiss bei 10 % Deckung, darin das Symbol in 20px (bzw.
   16) **weiss** — nicht in der Akzentfarbe. */
.fuss-social { display: flex; gap: 0.75rem; margin: 1.25rem 0; }
.fuss-social a {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgb(var(--tinte-rgb) / 10%);
  color: var(--tinte);
  transition: background 0.2s ease;
}
.fuss-social a:hover { background: rgb(var(--tinte-rgb) / 20%); color: var(--tinte); }
.fuss-social svg { width: 20px; height: 20px; }

/* Im Fuß: gemessen 40px-Felder (44 auf dem Telefon), Radius 10 %, keine
   Fläche, Symbol in der Akzentfarbe. */
.fuss .fuss-social a { width: 40px; height: 40px; border-radius: 10%; background: none; color: var(--akzent-text); }
.fuss .fuss-social a:hover { background: rgb(var(--tinte-rgb) / 8%); }
.fuss .fuss-social svg { width: 20px; height: 20px; }

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

/* --------------------------------------------------------- Kontaktformular -- */

/* Überschrift über dem Formular — neu (`.kontakt-titel`). Gemessen: 32px
   auf dem Schreibtisch, 19px auf dem Telefon, 700, Versalien, Akzent. */
.kontakt-titel {
  margin-bottom: 1.5rem;
  font-size: clamp(1.1875rem, 4.17vw, 2rem);   /* 19 → 32px, 32 ab 768 */
  line-height: 1;
  color: var(--akzent-text);
}

/* ------------------------------------------------------------- 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-logo,
html.anim .hero-titel,
html.anim .hero-text .knopf {
  animation: hero-auf 0.9s var(--kurve) both;
}
html.anim .hero-logo        { animation-delay: 0.08s; }
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%; }
/* Absenden: gemessen 19px (13px auf dem Telefon), Stärke 900. */
.form .knopf-voll { font-size: clamp(0.8125rem, 2.5vw, 1.1875rem); font-weight: 900; }

.knopf-reihe[data-mitte] {
  justify-content: center;
  margin-top: clamp(1.75rem, 4vw, 2.75rem);
}
