/* =========================================================================
   Kulturverein Eggenfelden — Stylesheet
   Quelle der Wahrheit fuer die gesamte Optik. Das Plugin kv-content gibt
   nur Auszeichnung mit .kv-*-Klassen aus und enthaelt keine Inline-Styles.

   Werte stammen aus dem Design-Handoff (handoff/README.md), Abschnitte
   „Design Tokens" und „Kernkomponenten".

   ALLE MASSE IN px, NICHT in rem: Bricks setzt html auf 62,5 %, jede
   rem-Angabe waere 10/16 zu klein (Leitfaden §6.1).
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. Tokens
   ------------------------------------------------------------------------- */

:root {
	/* Farben */
	--kv-ink:            #231F23;
	--kv-ink-alt:        #1A1A17;
	--kv-ink-alt-50:     rgba(26, 26, 23, 0.5);
	--kv-ink-72:         rgba(35, 31, 35, 0.72);
	--kv-ink-64:         rgba(35, 31, 35, 0.64);
	--kv-ink-50:         rgba(35, 31, 35, 0.5);
	--kv-ink-12:         rgba(35, 31, 35, 0.12);
	/* Für Rahmen an leeren Feldern: 12 % sind auf weißem Grund kaum zu
	   sehen, 50 % wirken wie ein Fehler. */
	--kv-ink-24:         rgba(35, 31, 35, 0.24);
	--kv-ink-08:         rgba(35, 31, 35, 0.08);
	--kv-soft:           #F7F6F5;
	--kv-footer:         #FCFCFC;
	--kv-weiss:          #FFFFFF;
	--kv-feld:           #EAE9E1;

	--kv-rot:            #8C1D18;
	--kv-rot-dunkel:     #6E1512;
	--kv-rot-hell:       #A5322C;
	--kv-rot-mittel:     #C4544E;
	--kv-creme:          #F4E7C7;
	/* Die beiden weiteren Pastelltoene der Symbolflaechen. Im Entwurf
	   laufen Creme, Aprikose und Rose der Reihe nach durch die Karten. */
	--kv-aprikose:       #FFE1D6;
	--kv-rose:           #F3DDDB;

	/* In oklch, damit weitere Kategoriefarben bei gleicher Helligkeit und
	   Buntheit ueber den Farbton abgeleitet werden koennen:
	   oklch(0.87 0.10 <hue>). Aktuell bewusst nur ein Ton. */
	--kv-tag:            oklch(0.87 0.10 82);

	--kv-licht-86:       rgba(247, 246, 245, 0.86);
	--kv-licht-82:       rgba(247, 246, 245, 0.82);
	--kv-licht-70:       rgba(247, 246, 245, 0.7);
	--kv-licht-68:       rgba(247, 246, 245, 0.68);
	--kv-licht-50:       rgba(247, 246, 245, 0.5);
	--kv-licht-22:       rgba(247, 246, 245, 0.22);
	--kv-licht-16:       rgba(247, 246, 245, 0.16);

	/* Schriftfamilien */
	/* Satoshi trägt beide Rollen — Display und Text. Der Entwurf ist in
	   Satoshi gerendert, seine Größen und Laufweiten sind auf diese
	   Metrik abgestimmt. */
	--kv-display:        'Satoshi', system-ui, sans-serif;
	--kv-text:           'Satoshi', system-ui, sans-serif;
	--kv-mono:           'Fragment Mono', ui-monospace, monospace;
	--kv-label:          'Inconsolata', ui-monospace, monospace;
	/* Die Rechtszeile steht im Entwurf bewusst in Arial. */
	--kv-recht:          Arial, sans-serif;

	/* Breiten */
	--kv-breite:         1512px;   /* Inhaltsbreite */
	--kv-mass:           752px;    /* Textmass einspaltig */
	--kv-mass-breit:     984px;    /* Textmass zweispaltiger Satz */
	--kv-rand:           32px;     /* Seitenrand */

	/* Abstaende */
	--kv-abschnitt:      80px;     /* Abschnittspolster vertikal */
	--kv-hero-top:       140px;
	--kv-bildbox-pad:    48px;
	--kv-karte-pad:      24px;
	--kv-formkarte-pad:  40px;

	/* Radien */
	--kv-r-gross:        20px;     /* Bildboxen, Kacheln, Hero, Formularkarten */
	--kv-r-mittel:       16px;     /* Slider-Bilder, Portraits */
	--kv-r-klein:        12px;     /* Glaskarten, Infoleisten, Icon-Box 44 */
	--kv-r-mini:         8px;      /* Buttons, Tags, Eingabefelder, Icon-Box 32 */
	--kv-r-pfeil:        24px;     /* runde Pfeil-Buttons 44x44 */
	--kv-r-punkt:        2px;      /* quadratische Akzentpunkte */

	/* Schatten */
	--kv-schatten-kopf:  0 12px 24px rgba(213, 207, 224, 0.21);
	--kv-schatten-karte: 0 4px 40px rgba(0, 0, 0, 0.06);
	--kv-schatten-bild:  0 14px 44px rgba(35, 31, 35, 0.22);

	/* Uebergaenge */
	--kv-t-flaeche:      240ms ease;
	--kv-t-schnell:      180ms ease;
	--kv-t-bild:         700ms cubic-bezier(.2, .7, .2, 1);
	--kv-t-panorama:     900ms cubic-bezier(.2, .7, .2, 1);

	/* Hoehe des klebenden Kopfes — speist scroll-margin-top der Anker */
	--kv-kopf-hoehe:     88px;
}

/* -------------------------------------------------------------------------
   2. Basis und Resets
   Alles unter .kv-page, damit nichts ins Backend oder ins Builder-Panel
   durchschlaegt.
   ------------------------------------------------------------------------- */

/* Bricks vererbt global line-height 1.7, Ueberschriften zusaetzlich 1.4.
   Die Entwurfsdatei setzt keine — also `normal`. Ohne das sind alle
   Zeilenabstaende zu gross und die Geometrie stimmt nirgends (§9.2). */
.kv-page {
	font-family: var(--kv-text);
	/* 400, nicht 300. Die Entwurfsdatei setzt am Wurzelelement gar kein
	   font-weight — das ist `normal`. Ein globales 300 hier faerbt jede
	   Beschriftung Light, die ihr Gewicht nicht selbst setzt: Navigation,
	   Knoepfe, Eyebrows, Rubriken, Fusszeilenlinks. Genau das war der
	   sichtbare Unterschied zur Referenz. 300 steht deshalb nur an den
	   Rollen, die es laut Typografietabelle haben. */
	font-weight: 400;
	font-size: 16px;
	line-height: 26px;
	color: var(--kv-ink);
	background: var(--kv-weiss);

	/* Glättung ausdrücklich zurück auf den Browserwert.
	 *
	 * ZWEI URSACHEN, EINE WIRKUNG. Ich hatte hier `antialiased` und
	 * `optimizeLegibility` gesetzt — beides gut gemeint, beides falsch:
	 * der Entwurf setzt weder das eine noch das andere. Und BRICKS setzt
	 * `-webkit-font-smoothing: antialiased` selbst in frontend.min.css.
	 *
	 * Auf macOS schaltet das die Subpixel-Glättung ab; jede Schrift wirkt
	 * dünner, bei identischer Größe, Laufweite und Textbreite. Messbar ist
	 * es nur an der Eigenschaft selbst, sichtbar überall. Aufgefallen an
	 * der Navigation, betroffen war die ganze Seite.
	 *
	 * Merksatz fürs nächste Bricks-Projekt: Bricks stylt nicht nur
	 * generische Tags, es stellt auch die Schriftglättung um. */
	-webkit-font-smoothing: auto;
	-moz-osx-font-smoothing: auto;
	text-rendering: auto;
}

.kv-page :where(h1, h2, h3, h4, h5, h6) {
	font-family: var(--kv-display);
	font-weight: 400;
	line-height: normal;
	margin: 0;
	color: var(--kv-ink);
}

.kv-page :where(p, ul, ol, figure, blockquote) {
	margin: 0;
}

/* Bricks stylt generische Tags per Element-Selektor. Eigene Klassen ohne
   diese Properties erben das (§4.3). */
.kv-page blockquote {
	font-family: inherit;
	font-size: inherit;
	margin: 0;
	padding-left: 0;
	border-left: 0;
}

.kv-page blockquote cite {
	font-family: inherit;
	font-style: normal;
	text-transform: none;
	opacity: 1;
}

.kv-page figcaption {
	text-align: left;
}

.kv-page a {
	color: var(--kv-rot);
	text-decoration: none;
	transition: color var(--kv-t-schnell);
}

.kv-page a:hover {
	color: var(--kv-rot-dunkel);
}

.kv-page img {
	max-width: 100%;
}

/* Sichtbarer Fokus. outline, nicht box-shadow — der wuerde von den
   inset-Konturen der Buttons ueberschrieben. */
.kv-page :where(a, button, input, select, textarea, [tabindex]):focus-visible {
	outline: 2px solid var(--kv-rot);
	outline-offset: 2px;
	border-radius: var(--kv-r-mini);
}

/* Nur fuer Screenreader — Skip-Link und aria-live-Bereiche */
.kv-sr {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* `fixed`, nicht `absolute`: bei `absolute` ist der Bezug der umgebende
   Block, und der beginnt nicht zwangsläufig am Fensterrand. Liegt über
   der Seite ein Meldungsband (bold-meldungen), rutscht der Bezug um die
   Bandhöhe nach unten — aus -100px werden -24px, und der Sprunglink
   schaut sichtbar heraus. Am Fenster gemessen liegt er immer draußen,
   und beim Fokus kommt er auch dann ins Bild, wenn schon gescrollt
   wurde. */
.kv-skip {
	position: fixed;
	top: -100px;
	left: var(--kv-rand);
	z-index: 100;
	padding: 12px 18px;
	background: var(--kv-rot);
	color: var(--kv-soft);
	border-radius: var(--kv-r-mini);
	transition: top var(--kv-t-schnell);
}

.kv-skip:focus {
	top: 12px;
	color: var(--kv-soft);
}

/* -------------------------------------------------------------------------
   3. Layout-Wrapper
   ------------------------------------------------------------------------- */

/* Der Bricks-Container ist eine Flex-Spalte mit align-items:center. Ein
   max-width-Kind darin schrumpft auf Inhaltsbreite — „alles zu eng".
   width:100% ist der Fix, und er ist nicht optional (§4.1). */
.kv-page .kv-inner {
	display: block;
	width: 100%;
	max-width: var(--kv-breite);
	margin-inline: auto;
}

/* Schmalere Reihe unter einem mittigen Kopf — Kontaktkarten im Entwurf. */
.kv-page .kv-inner--1028 { max-width: 1028px; }

/* DER SEITENRAND GEHÖRT AUF DEN ABSCHNITT, NICHT IN DEN WRAPPER.
 *
 * Der Entwurf setzt `padding: 80px 32px` auf die <section> und deckelt den
 * Wrapper darin bei 1512 px ohne eigenes Polster. Die Inhaltsbreite ist
 * damit volle 1512 px.
 *
 * Ich hatte das Polster zuerst in .kv-inner — damit lagen die 32 px INNEN
 * und die Inhaltsbreite war 1448 statt 1512. Bei 1440 px Fenster fällt das
 * gar nicht auf (beide Male 1376), erst ab 1576 px geht die Schere auf.
 * Gemessen mit pruefung/abstaende.js bei 1920 px.
 *
 * Über :has(), damit ein neuer Abschnitt den Rand automatisch bekommt und
 * ihn nicht vergessen kann. Abschnitte mit eigener Bildbühne (Hero, Band,
 * Ortsband) bringen ihr Polster selbst mit und stehen hier nicht drin. */
.kv-page section:has(> .kv-inner),
.kv-page header:has(> .kv-inner),
.kv-page footer:has(> .kv-inner) {
	padding-inline: var(--kv-rand);
}

/* Bricks-Block hat width:100% als Default. Flex-Gruppen, die nur so breit
   sein sollen wie ihr Inhalt, muessen das zuruecksetzen (§2.1). */
.kv-page .kv-auto {
	width: auto;
}

/* Bricks-Section/Container sind Flex-Spalten. Reihen muessen die Richtung
   ausdruecklich drehen. */
.kv-page .kv-reihe {
	flex-direction: row;
}

.kv-page .kv-sec {
	padding-block: var(--kv-abschnitt);
}

.kv-page .kv-sec--soft  { background: var(--kv-soft); }
.kv-page .kv-sec--weiss { background: var(--kv-weiss); }

/* Anker duerfen nicht unter dem klebenden Kopf verschwinden (§4.6). */
.kv-page [id] {
	scroll-margin-top: calc(var(--kv-kopf-hoehe) + 24px);
}

/* -------------------------------------------------------------------------
   4. Typografie-Rollen
   Werte aus der Tabelle „Typografie" des Handoffs.
   ------------------------------------------------------------------------- */

.kv-h1 {
	font-family: var(--kv-display);
	text-wrap: pretty;
	font-size: 64px;
	line-height: 68px;
	letter-spacing: -1px;
	font-weight: 400;
}

.kv-h2 {
	font-family: var(--kv-display);
	font-size: clamp(32px, 4vw, 56px);
	line-height: 1.05;
	letter-spacing: -0.03em;
	font-weight: 400;
}

.kv-h2--bild {
	font-size: 40px;
	line-height: 48px;
	letter-spacing: -0.5px;
}

/* Feste Displaystufen.
 *
 * Die meisten Seiten laufen mit der Grundgroesse (clamp bis 56). Auf den
 * Kinderkunsttagen setzt der Entwurf drei Ueberschriften ausdruecklich
 * anders — 48/52, 56/52 halbfett und 64/68. Als Stufen statt als
 * Einzelfaelle, damit sie im Builder waehlbar sind. */
.kv-page .kv-h2--48 {
	font-size: clamp(32px, 3.4vw, 48px);
	line-height: 1.083;
	letter-spacing: -1px;
}

.kv-page .kv-h2--56 {
	font-size: clamp(34px, 4vw, 56px);
	line-height: 0.93;
	letter-spacing: -0.04em;
	font-weight: 500;
}

.kv-page .kv-h2--64 {
	font-size: clamp(36px, 4.6vw, 64px);
	line-height: 1.0625;
	letter-spacing: -1px;
}

.kv-h2--klein {
	font-size: 32px;
	line-height: 40px;
	letter-spacing: -0.5px;
	text-wrap: pretty;
}

/* 24/32 ohne Laufweitenkorrektur — so steht sie im Entwurf, an jeder
   Stelle. Die Bildkachel setzt in 26 px und behält ihre -0.02em. */
.kv-h3 {
	font-family: var(--kv-display);
	font-size: 24px;
	line-height: 32px;
	letter-spacing: 0;
	font-weight: 400;
}

.kv-lead {
	font-family: var(--kv-text);
	font-size: 18px;
	line-height: 30px;
	letter-spacing: -0.01em;
	font-weight: 300;
	color: var(--kv-ink-72);
}

/* Der Vorspann in 20/32 — der Entwurf setzt ihn so über Kartenreihen,
   wo er die Überschrift traegt statt nur zu ergaenzen. */
.kv-page .kv-lead--20 {
	font-size: 20px;
	line-height: 32px;
}

.kv-lead--gross {
	font-size: 24px;
	line-height: 36px;
}

.kv-text {
	font-family: var(--kv-text);
	font-size: 16px;
	line-height: 26px;
	font-weight: 300;
	color: var(--kv-ink-72);
}

.kv-klein {
	font-size: 13px;
	line-height: 20px;
	font-weight: 300;
	color: var(--kv-ink-64);
}

/* Auf dunklem Grund kehren sich die Textfarben um. */
.kv-auf-dunkel,
.kv-auf-dunkel :where(h1, h2, h3, h4, h5, h6) { color: var(--kv-soft); }
.kv-auf-dunkel :where(.kv-lead, .kv-text)     { color: var(--kv-licht-82); }
.kv-auf-dunkel .kv-klein                      { color: var(--kv-licht-68); }

/* -------------------------------------------------------------------------
   5. Kernkomponenten
   ------------------------------------------------------------------------- */

/* --- 5.1 Button ---------------------------------------------------------
   Grundprinzip aller vier Auspraegungen: Flaeche <-> Kontur. Gefuellt im
   Ruhezustand, auf Hover laeuft die Fuellung heraus und eine 1-px-Kontur
   bleibt stehen.

   Konturen sind bewusst inset-Schatten, keine border: so aendert der
   Wechsel zwischen gefuellt und umrandet die Elementgroesse nicht.

   .kv-page vorangestellt, weil Bricks' .bricks-button-Defaults und der
   generische a:hover sonst durchschlagen (§4.6). */

.kv-page .kv-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	box-sizing: border-box;
	height: 44px;
	padding: 12px 18px;
	border: 0;
	border-radius: var(--kv-r-mini);
	font-family: var(--kv-text);
	font-size: 16px;
	line-height: 20px;
	font-weight: 400;
	white-space: nowrap;
	cursor: pointer;
	text-decoration: none;
	transition: background var(--kv-t-flaeche), color var(--kv-t-flaeche),
	            box-shadow var(--kv-t-flaeche);
}

/* Primaer, auf Hell */
.kv-page .kv-btn--primaer {
	background: var(--kv-rot);
	box-shadow: inset 0 0 0 1px var(--kv-rot);
	color: var(--kv-soft);
}

.kv-page .kv-btn--primaer:hover {
	background: rgba(140, 29, 24, 0);
	color: var(--kv-rot);
}

/* Primaer, auf Foto — die Kontur wird hell, damit sie auf dem Bild traegt */
.kv-page .kv-btn--primaer-foto {
	background: var(--kv-rot);
	box-shadow: inset 0 0 0 1px var(--kv-rot);
	color: var(--kv-soft);
}

.kv-page .kv-btn--primaer-foto:hover {
	background: rgba(140, 29, 24, 0);
	color: var(--kv-soft);
	box-shadow: inset 0 0 0 1px var(--kv-soft);
}

/* Sekundaer, auf Hell */
.kv-page .kv-btn--sekundaer {
	background: var(--kv-ink-08);
	box-shadow: inset 0 0 0 1px rgba(35, 31, 35, 0);
	color: var(--kv-ink);
}

.kv-page .kv-btn--sekundaer:hover {
	background: rgba(35, 31, 35, 0);
	box-shadow: inset 0 0 0 1px rgba(35, 31, 35, 0.4);
	color: var(--kv-ink);
}

/* Glas, auf Foto */
.kv-page .kv-btn--glas {
	background: var(--kv-licht-16);
	backdrop-filter: blur(16px);
	-webkit-backdrop-filter: blur(16px);
	box-shadow: inset 0 0 0 1px rgba(247, 246, 245, 0);
	color: var(--kv-soft);
}

.kv-page .kv-btn--glas:hover {
	background: rgba(247, 246, 245, 0);
	box-shadow: inset 0 0 0 1px rgba(247, 246, 245, 0.85);
	color: var(--kv-soft);
}

/* Das Chevron als CSS-Maske mit currentColor, NICHT als <img>: nur so
   wechselt es beim Flaeche-zu-Kontur-Uebergang die Farbe mit dem Text. */
.kv-chevron {
	flex: 0 0 auto;
	width: 16px;
	height: 16px;
	background: currentColor;
	mask: url('../img/icon-chevron-right.svg') center / contain no-repeat;
	-webkit-mask: url('../img/icon-chevron-right.svg') center / contain no-repeat;
}

/* --- 5.2 Textlink mit Chevron ------------------------------------------- */

.kv-page .kv-link {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-family: var(--kv-text);
	font-size: 16px;
	line-height: 24px;
	font-weight: 400;
	color: var(--kv-ink);
	transition: color var(--kv-t-schnell), gap var(--kv-t-schnell);
}

.kv-page .kv-link:hover {
	color: var(--kv-rot);
	gap: 14px;
}



.kv-page .kv-link--hell        { color: var(--kv-soft); }
.kv-page .kv-link--hell:hover  { color: var(--kv-soft); }

/* In den Bildkacheln ist der Textlink kleiner als in der Atempause —
   15/20 gegen 16/24. Beides steht so in der Referenz. */
.kv-page .kv-kachel .kv-link,
.kv-page .kv-ekarte .kv-link {
	font-size: 15px;
	line-height: 20px;
}

/* --- 5.3 Tag ------------------------------------------------------------ */

.kv-tag {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 4px 8px;
	border-radius: var(--kv-r-mini);
	background: var(--kv-tag);
	font-family: var(--kv-mono);
	font-size: 12px;
	line-height: 16px;
	font-weight: 400;
	letter-spacing: 0.75px;
	text-transform: uppercase;
	color: var(--kv-ink);
}

/* Auf Fotos: Kontur statt Fuellung */
.kv-tag--kontur {
	background: transparent;
	box-shadow: inset 0 0 0 1px var(--kv-licht-50);
	color: var(--kv-soft);
}

/* Kein Punkt: der Entwurf setzt den Konturchip als reine Zeile — er nennt
   den Spielort und soll nicht wie eine zweite Kategorie aussehen. */
.kv-tag--kontur::before { content: none; }

/* --- 5.4 Eyebrow -------------------------------------------------------- */

/* Form A: farbiger Punkt plus Mono-Text — auf Fotos und in Hero-Bereichen */
.kv-eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 12px;
	font-family: var(--kv-mono);
	font-size: 12px;
	line-height: 16px;
	font-weight: 400;
	letter-spacing: 0.75px;
	text-transform: uppercase;
	color: var(--kv-ink);
}

.kv-eyebrow::before {
	content: '';
	flex: 0 0 auto;
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: var(--kv-rot);
}

/* Auf Fotos 10 px. Der Punkt ist NICHT ueberall gleich: im Hero creme,
   im Mitgliedschaftsband tag-gelb. Beides steht so in der Referenz. */
.kv-eyebrow--hell         { color: var(--kv-soft); }
.kv-eyebrow--hell::before { background: var(--kv-tag); width: 10px; height: 10px; }
.kv-eyebrow--creme::before { background: var(--kv-creme); }

/* Form B: Kapsel in hellen Abschnitten */
.kv-eyebrow--kapsel {
	gap: 10px;
	padding: 8px 12px;
	border-radius: var(--kv-r-mini);
	box-shadow: inset 0 0 0 1px var(--kv-ink-08);
}

.kv-eyebrow--kapsel::before {
	width: 10px;
	height: 10px;
	border-radius: var(--kv-r-punkt);
	background: var(--kv-rot);
}

/* --- 5.5 Rubrik-Label --------------------------------------------------- */

/* Inconsolata und Fragment Mono liegen nur in 400 vor — ein geerbtes 300
   liesse den Browser einen Schnitt waehlen, den es nicht gibt. */
.kv-rubrik {
	font-family: var(--kv-label);
	font-size: 12px;
	line-height: 16px;
	font-weight: 400;
	letter-spacing: 1px;
	text-transform: uppercase;
	color: var(--kv-ink-50);
}

/* Nur die Fußzeile nutzt den zweiten Ton. Ich hatte ihn zuerst global
   gesetzt — im Inhalt ist die Rubrik rgba(35,31,35,0.5), nicht
   rgba(26,26,23,0.5). */
.kv-page .kv-fuss .kv-rubrik { color: var(--kv-ink-alt-50); }

.kv-rubrik--hell { color: var(--kv-licht-68); }

/* --- 5.6 Bildkachel mit Overlay ----------------------------------------
   Das Leitmotiv der Seite. */

.kv-kachel {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	min-height: 560px;
	padding: var(--kv-karte-pad);
	border-radius: var(--kv-r-gross);
	overflow: hidden;
	/* Die Farbe UNTER dem Motiv, und sie ist kein Detail: solange das
	   Foto lädt, war die Kachel durchsichtig — helle Schrift auf hellem
	   Abschnitt, unlesbar, und beim Eintreffen des Bildes sprang es um.
	   Der Kunde hat es als „Blitzer" gemeldet (08.09.2026); gemessen war
	   `background-color: rgba(0,0,0,0)` bei Titelfarbe #F7F6F5. Mit der
	   Tinte darunter ist die Kachel vom ersten Bild an dunkel. */
	background-color: var(--kv-ink);
	color: var(--kv-soft);
	transition: box-shadow var(--kv-t-flaeche);
}

.kv-kachel:hover {
	box-shadow: var(--kv-schatten-bild);
	color: var(--kv-soft);
}

/* Das Motiv liegt als <img> in der Kachel, damit der Browser aus dem
   `srcset` die passende Größe wählen kann (ein `background-image` kennt
   kein srcset — daher die unscharfen breiten Karten, Kunde 08.09.2026).
   Absolut und ganz unten im Stapel: darüber die zwei Verlaufsebenen,
   darüber Kopf und Fuß. */
.kv-kachel__motiv {
	position: absolute;
	inset: 0;
	z-index: 0;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: inherit;
}

/* Zwei absolute Verlaufsebenen — ohne die traegt heller Text auf hellen
   Motiven nicht (§9.6). */
.kv-kachel::before,
.kv-kachel::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	pointer-events: none;
}

.kv-kachel::before {
	top: 0;
	height: 160px;
	background: linear-gradient(180deg, rgba(35, 31, 35, 0.5) 0%, rgba(35, 31, 35, 0) 100%);
}

/* Der untere Verlauf trägt Titel, Ort und Preis — deshalb in PIXELN
   verankert, nicht in Prozent.
   -----------------------------------------------------------------------
   Mit `height: 65%` und Prozentstopps wandert die Kurve mit der
   Kachelhöhe, der Text aber nicht: auf dem Telefon (Kachel 420 px) lag
   der Titel bei 51 % der Kurve und bekam nur noch 25 % Deckung —
   gemessen 1,75:1 gegen Weiß. Am Desktop (560 px) waren es 2,8:1, also
   auch dort unter der Grenze.

   Vom unteren Rand gerechnet sitzt der Titel immer an derselben Stelle:
   sein Kasten beginnt 128–140 px über der Kante. Der Entwurf setzt hier
   0,86 auf 65 % — die Abweichung ist bewusst und der Lesbarkeit
   geschuldet (§12.3). */
.kv-kachel::after {
	bottom: 0;
	height: 100%;
	background: linear-gradient(
		0deg,
		rgba(35, 31, 35, 0.9) 0px,
		rgba(35, 31, 35, 0.82) 120px,
		rgba(35, 31, 35, 0.58) 200px,
		rgba(35, 31, 35, 0.22) 280px,
		rgba(35, 31, 35, 0) 360px
	);
}

/* `z-index` OHNE `position: relative` — beide sind Flexkinder der Kachel,
   und bei Flexkindern wirkt z-index auch ohne Positionierung. Das ist
   hier keine Spielerei: die Klickfläche unten hängt sich als absolutes
   Pseudoelement an den Link, und ihr Bezugsrahmen muss die KACHEL sein,
   nicht der Fußbereich. Wäre der Fuß positioniert, würde die Fläche nur
   den Fuß abdecken. */
.kv-kachel__kopf,
.kv-kachel__fuss {
	z-index: 1;
}

.kv-kachel__kopf {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
}

.kv-kachel__fuss {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

/* --- Die ganze Kachel ist klickbar -------------------------------------

   EIN Link je Kachel, nicht drei: der bestehende Textlink bekommt eine
   unsichtbare Fläche über die ganze Kachel. Verschachtelte Links wären
   ungültiges Markup, und ein zweiter Link auf Titel und Bild wäre für
   Screenreader dreimal dasselbe Ziel.

   Der Tastaturfokus bleibt am Textlink, wo er hingehört, und der
   Zeigerpfeil wird über der ganzen Fläche zur Hand.

   Über den Verlaufsebenen (z-index 2), damit der Klick nicht an ihnen
   hängen bleibt — sie sind ohnehin `pointer-events: none`, aber der
   Aufbau bleibt so nachvollziehbar. */
.kv-page .kv-kachel .kv-link::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 2;
	border-radius: var(--kv-r-gross);
}

/* --- 5.7 Glas-Infoleiste ------------------------------------------------ */

.kv-glas {
	display: flex;
	align-items: center;
	gap: 18px;
	padding: 14px 20px;
	border-radius: var(--kv-r-klein);
	background: rgba(35, 31, 35, 0.5);
	backdrop-filter: blur(16px);
	-webkit-backdrop-filter: blur(16px);
	color: var(--kv-soft);
}

.kv-glas__feld {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

/* In der Infoleiste des Kopfbilds stehen Beschriftung und Wert
   NEBENEINANDER auf einer Grundlinie — im Ortsband dagegen untereinander.
   Als Spalte war die Leiste 138 px schmaler als im Entwurf; dadurch passte
   sie neben die Überschrift, statt darunter zu rutschen, und „Django 3000,
   Unplugged" brach auf zwei Zeilen um. */
.kv-hero__leiste .kv-glas__feld {
	flex-direction: row;
	align-items: baseline;
	gap: 8px;
}

.kv-hero__leiste .kv-glas__wert { white-space: nowrap; }

.kv-glas__label {
	font-family: var(--kv-label);
	font-weight: 400;
	font-size: 13px;
	/* Ohne eigene Zeilenhöhe erbt das Label die 26 px des Fließtextes und
	   die Infoleiste wird 16 px höher als im Entwurf. */
	line-height: 18px;
	letter-spacing: 1px;
	text-transform: uppercase;
	color: var(--kv-licht-68);
}

.kv-glas__wert {
	font-family: var(--kv-text);
	font-size: 17px;
	line-height: 24px;
	font-weight: 400;
	color: var(--kv-soft);
}

.kv-glas__strich {
	flex: 0 0 auto;
	width: 1px;
	height: 18px;
	background: var(--kv-licht-22);
}

/* --- 5.8 Auswahlfeld und Eingabefelder ---------------------------------- */

.kv-page .kv-select,
.kv-page .kv-input {
	box-sizing: border-box;
	width: 100%;
	height: 44px;
	padding: 10px 14px;
	border: 0;
	border-radius: var(--kv-r-mini);
	background: var(--kv-feld);
	font-family: var(--kv-text);
	font-size: 16px;
	line-height: 24px;
	font-weight: 300;
	color: var(--kv-ink);
}

.kv-page .kv-select {
	appearance: none;
	-webkit-appearance: none;
	padding-right: 36px;
	background-image: url('../img/icon-chevron-down.svg');
	background-repeat: no-repeat;
	background-position: right 14px center;
	background-size: 11px 6px;
	cursor: pointer;
}

.kv-page textarea.kv-input {
	height: auto;
	min-height: 120px;
	padding: 14px;
	resize: vertical;
}

.kv-page .kv-select:focus-visible,
.kv-page .kv-input:focus-visible {
	outline: 2px solid var(--kv-rot);
	outline-offset: 2px;
}

.kv-page .kv-pflicht {
	color: var(--kv-rot);
}

.kv-page input[type="checkbox"].kv-check {
	width: 18px;
	height: 18px;
	accent-color: var(--kv-rot);
	flex: 0 0 auto;
}

/* --- 5.9 Bild-Slider ----------------------------------------------------
   Endlosband ohne Bedienelemente. Der Satz steht im Markup doppelt, die
   Animation verschiebt um -50% — dadurch springt sie unsichtbar zurueck.
   Die Duplikate tragen aria-hidden. */

.kv-slider {
	overflow: hidden;
}

.kv-track {
	display: flex;
	width: max-content;
	gap: 8px;
	animation: kv-slide 60s linear infinite;
}

/* KEIN Anhalten beim Überfahren (Kunde, 07.09.2026).
 *
 * Vorher stand hier `animation-play-state: paused` — gedacht als
 * Rücksicht: wer ein Motiv genauer ansehen will, hält es an. In der
 * Praxis bleibt das Band beim Weg zur Navigation stehen, ruckelt beim
 * Verlassen wieder an, und niemand versteht, warum. Ein Endlosband ohne
 * Bedienelemente ist Dekoration; Dekoration reagiert nicht auf die Maus.
 *
 * Angehalten wird es weiter für `prefers-reduced-motion` — das ist keine
 * Zierde, sondern eine Ansage des Geräts (siehe unten). */

.kv-track img {
	height: 480px;
	width: 560px;
	object-fit: cover;
	border-radius: var(--kv-r-mittel);
	flex: 0 0 auto;
}

.kv-track img:nth-child(even) {
	width: 380px;
}

@keyframes kv-slide {
	from { transform: translateX(0); }
	to   { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
	.kv-track { animation: none !important; }
}

/* --- 5.10 Raster --------------------------------------------------------
   Fuer Reihen mit fester Elementzahl immer Grid, nicht Flexbox. Flexbox mit
   flex-basis plus max-width erzeugt Waisenzeilen (2+1 statt 3), weil eine
   Mindestbreite gleichzeitig als Hoechstbreite wirkt.

   Spaltenzahl explizit, nicht auto-fit raten lassen — Kunden sehen 5+1
   sofort (Leitfaden §9.5). */

.kv-raster {
	display: grid;
	gap: 48px 16px;
	align-items: start;
}

.kv-raster--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.kv-raster--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.kv-raster--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }

/* --- 5.11 Wolke ---------------------------------------------------------
   Weichgezeichneter Verlauf hinter zentrierten Ueberschriften. */

.kv-wolke-buehne {
	position: relative;
	overflow: hidden;
	background: var(--kv-soft);
}

.kv-wolke-buehne > * {
	position: relative;
	z-index: 1;
}

.kv-wolke-buehne::before {
	content: '';
	position: absolute;
	left: 50%;
	top: 90px;
	transform: translateX(-50%);
	width: 1308px;
	max-width: 108%;
	height: 590px;
	border-radius: 50%;
	background: linear-gradient(180deg, var(--kv-rot-hell) 0%, var(--kv-rot-mittel) 28%, var(--kv-creme) 62%);
	filter: blur(120px);
	z-index: 0;
	pointer-events: none;
}

/* Weissabdeckung oben darueber */
.kv-wolke-buehne::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	top: 0;
	height: 252px;
	background: linear-gradient(180deg, var(--kv-soft) 0%, rgba(247, 246, 245, 0) 100%);
	z-index: 0;
	pointer-events: none;
}

/* --- 5.12 Kuh als Maske ------------------------------------------------- */

.kv-kuh {
	width: 132px;
	height: 110px;
	background: var(--kv-rot);
	mask: url('../img/kuh-solid.svg') center / contain no-repeat;
	-webkit-mask: url('../img/kuh-solid.svg') center / contain no-repeat;
}

/* -------------------------------------------------------------------------
   6. Platzhalter
   Sichtbar und gestrichelt: fehlende Inhalte bleiben Luecken, der Kunde
   entscheidet was fehlt — nicht das Skript.
   ------------------------------------------------------------------------- */

.kv-platzhalter {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 64px;
	padding: 16px;
	border: 1px dashed var(--kv-ink-12);
	border-radius: var(--kv-r-mini);
	background: repeating-linear-gradient(
		135deg,
		rgba(35, 31, 35, 0.03) 0 8px,
		rgba(35, 31, 35, 0) 8px 16px
	);
	font-family: var(--kv-mono);
	font-size: 12px;
	line-height: 16px;
	letter-spacing: 0.75px;
	text-transform: uppercase;
	color: var(--kv-ink-50);
	text-align: center;
}

.kv-platzhalter--inline {
	display: inline-flex;
	min-height: 0;
	padding: 6px 10px;
}

.kv-platzhalter--logo { width: 210px; min-height: 56px; }
.kv-platzhalter--nl   { min-height: 44px; }

/* Portraits: gestreift, wie im Entwurf */
.kv-platzhalter--portrait {
	aspect-ratio: 1 / 1;
	min-height: 0;
	border-radius: var(--kv-r-mittel);
}

/* -------------------------------------------------------------------------
   7. Kopfzeile
   ------------------------------------------------------------------------- */

.kv-page .kv-kopf {
	/* width:100% ist hier nicht Kosmetik: die Bricks-Section ist eine
	   Flex-Spalte mit align-items:center, und ein Block-Kind darin
	   schrumpft auf Inhaltsbreite. Gemessen waren es 1120 statt 1440 px —
	   die weiße Leiste lief nicht über das Fenster (§4.1). */
	width: 100%;
	background: var(--kv-weiss);
	box-shadow: var(--kv-schatten-kopf);
	padding: 20px 0;
}

.kv-page .kv-kopf--klebt {
	position: sticky;
	top: 0;
	z-index: 20;
}

.kv-page .kv-kopf__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 32px;
}

.kv-page .kv-kopf__logo {
	display: block;
	flex: 0 0 auto;
	line-height: 0;
}

.kv-page .kv-kopf__logo img {
	width: 210px;
	max-width: 100%;
	display: block;
}

.kv-page .kv-kopf__rechts {
	display: flex;
	align-items: center;
	gap: 24px;
	justify-content: flex-end;
	min-width: 0;
	/* Bricks-Block hat width:100% als Default — ohne das Zuruecksetzen
	   sprengt die Gruppe die Reihe (§2.1). */
	width: auto;
}

.kv-page .kv-nav {
	display: flex;
	align-items: center;
	gap: 24px;
}

.kv-page .kv-nav__link {
	font-family: var(--kv-text);
	font-size: 16px;
	line-height: 24px;
	letter-spacing: -0.005em;
	font-weight: 400;
	color: var(--kv-ink);
	white-space: nowrap;
	transition: color var(--kv-t-schnell);
}

.kv-page .kv-nav__link:hover {
	color: var(--kv-rot);
}

/* Der aktive Zustand fuer die laufende Seite — im Entwurf offen
   (Handoff, offener Punkt 7). Unterstrichen statt nur eingefaerbt, damit
   er nicht allein an der Farbe haengt. */
.kv-page .kv-nav__link--aktiv {
	color: var(--kv-rot);
	text-decoration: underline;
	text-underline-offset: 6px;
	text-decoration-thickness: 1px;
}

/* --- Der Umschalter: eine Treppe -------------------------------------
   Drei Linien absteigender Länge, rechtsbündig im 44-px-Feld, die
   mittlere in Brand Rot. Beim Überfahren kehrt sich die Treppe um: die
   Längen tauschen, das Rot wandert auf die längste Linie.

   Ohne Fläche und ohne Rahmen (Spezifikation Mobilnavigation) — die
   44 × 44 px sind Trefferfläche, nicht Button.

   Sichtbar erst unterhalb der Schwelle UND nur mit JavaScript: ohne
   Skript bleibt die Navigation aufgeklappt im Fluss, dann wäre ein
   Button, der nichts tut, eine Falle.
   --------------------------------------------------------------------- */
.kv-page .kv-burger {
	display: none;
	flex-direction: column;
	align-items: flex-end;
	justify-content: center;
	gap: 5px;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
}

.kv-page .kv-burger span {
	display: block;
	height: 2px;
	background: var(--kv-ink);
	transition:
		width 260ms cubic-bezier(0.2, 0.7, 0.2, 1),
		background 260ms ease,
		transform 260ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

.kv-page .kv-burger span:nth-child(1) { width: 26px; }
.kv-page .kv-burger span:nth-child(2) { width: 19px; background: var(--kv-rot); }
.kv-page .kv-burger span:nth-child(3) { width: 12px; }

/* NUR MIT ECHTEM ZEIGEGERÄT.
 *
 * Auf dem Telefon gibt es kein Überfahren — Safari täuscht `:hover` beim
 * Antippen vor und LÄSST DEN ZUSTAND STEHEN. Nach einem Tipp auf den
 * Umschalter blieb die Treppe also umgekehrt (Rot auf der längsten
 * Linie), und beim nächsten Öffnen sah das Symbol anders aus als vorher.
 * Genau das fühlt sich „komisch" an, ohne dass man den Finger darauf
 * legen kann.
 *
 * `@media (hover: hover)` fragt das Gerät, nicht die Breite. */
@media (hover: hover) {
	.kv-page .kv-burger:hover span:nth-child(1) { width: 12px; }
	.kv-page .kv-burger:hover span:nth-child(2) { width: 26px; background: var(--kv-rot); }
	.kv-page .kv-burger:hover span:nth-child(3) { width: 19px; }
}

/* Rückmeldung für den FINGER: das Antippen drückt die Treppe kurz
   zusammen. `:active` bleibt nicht stehen. */
.kv-page .kv-burger:active span { transform: scaleX(0.86); }

/* Kein grauer iOS-Kasten über dem Symbol; die Rückmeldung machen wir
   selbst. Und `touch-action: manipulation` nimmt die Wartezeit auf einen
   möglichen Doppeltipp. */
.kv-page .kv-burger,
.kv-page .kv-drawer__zu,
.kv-page .kv-drawer__link,
.kv-page .kv-drawer .kv-btn {
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
}

/* --- Das mobile Menü: ein Vollbild ------------------------------------
   `position: fixed; inset: 0` über allem, weißer Grund, eigener Scroll.
   Drei Zonen: Kopf mit Logo und Schließen, Punkte mit Button, Fuß mit
   Anschrift.
   --------------------------------------------------------------------- */
.kv-page .kv-drawer {
	position: fixed;
	inset: 0;
	z-index: 30;
	display: flex;
	flex-direction: column;
	background: var(--kv-weiss);
	overflow-y: auto;
	overscroll-behavior: contain;
	/* DAS VOLLBILD ROLLT AUF — ES BLENDET NICHT EIN.
	 *
	 * Dritter Versuch, und die beiden vorherigen sind die Begründung:
	 *
	 * 1. `opacity` + `translateY(-8px)` über dem ganzen Vollbild: ein
	 *    weißes Blatt, das sich als Ganzes verschiebt — ein Ruck.
	 * 2. Grund aufblenden, Zonen gestaffelt heben: solange der Grund
	 *    halbdurchsichtig ist, SIEHT MAN DIE SEITE DAHINTER. Für 240 ms
	 *    stehen zwei Bilder übereinander, dazu drei Teile, die sich zu
	 *    verschiedenen Zeiten bewegen. Es wirkt unsauber, ohne dass man
	 *    sagen kann, woran es liegt — der Kunde: „kommt immer noch
	 *    irgendwie komisch rein, fühlt sich nicht gut an."
	 *
	 * Jetzt FÄHRT das Blatt herein: deckend von der ersten Bildzeile an,
	 * von oben nach unten, eine einzige Bewegung. Man sieht nie zwei
	 * Bilder übereinander, und die Bewegung kommt aus der Kopfzeile —
	 * dort, wo der Finger war.
	 *
	 * `transform` ist dabei die einzige Eigenschaft, die sich ändert. Das
	 * ist kein Stilentscheid, sondern eine Rechenfrage: Verschiebung und
	 * Deckkraft kann der Compositor allein, alles andere (auch
	 * `clip-path`, der Versuch davor) verlangt in jedem Bild ein neues
	 * Rastern der ganzen Fläche — auf dem Telefon fallen dabei Bilder aus,
	 * und genau das fühlt sich „nicht gut" an. `will-change` sagt es dem
	 * Browser vorher, damit er die Ebene EINMAL anlegt und nicht mitten
	 * in der Bewegung. */
	/* 320 ms mit der Kurve, die iOS für seine eigenen Blätter benutzt:
	   der Anfang ist zügig, das Ende läuft lang aus. Die Kurve davor
	   (0.22, 0.61, 0.36, 1) hatte fast die ganze Strecke in den ersten
	   100 ms — technisch dieselbe Bewegung, gefühlt ein Schnappen. */
	animation: kv-drawer-auf 320ms cubic-bezier(0.32, 0.72, 0, 1);
	will-change: transform;
	backface-visibility: hidden;
}

.kv-page .kv-drawer[hidden] { display: none; }

@keyframes kv-drawer-auf {
	from { transform: translateY(-100%); }
	to   { transform: translateY(0); }
}

/* Und wieder weg, dieselbe Bewegung rückwärts und kürzer: Schließen darf
 * schneller sein als Öffnen, sonst wartet man auf etwas, das man schon
 * hinter sich hat. `kv.js` setzt die Klasse, wartet 220 ms und versteckt
 * dann — die Dauer steht an BEIDEN Stellen. */
.kv-page .kv-drawer--geht {
	animation: kv-drawer-zu 220ms cubic-bezier(0.4, 0, 1, 1) both;
	/* Ein Blatt, das gerade verschwindet, darf keine Tipper mehr
	   abfangen: 180 ms sind kurz, ein Fingertipp ist kürzer. */
	pointer-events: none;
}

@keyframes kv-drawer-zu {
	from { transform: translateY(0); }
	to   { transform: translateY(-100%); }
}

@media (prefers-reduced-motion: reduce) {
	.kv-page .kv-drawer,
	.kv-page .kv-drawer--geht { animation: none; }
}

/* Polster 20/32 — feste Werte aus der Spezifikation, NICHT `--kv-rand`:
   das ist auf schmalen Geräten 20 px, und der Entwurf setzt hier 32.
   Nachgemessen an `mobilnav-offen.png`: Trennlinien und Button beginnen
   bei x = 32. */
.kv-page .kv-drawer__kopf {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	padding: 20px 32px;
	border-bottom: 1px solid var(--kv-ink-12);
}

.kv-page .kv-drawer__logo { display: block; line-height: 0; }
.kv-page .kv-drawer__logo img { width: 150px; max-width: 100%; display: block; }

/* Schließen: zwei gedrehte Linien, dieselbe Trefferfläche wie der
   Umschalter. */
.kv-page .kv-drawer__zu {
	position: relative;
	flex: 0 0 auto;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
}

.kv-page .kv-drawer__zu span {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 22px;
	height: 2px;
	margin-left: -11px;
	background: var(--kv-ink);
	transition: background 180ms ease;
}

.kv-page .kv-drawer__zu span:nth-child(1) { transform: rotate(45deg); }
.kv-page .kv-drawer__zu span:nth-child(2) { transform: rotate(-45deg); }
@media (hover: hover) {
	.kv-page .kv-drawer__zu:hover span { background: var(--kv-rot); }
}

.kv-page .kv-drawer__zu:active span { background: var(--kv-rot); }

.kv-page .kv-drawer__mitte {
	flex: 1 0 auto;
	padding: 28px 32px 32px;
}

.kv-page .kv-drawer__nav {
	display: flex;
	flex-direction: column;
}

.kv-page .kv-drawer__link {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	/* 14 px oben und unten — der Wert der SPEZIFIKATION.
	   Vorher standen hier 28, abgemessen am Rendering des Entwurfs
	   (`mobilnav-offen.png`, Trennlinien bei 217, 306, 395, 484, 573,
	   662 = 89 px Zeilenhöhe). Der Kunde hat am 07.09.2026 anders
	   entschieden: „Die Navigation sollte auf einen Blick erkennbar
	   sein, bitte die einzelnen Rows weniger hoch." Mit 14 sind es
	   61 px, und alle sechs Punkte samt Button stehen ohne Scrollen da.
	   Eine Kundenentscheidung schlägt die Bildmessung. */
	min-height: 56px;
	padding: 14px 0;
	border-bottom: 1px solid var(--kv-ink-12);
	font-family: var(--kv-display);
	font-size: 26px;
	line-height: 32px;
	font-weight: 400;
	letter-spacing: -0.02em;
	color: var(--kv-ink);
	transition: color var(--kv-t-schnell);
}

@media (hover: hover) {
	.kv-page .kv-drawer__link:hover { color: var(--kv-rot); }
}

/* Der gedrückte Punkt bekommt Fläche, nicht nur Farbe: auf dem Telefon
   liegt der Finger auf der Schrift und verdeckt sie. Die Fläche reicht
   über das Polster der Zeile hinaus, damit man den Treffer auch am Rand
   sieht. */
.kv-page .kv-drawer__link:active {
	color: var(--kv-rot);
	background: var(--kv-soft);
	box-shadow: 0 0 0 8px var(--kv-soft);
	border-radius: 2px;
}

/* Der Chevron steht hier im CSS und nicht im Markup: die Punkte kommen
   aus einem WordPress-Menü, und dessen Ausgabe soll ein Menü bleiben. */
.kv-page .kv-drawer__link::after {
	content: '';
	flex: 0 0 auto;
	width: 14px;
	height: 14px;
	background: currentColor;
	mask: url('../img/icon-chevron-right.svg') center / contain no-repeat;
	-webkit-mask: url('../img/icon-chevron-right.svg') center / contain no-repeat;
}

.kv-page .kv-drawer__link--aktiv { color: var(--kv-rot); }

.kv-page .kv-drawer__mitte .kv-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 56px;
	/* 24 — der Wert der Spezifikation. Die 28, die hier standen, waren
	   an der Fußlinie des Entwurfsbildes ausgerichtet (775 gegen 779);
	   mit flacheren Zeilen bezieht sich diese Rechnung auf nichts mehr. */
	margin-top: 24px;
	border-radius: var(--kv-r-mini);
	font-size: 18px;
}

.kv-page .kv-drawer__fuss {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 8px;
	padding: 24px 32px 32px;
	border-top: 1px solid var(--kv-ink-12);
}

.kv-page .kv-drawer__adresse {
	display: flex;
	flex-direction: column;
	font-style: normal;
	font-size: 15px;
	line-height: 22px;
	font-weight: 300;
	color: var(--kv-ink);
}

/* „Sponsoring": der Abstand zum Chevron wächst beim Überfahren. */
.kv-page .kv-drawer__fuss .kv-link { gap: 4px; margin-top: 8px; }
@media (hover: hover) {
	.kv-page .kv-drawer__fuss .kv-link:hover { gap: 12px; }
}

/* -------------------------------------------------------------------------
   8. Fusszeile
   ------------------------------------------------------------------------- */

.kv-page .kv-fuss {
	/* Siehe .kv-kopf — dasselbe Flex-Kind-Problem (§4.1). */
	width: 100%;
	background: var(--kv-footer);
	padding: var(--kv-abschnitt) 0;
	color: var(--kv-ink-alt);
}

.kv-page .kv-fuss__oben {
	display: grid;
	grid-template-columns: 1.6fr 1fr 1fr 1.2fr;
	gap: 48px;
	align-items: start;
}

.kv-page .kv-fuss__marke {
	display: flex;
	flex-direction: column;
	gap: 28px;
}

.kv-page .kv-fuss__logo img {
	width: 240px;
	max-width: 100%;
	display: block;
}

/* Der Hinweis unter dem Newsletter-Feld steht im Entwurf in derselben
   Arial-Kleinschrift wie die Rechtszeile, nicht im Fließtext. */
.kv-page .kv-fuss__nl .kv-klein {
	font-family: var(--kv-recht);
	font-size: 12px;
	line-height: 16px;
	font-weight: 400;
	color: var(--kv-ink-alt-50);
}

.kv-page .kv-fuss__nl,
.kv-page .kv-fuss__social,
.kv-page .kv-fuss__spalte {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.kv-page .kv-fuss__socialreihe {
	display: flex;
	gap: 8px;
}

/* Ruhezustand Kontur, auf Hover mit Rot gefuellt */
.kv-page .kv-social {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	border-radius: var(--kv-r-mini);
	box-shadow: inset 0 0 0 1px var(--kv-ink-12);
	color: var(--kv-ink);
	transition: background var(--kv-t-flaeche), color var(--kv-t-flaeche),
	            box-shadow var(--kv-t-flaeche);
}

.kv-page .kv-social:hover {
	background: var(--kv-rot);
	box-shadow: inset 0 0 0 1px var(--kv-rot);
	color: var(--kv-soft);
}

.kv-social__icon {
	width: 20px;
	height: 20px;
	background: currentColor;
	mask-position: center;
	mask-repeat: no-repeat;
	mask-size: contain;
	-webkit-mask-position: center;
	-webkit-mask-repeat: no-repeat;
	-webkit-mask-size: contain;
}

.kv-social--facebook  .kv-social__icon {
	mask-image: url('../img/icon-facebook.svg');
	-webkit-mask-image: url('../img/icon-facebook.svg');
}
.kv-social--instagram .kv-social__icon {
	mask-image: url('../img/icon-instagram.svg');
	-webkit-mask-image: url('../img/icon-instagram.svg');
}
.kv-social--whatsapp  .kv-social__icon {
	mask-image: url('../img/icon-whatsapp.svg');
	-webkit-mask-image: url('../img/icon-whatsapp.svg');
}

.kv-page .kv-fuss__links {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.kv-page .kv-fuss__link {
	font-size: 16px;
	line-height: 24px;
	color: var(--kv-ink-alt);
}

/* Die Kontaktadresse ist ein Link und im Entwurf rot — die
   Navigationslinks daneben sind es nicht. */
.kv-page .kv-fuss__adresse a {
	font-size: 16px;
	line-height: 24px;
	color: var(--kv-rot);
}

.kv-page .kv-fuss__link:hover {
	color: var(--kv-rot);
}

.kv-page .kv-fuss__adresse a:hover {
	color: var(--kv-rot-dunkel);
}

.kv-page .kv-fuss__adresse {
	display: flex;
	flex-direction: column;
	gap: 4px;
	font-style: normal;
	font-size: 16px;
	line-height: 24px;
	color: var(--kv-ink-alt);
}

.kv-page .kv-fuss__linie {
	height: 1px;
	background: var(--kv-ink-12);
	margin-block: 48px 24px;
}

.kv-page .kv-fuss__unten {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: 16px 32px;
	/* Arial 12/16 — so steht es in der Typografietabelle („Rechtszeile")
	   und so rendert die Referenz. */
	font-family: var(--kv-recht);
	font-size: 12px;
	line-height: 16px;
	color: var(--kv-ink-alt-50);
}

.kv-page .kv-fuss__recht {
	display: flex;
	flex-wrap: wrap;
	gap: 8px 20px;
}

.kv-page .kv-fuss__rechtlink,
.kv-page .kv-fuss__credit {
	font-family: var(--kv-recht);
	font-size: 12px;
	line-height: 16px;
	color: var(--kv-ink-alt-50);
}

.kv-page .kv-fuss__rechtlink:hover {
	color: var(--kv-rot);
}

.kv-page .kv-fuss__credit a {
	color: var(--kv-rot);
}

/* -------------------------------------------------------------------------
   9. Sektionen über die volle Fensterbreite
   Die Bricks-Section ist eine Flex-Spalte mit align-items:center. Jedes
   Element-Wurzel-Kind darin schrumpft auf Inhaltsbreite, wenn es nicht
   ausdrücklich 100 % nimmt. Die Breite steuert innen .kv-inner.
   ------------------------------------------------------------------------- */

.kv-page .brxe-section > .kv-sec-voll,
.kv-page .kv-sec > [class*="kv-"] {
	width: 100%;
}

/* -------------------------------------------------------------------------
   10. Hero — naechste Veranstaltung
   ------------------------------------------------------------------------- */

.kv-page .kv-hero {
	width: 100%;
	padding: var(--kv-rand);
}

.kv-hero__buehne {
	position: relative;
	display: flex;
	align-items: flex-end;
	min-height: 720px;
	border-radius: var(--kv-r-gross);
	overflow: hidden;
	isolation: isolate;
}

.kv-hero__motiv {
	position: absolute;
	inset: 0;
	z-index: 0;
}

.kv-hero__motiv img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* Bildausschnitt steuern statt Bild tauschen: bei hohen Motiven haelt
   „unten" die Personen im Bild, beschnitten wird oben (§9.5). */
.kv-hero__buehne--mittig .kv-hero__motiv img { object-position: center center; }
.kv-hero__buehne--oben   .kv-hero__motiv img { object-position: center top; }
.kv-hero__buehne--unten  .kv-hero__motiv img { object-position: center bottom; }

/* Drei Ebenen — abdunkeln, WO Text liegt, nicht überall.
   -----------------------------------------------------------------------
   Vorher lag über dem ganzen Motiv eine flache Tönung von 30 %, dazu ein
   Verlauf von links, der auf halber Breite noch 66 % hielt. Zusammen war
   das Foto durchgehend dunkel — auch oben rechts, wo nie ein Buchstabe
   steht. Gemessen lag der Kontrast bei 7 bis 15 zu 1, gebraucht werden
   4,5: es war nicht knapp zu stark, sondern um ein Mehrfaches.

   Der Inhalt sitzt unten (Text links, Infoleiste rechts). Also trägt der
   Verlauf VON UNTEN die Hauptlast über die volle Breite, der Verlauf von
   links gibt der Überschrift zusätzlich Grund und endet früh, und von der
   flachen Tönung bleibt ein Hauch gegen ausgewaschene Motive.

   Die obere Bildhälfte bleibt damit weitgehend das Foto. */
.kv-hero__ton,
.kv-hero__links,
.kv-hero__unten {
	position: absolute;
	z-index: 1;
	pointer-events: none;
}

/* --kv-deckung skaliert alle drei Ebenen gemeinsam. 1 = Vorgabe.
   Gesetzt wird sie vom Element als einzige Inline-Eigenschaft — ein Wert,
   der zum Inhalt gehört, gehört nicht ins Stylesheet. */
.kv-hero__buehne { --kv-deckung: 1; }

.kv-hero__ton {
	inset: 0;
	background: rgb(35 31 35 / calc(0.1 * var(--kv-deckung)));
}

/* Zusätzlicher Grund unter der Überschrift, aus der Ecke heraus.
   Kein Verlauf über die ganze Höhe: der hätte auch oben links abgedunkelt,
   wo nur Bild ist. */
.kv-hero__links {
	inset: 0;
	background: radial-gradient(
		115% 95% at 2% 100%,
		rgb(35 31 35 / calc(0.34 * var(--kv-deckung))) 0%,
		rgb(35 31 35 / calc(0.18 * var(--kv-deckung))) 45%,
		rgb(35 31 35 / 0) 78%
	);
}

/* Die Hauptlast: ein Keil — links hoch, nach rechts auslaufend.
   -----------------------------------------------------------------------
   Zwei Anläufe waren nötig, und der Umweg ist die Erklärung wert.

   Ein GEKIPPTER Verlauf (18°) sieht auf dem Bild genau richtig aus, hält
   die Schrift aber nicht: die Überschrift ist bis zu 700 px breit, und
   ihre obere rechte Ecke landet bei 1440 px Fenster im hellen Teil —
   direkt über dem Kronleuchter. Gemessen 2,1:1 statt 4,5.

   Deshalb steht hier die Kombination, die beides kann: ein Verlauf VON
   UNTEN, der die Schrift trägt, und eine MASKE, die ihn nach rechts hin
   ausblendet. Ergebnis ist derselbe Keil — links reicht die Abdunklung
   hoch, rechts bleibt nur ein Streifen am Rand für die Infoleiste —, aber
   über der ganzen Breite der Überschrift liegt die volle Stärke.

   Die Stopps stehen in PIXELN, nicht in Prozent: in Prozent wandert der
   Verlauf mit der Bühnenhöhe, der Text aber nicht. Bei 1024 px ist die
   Bühne 100 px kürzer und der Textblock höher — die Überschrift lag
   plötzlich im hellen Teil (2,5:1). Vom unteren Rand gerechnet liegt sie
   immer an derselben Stelle der Kurve. */
.kv-hero__unten {
	inset: 0;
	height: auto;
	background: linear-gradient(
		0deg,
		rgb(35 31 35 / calc(0.88 * var(--kv-deckung))) 0px,
		rgb(35 31 35 / calc(0.8 * var(--kv-deckung))) 150px,
		rgb(35 31 35 / calc(0.68 * var(--kv-deckung))) 320px,
		rgb(35 31 35 / calc(0.36 * var(--kv-deckung))) 470px,
		rgb(35 31 35 / 0) 620px
	);
	-webkit-mask-image: linear-gradient(
		to right,
		#000 0%,
		#000 55%,
		rgb(0 0 0 / 0.55) 78%,
		rgb(0 0 0 / 0.42) 100%
	);
	mask-image: linear-gradient(
		to right,
		#000 0%,
		#000 55%,
		rgb(0 0 0 / 0.55) 78%,
		rgb(0 0 0 / 0.42) 100%
	);
}

/* Der Inhalt sitzt in einem eigenen Container, damit Text und Infoleiste
   auf der Achse der Abschnitte darunter bleiben — obwohl das Bild ueber
   die volle Breite laeuft.

   ZUR SEITLICHEN LUFT (Kundenwunsch 07.09.2026): der Entwurf setzt hier
   48 px Polster, dadurch beginnt die Überschrift 48 px INNERHALB der
   Achse — auf breiten Bildschirmen sichtbar gegen Logo, Navigation und
   die Abschnitte darunter versetzt. Gemessen gegen die Referenzdatei:
   dort ist es genauso (Titel bei 252 px auf 1920). Es ist also eine
   bewusste Abweichung vom Handoff.

   Die Rechnung hält beides zusammen: der Inhalt läuft auf der Achse,
   solange das Bild breiter ist als die Achse — und behält sonst 48 px
   Abstand zur Bildkante. `100vw - 2*32px` ist die Bildbreite,
   `--kv-breite` die Achse; ist die Differenz größer als 2 × 48 px, wird
   das Polster 0. Dazwischen läuft es weich aus, es springt nichts. */
.kv-page .kv-hero__inhalt {
	--kv-hero-vorsprung: max(0px, calc((100vw - 2 * var(--kv-rand) - var(--kv-breite)) / 2));
	position: relative;
	z-index: 2;
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 48px;
	flex-wrap: wrap;
	padding: var(--kv-bildbox-pad);
	padding-inline: max(0px, calc(var(--kv-bildbox-pad) - var(--kv-hero-vorsprung)));
}

/* flex-Basis statt starrer Breite: mit `max-width: 752px` allein nahm die
   Textspalte immer volle 752 px, fuer die Infoleiste blieben 480 statt der
   noetigen 540 — sie brach unter den Text statt daneben zu stehen. Jetzt
   schrumpft der Text, bis es wirklich zu eng wird. */
.kv-hero__text {
	display: flex;
	flex-direction: column;
	gap: 24px;
	flex: 1 1 480px;
	max-width: 760px;
}

/* Mobil ist das Kopfbild eine Kachel; die Meldung steht darunter auf der
   Abschnittsfläche. Abstand wie zwischen Kachel und folgendem Inhalt. */
.kv-hero__meldung {
	margin-top: 20px;
}

/* Steht eine Meldung im Kopfbild (bold-meldungen), sind es fünf Teile
   statt drei: Chip, Überschrift, Lead, Meldungsblock, Buttons. Bei 24px
   Abstand zwischen allen wirkt der Block wie ein weiterer Absatz — er
   soll aber zur Überschrift gehören. Deshalb rückt er näher an den Lead
   und die Buttons behalten ihren Abstand. */
.kv-hero__buehne--meldung .kv-hero__text {
	gap: 20px;
}

.kv-hero__buehne--meldung .kv-hero__text .bold-meldung--hero {
	margin-top: -4px;
}

.kv-hero__buehne--meldung .kv-hero__knoepfe {
	margin-top: 4px;
}

/* Die Meldung oben links in der Bildecke — in beiden Kopfbildern
   (Startseite und Veranstaltung). Sie liegt in der Bühne und nicht im
   Inhalt: der Inhalt sitzt unten und auf der Inhaltsachse der Seite,
   ein Badge in der Ecke gehört an die Bildkante.

   `z-index: 3`, weil die drei Verlaufsebenen darüberliegen würden — die
   Bühne trägt `isolation: isolate`, der Stapel bleibt also lokal. */
.kv-hero__buehne,
.kv-ekopf__buehne {
	--kv-ecke-top: var(--kv-bildbox-pad);
}

.kv-meldung-ecke {
	position: absolute;
	top: var(--kv-ecke-top);
	left: var(--kv-ecke-top);
	z-index: 3;
	display: flex;
}

/* Und der Inhalt macht Platz. Auf schmalen Geräten füllt er die ganze
   Bühne (gemessen bei 390px: Inhalt 448 hoch in einer 448 hohen Bühne) —
   dann beginnt er oben, und das absolute Badge lag über den
   Kategorie-Chips. Der Geschwisterwähler greift nur, wenn eine Meldung
   da ist: kein zweiter Zustand, den man pflegen müsste.

   44px = Höhe des Badges (28) plus Abstand (16). */
.kv-meldung-ecke ~ .kv-ekopf__inhalt,
.kv-meldung-ecke ~ .kv-hero__inhalt {
	padding-top: calc(var(--kv-ecke-top) + 44px);
}

@media (max-width: 900px) {
	.kv-hero__buehne,
	.kv-ekopf__buehne {
		--kv-ecke-top: 32px;
	}
}

@media (max-width: 700px) {
	.kv-hero__buehne,
	.kv-ekopf__buehne {
		--kv-ecke-top: 24px;
	}
}

.kv-hero__leiste {
	flex: 0 1 auto;
}

.kv-hero__text .kv-lead {
	max-width: 520px;
}

.kv-hero__knoepfe,
.kv-fokus__knoepfe,
.kv-band__knoepfe {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	margin-top: 8px;
}

.kv-hero__leer {
	padding-block: 120px;
}

/* -------------------------------------------------------------------------
   11. Im Fokus
   ------------------------------------------------------------------------- */

.kv-page .kv-fokus {
	width: 100%;
	background: var(--kv-soft);
	padding-block: var(--kv-abschnitt);
}

/* Flex mit Basis, nicht Grid mit zwei gleichen Spalten: die Referenz
   gibt dem Bild 1 1 440px und dem Text 1 1 360px bei max-width 520 —
   die Spalten sind also bewusst ungleich. */
.kv-page .kv-fokus__inner {
	display: flex;
	flex-direction: row;
	gap: 48px;
	align-items: center;
}

/* „Bild steht rechts" dreht nur die Reihenfolge, nicht das Markup —
   die Lesereihenfolge bleibt Bild, dann Text. */
.kv-page .kv-fokus__inner--rechts .kv-fokus__bild { order: 2; }

.kv-fokus__bild {
	flex: 1 1 440px;
	aspect-ratio: 16 / 10;
	/* aspect-ratio plus Hoehe laesst den Browser die BREITE ableiten —
	   width: 100% muss danebenstehen (§9.5). */
	width: 100%;
	border-radius: var(--kv-r-gross);
	overflow: hidden;
}

.kv-fokus__bild img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform var(--kv-t-bild), filter var(--kv-t-bild);
}

.kv-fokus__bild:hover img {
	transform: scale(1.045);
	filter: brightness(1.06);
}

/* Ohne align-items: flex-start; Kapsel und Buttons sitzen über
   align-self links, alles andere füllt die Spalte wie im Entwurf. */
.kv-fokus__text {
	display: flex;
	flex: 1 1 360px;
	flex-direction: column;
	gap: 20px;
	max-width: 520px;
}

/* Nur die Kapsel darf schrumpfen — Punkt und Rubrik sind reine Zeilen
   und dürfen die Spalte füllen, wie im Entwurf. */
.kv-page .kv-fokus__text > .kv-eyebrow--kapsel,
.kv-page .kv-fokus__text > .kv-tag { align-self: flex-start; }

/* -------------------------------------------------------------------------
   12. Aussage
   ------------------------------------------------------------------------- */

.kv-page .kv-aussage {
	width: 100%;
	background: var(--kv-weiss);
	padding-block: 120px;
}

/* Die Breite ist im Panel wählbar (Kunde, 09.09.2026: „bzw. im Builder
   die Option, dass ich den Bereich breiter machen kann"). Die 1080 px
   bleiben die Vorgabe — dieselbe Mechanik wie beim Wolken-Hero. */
.kv-page .kv-aussage--b880  .kv-aussage__satz { max-width: 880px; }
.kv-page .kv-aussage--b1080 .kv-aussage__satz { max-width: 1080px; }
.kv-page .kv-aussage--b1280 .kv-aussage__satz { max-width: 1280px; }
.kv-page .kv-aussage--b1512 .kv-aussage__satz { max-width: var(--kv-breite); }

.kv-aussage__satz {
	max-width: 1080px;
	margin-inline: auto;
	font-family: var(--kv-display);
	font-size: 40px;
	line-height: 48px;
	font-weight: 400;
	letter-spacing: -0.5px;
	text-align: center;
	/* Ohne balance bleibt die letzte Zeile als Einzelwort stehen. */
	text-wrap: balance;
	color: var(--kv-ink);
}

/* -------------------------------------------------------------------------
   13. Atempause
   ------------------------------------------------------------------------- */

.kv-page .kv-atempause {
	width: 100%;
	background: var(--kv-weiss);
	padding-block: 140px;
}

.kv-page .kv-atempause .kv-inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 40px;
	max-width: 900px;
	text-align: center;
}

/* Die Breite ist im Panel wählbar (Kunde, 09.09.2026). Die Regeln stehen
   NACH der Grundregel: `.kv-page .kv-atempause .kv-inner` hat dieselbe
   Spezifität wie `.kv-page .kv-atempause--b1080 .kv-inner`, und bei
   Gleichstand gewinnt die spätere. Gedeckelt wird beides — die Spur und
   der Satz darin. */
.kv-page .kv-atempause--b760  .kv-inner,
.kv-page .kv-atempause--b760  .kv-atempause__satz { max-width: 760px; }
.kv-page .kv-atempause--b900  .kv-inner,
.kv-page .kv-atempause--b900  .kv-atempause__satz { max-width: 900px; }
.kv-page .kv-atempause--b1080 .kv-inner,
.kv-page .kv-atempause--b1080 .kv-atempause__satz { max-width: 1080px; }
.kv-page .kv-atempause--b1280 .kv-inner,
.kv-page .kv-atempause--b1280 .kv-atempause__satz { max-width: 1280px; }
.kv-page .kv-atempause--b1512 .kv-inner,
.kv-page .kv-atempause--b1512 .kv-atempause__satz { max-width: var(--kv-breite); }

.kv-atempause__satz {
	max-width: 900px;
	font-family: var(--kv-display);
	font-size: clamp(26px, 3.2vw, 40px);
	line-height: 1.18;
	font-weight: 400;
	letter-spacing: -0.02em;
	text-wrap: balance;
	color: var(--kv-ink);
}

/* -------------------------------------------------------------------------
   14. Bildkacheln
   ------------------------------------------------------------------------- */

.kv-page .kv-kacheln {
	width: 100%;
	background: var(--kv-soft);
	padding-block: 40px var(--kv-abschnitt);
}

.kv-kacheln__kopf {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 16px;
	margin-bottom: 40px;
}

/* Fragment Mono wie der Tag daneben, nicht die Fliesstext-Kleinschrift. */
.kv-kachel__datum {
	font-family: var(--kv-mono);
	font-size: 12px;
	line-height: 16px;
	font-weight: 400;
	letter-spacing: 0.75px;
	color: rgba(247, 246, 245, 0.85);
}

/* 26/32 MIT Laufweitenkorrektur — anders als die 24er-h3 setzt der
   Entwurf sie hier auf -0.02em. */
.kv-kachel__titel {
	font-size: 26px;
	line-height: 32px;
	letter-spacing: -0.02em;
	color: var(--kv-soft);
	text-wrap: balance;
}

/* -------------------------------------------------------------------------
   15. Mitgliedschaftsband
   ------------------------------------------------------------------------- */

.kv-page .kv-band {
	width: 100%;
	background: var(--kv-soft);
	padding: var(--kv-rand) var(--kv-rand) var(--kv-abschnitt);
}

/* Anders als der Hero laeuft das Band NICHT ueber die volle Breite:
   die Referenz deckelt es bei 1512 px. */
.kv-band__buehne {
	position: relative;
	display: flex;
	align-items: flex-end;
	width: 100%;
	max-width: var(--kv-breite);
	margin-inline: auto;
	min-height: 620px;
	border-radius: var(--kv-r-gross);
	overflow: hidden;
	isolation: isolate;
}

.kv-band__motiv {
	position: absolute;
	inset: 0;
	z-index: 0;
}

.kv-band__motiv img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.kv-band__buehne--mittig .kv-band__motiv img { object-position: center center; }
.kv-band__buehne--oben   .kv-band__motiv img { object-position: center top; }
.kv-band__buehne--unten  .kv-band__motiv img { object-position: center bottom; }

.kv-band__ton,
.kv-band__unten {
	position: absolute;
	z-index: 1;
	pointer-events: none;
}

.kv-band__ton {
	inset: 0;
	background: rgba(35, 31, 35, 0.34);
}

/* Auch hier in PIXELN, nicht in Prozent — dieselbe Rechnung wie beim
   Hero und bei den Bildkacheln: der Text sitzt immer gleich weit über der
   unteren Kante, der Verlauf soll dort immer gleich stark sein. Mit 88 %
   und Prozentstopps hatte die Überschrift auf 390 px nur 3,8:1. */
.kv-band__unten {
	left: 0;
	right: 0;
	bottom: 0;
	height: 100%;
	background: linear-gradient(
		0deg,
		rgba(35, 31, 35, 0.9) 0px,
		rgba(35, 31, 35, 0.84) 180px,
		rgba(35, 31, 35, 0.6) 320px,
		rgba(35, 31, 35, 0.24) 440px,
		rgba(35, 31, 35, 0) 560px
	);
}

.kv-page .kv-band__inhalt {
	position: relative;
	z-index: 2;
	display: flex;
	flex-direction: column;
	gap: 40px;
	padding: var(--kv-bildbox-pad);
}

.kv-band__kopf {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 48px;
	flex-wrap: wrap;
}

.kv-band__text {
	display: flex;
	flex: 1 1 480px;
	flex-direction: column;
	gap: 20px;
	max-width: 720px;
}

.kv-band__titel {
	font-size: clamp(30px, 3.6vw, 48px);
	/* 1.08, nicht die 1.05 der Abschnitts-H2 — gemessen 51,84 px bei
	   48 px Schrift. */
	line-height: 1.08;
	text-wrap: balance;
}

.kv-band__karte {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 24px 32px;
	align-items: start;
	padding: 24px;
}

.kv-band__vorteil {
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.kv-band__vorteiltitel {
	font-family: var(--kv-text);
	font-size: 16px;
	line-height: 24px;
	font-weight: 500;
	color: var(--kv-soft);
}

/* Die Glaskarte hat ihre eigene Kleinschrift: 14/22 statt 13/20, und
   eine Spur blasser als der übrige helle Text. */
.kv-band__karte .kv-klein {
	font-size: 14px;
	line-height: 22px;
	color: rgba(247, 246, 245, 0.78);
}

/* =========================================================================
   16. Responsive Stufen

   Grundhaltung ist fluid (clamp, flex-basis). Media Queries stehen nur
   dort, wo sich das VERHALTEN aendert — Spaltenzahlen, Stapeln, das
   Wegklappen der Navigation (§9.5).

   Spaltenzahlen sind ausdruecklich vorgegeben, nicht per auto-fit geraten:
   Kunden sehen einen 5+1-Umbruch sofort.
   ========================================================================= */

/* --- bis 1200: Navigation ruecken enger zusammen ----------------------- */
@media (max-width: 1200px) {
	.kv-page .kv-kopf__inner { gap: 20px; }
	.kv-page .kv-nav         { gap: 16px; }
}

/* --- bis 900: die Navigation wandert ins Vollbildmenü -----------------
   EINE Schwelle, und zwar 900 — so steht sie in der Spezifikation der
   Mobilnavigation, und `kv.js` fragt dieselbe Zahl über `matchMedia` ab.
   Vorher lag der Umschlag bei 1024 und das Skript bei 900: dazwischen
   zeigte die Seite den Button, während das Skript sich noch für breit
   hielt.

   Ohne JavaScript bleibt die Navigation im Fluss stehen — gestapelt
   unter der Kopfzeile. Der Ausfallzustand ist die sichtbare Navigation,
   nicht die verschwundene.
   --------------------------------------------------------------------- */
@media (max-width: 900px) {
	/* Der Button erscheint nur, wenn er auch etwas tun kann. */
	.kv-page.kv-js .kv-burger { display: flex; }

	/* Logo 150 px, wie in der Spezifikation. */
	.kv-page .kv-kopf__logo img { width: 150px; }

	/* Mobil ist die Kopfzeile EINE Zeile: Logo links, Umschalter rechts
	   (Spezifikation). Kein Umbruch, und der Button „Mitglied werden"
	   steht nicht mehr daneben — er sitzt im Vollbildmenü. Vorher stapelte
	   sich der Kopf auf 164 px Höhe und nahm ein Viertel des Telefons ein. */
	.kv-page .kv-kopf__inner { flex-wrap: nowrap; }

	.kv-page .kv-kopf__rechts .kv-btn { display: none; }

	/* Kein eigener Rand: der Kopf folgt `--kv-rand` wie jeder Abschnitt.
	   Der Entwurf setzt mobil 32 px — genau das gibt `--kv-rand` unten
	   jetzt her, und damit steht das Logo auf derselben Achse wie der
	   Text der Abschnitte. Vorher lagen sie 12 px auseinander. */

	.kv-page .kv-nav {
		order: 3;
		flex-direction: column;
		align-items: flex-start;
		width: 100%;
		gap: 4px;
		padding-top: 16px;
		margin-top: 16px;
		border-top: 1px solid var(--kv-ink-12);
	}

	.kv-page .kv-nav__link {
		width: 100%;
		padding-block: 10px;
		font-size: 18px;
	}

	/* Mit Skript übernimmt das Vollbildmenü: die Navigation im Kopf ist
	   dann weg, der Button öffnet die Schublade. */
	.kv-page.kv-js .kv-nav { display: none; }
}

/* --- bis 900: zweispaltige Sektionen stapeln --------------------------- */
@media (max-width: 900px) {
	.kv-page .kv-fokus__inner { flex-direction: column; }

	/* „Bild rechts" hat gestapelt keine Bedeutung mehr — das Bild gehoert
	   nach oben, sonst startet die Sektion mit einer Textwand. */
	.kv-page .kv-fokus__inner--rechts .kv-fokus__bild { order: 0; }

	.kv-page .kv-fokus__text {
		flex-basis: auto;
		max-width: 640px;
	}

	.kv-page .kv-hero__inhalt,
	.kv-page .kv-band__kopf {
		flex-direction: column;
		align-items: flex-start;
		gap: 28px;
	}

	/* Ab hier stapelt der Hero: der Textblock steht über die ganze Breite,
	   und die Bühne ist 100 px kürzer. Damit ist die MASKE falsch — sie
	   nimmt dem Text die Abdunklung, die sie auf dem großen Bild der
	   rechten Bildhälfte zurückgibt. Gemessen bei 900 px: Eyebrow 2,2:1.

	   Also ohne Maske und mit kräftigerem Band. Auf kleinen Geräten sieht
	   man vom Motiv ohnehin fast nur den Teil, hinter dem Schrift steht. */
	.kv-hero__unten {
		-webkit-mask-image: none;
		mask-image: none;
		/* Prozent statt Pixel — und mit einem MINDESTWERT oben.
		   Hier stapelt der Hero: die Infoleiste rutscht unter den Text,
		   der Textblock beginnt dadurch fast am oberen Rand. Ein Verlauf,
		   der oben auf Null geht, lässt den Eyebrow über dem Kronleuchter
		   stehen — gemessen 1,9:1. Der Boden von 45 % deckelt den
		   schlimmsten Fall, egal wie lang die Überschrift wird. */
		background: linear-gradient(
			0deg,
			rgb(35 31 35 / calc(0.88 * var(--kv-deckung))) 0%,
			rgb(35 31 35 / calc(0.82 * var(--kv-deckung))) 40%,
			rgb(35 31 35 / calc(0.72 * var(--kv-deckung))) 66%,
			rgb(35 31 35 / calc(0.62 * var(--kv-deckung))) 86%,
			rgb(35 31 35 / calc(0.58 * var(--kv-deckung))) 100%
		);
	}

	.kv-hero__buehne { min-height: 620px; }

	.kv-page .kv-hero__inhalt,
	.kv-page .kv-band__inhalt { padding: 32px; }

	.kv-raster--5 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
	.kv-raster--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.kv-raster--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

	.kv-page .kv-fuss__oben  { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.kv-page .kv-band__karte { grid-template-columns: repeat(2, minmax(0, 1fr)); }

	.kv-aussage__satz  { font-size: 32px; line-height: 40px; }
	.kv-page .kv-aussage    { padding-block: 80px; }
	.kv-page .kv-atempause  { padding-block: 96px; }
}

/* --- bis 700: alles einspaltig ----------------------------------------- */
@media (max-width: 700px) {
	/* 32 px wie im Entwurf (dort ist der Seitenrand auf jeder Stufe 32),
	   aber nicht auf Kosten sehr kleiner Geräte: bis etwa 400 px Fenster
	   wächst der Rand mit der Breite, darüber steht er auf 32.
	     320 px → 26   ·   390 px → 31   ·   ab 400 px → 32
	   Vorher waren es hier pauschal 20 px. Der Kopf richtet sich nach
	   derselben Zahl, sonst stünde das Logo auf einer anderen Achse als
	   der Text darunter. */
	:root { --kv-rand: clamp(20px, 8vw, 32px); }

	.kv-raster--5,
	.kv-raster--4,
	.kv-raster--3 { grid-template-columns: minmax(0, 1fr); gap: 24px; }

	.kv-karten__raster > *,
	.kv-kontakt__raster > *,
	.kv-vorteile__raster > * { flex-basis: 100%; max-width: none; }

	.kv-page .kv-fuss__oben  { grid-template-columns: minmax(0, 1fr); gap: 32px; }
	.kv-page .kv-band__karte { grid-template-columns: minmax(0, 1fr); }

	.kv-h1,
	.kv-page .kv-hero__text .kv-h1 { font-size: 40px; line-height: 46px; }

	.kv-hero__buehne { min-height: 540px; }
	.kv-band__buehne { min-height: 560px; }


	.kv-kachel { min-height: 420px; }

	/* Die Infoleiste wird zur Spalte, sonst quetscht sie drei Felder plus
	   Trennstriche in 320 px. Die Striche entfallen dabei. */
	.kv-page .kv-glas {
		flex-direction: column;
		align-items: flex-start;
		gap: 10px;
		width: 100%;
	}

	.kv-glas__strich { display: none; }

	.kv-page .kv-fuss__unten {
		flex-direction: column;
		align-items: flex-start;
		gap: 16px;
	}

	.kv-aussage__satz { font-size: 26px; line-height: 34px; }
}

/* --- bis 480: Logo kleiner, Knoepfe volle Breite ----------------------- */
@media (max-width: 480px) {
	/* Kein eigenes Maß mehr: die Spezifikation kennt 150 (schmal) und
	   210 (Desktop). Hier standen 168 aus einer früheren Stufe. */
	.kv-page .kv-fuss__logo img { width: 200px; }

	.kv-page .kv-hero__knoepfe .kv-btn,
	.kv-page .kv-band__knoepfe .kv-btn,
	.kv-page .kv-fokus__knoepfe .kv-btn {
		flex: 1 1 100%;
	}

	.kv-page .kv-hero__inhalt,
	.kv-page .kv-band__inhalt { padding: 24px 20px; }
}

/* =========================================================================
   17. Wolken-Hero
   ========================================================================= */

/* Das gesamte vertikale Polster sitzt am Abschnitt, nicht halb hier und
   halb am Wrapper darin — sonst addiert sich die Stufe aus dem Panel zu
   einem Rest, den niemand sieht. */
/* Der Abschnitt traegt die Farbe des FOLGENDEN Abschnitts — dorthin
   blendet die Flaeche darin aus. */
.kv-page .kv-wolkenhero {
	position: relative;
	width: 100%;
	background: var(--kv-auslauf, var(--kv-weiss));
	padding-block: 0;
}

.kv-page .kv-wolkenhero--auslauf-weiss  { --kv-auslauf: var(--kv-weiss); }
.kv-page .kv-wolkenhero--auslauf-footer { --kv-auslauf: var(--kv-footer); }
.kv-page .kv-wolkenhero--auslauf-soft   { --kv-auslauf: var(--kv-soft); }

/* Die Flaeche mit Wolke und Hintergrund. Sie darf ausblenden, ohne dass
   dahinter Weiss durchscheint. */
.kv-page .kv-wolkenhero__flaeche {
	position: relative;
	width: 100%;
	background: var(--kv-soft);
	padding-block: var(--kv-hero-top) 0;
	/* Der Seitenrand kommt sonst über :has(> .kv-inner) vom Abschnitt.
	   Hier liegt die .kv-inner eine Ebene tiefer — der Abschnitt trägt
	   die Farbe des nächsten, die Fläche den Inhalt —, die Regel greift
	   also nicht. Ohne diese Zeile stand jeder Wolken-Hero der Seite
	   1440 statt 1376 px breit. */
	padding-inline: var(--kv-rand);
}

/* DIE WOLKE BRAUCHT AUSLAUF — UND EINEN WEICHEN ABSCHLUSS.
 *
 * Die Referenz setzt unter den Inhalt einen 200 px hohen Abstandshalter:
 * ein leeres div, damit der weichgezeichnete Verlauf ausklingen kann,
 * bevor `overflow: hidden` ihn abschneidet. Ich hatte nur das Polster aus
 * dem style-Attribut abgelesen (140/32/0) und den Halter übersehen, weil
 * er kein Polster IST — der Hero endete hart unter den Buttons.
 *
 * Das allein reicht aber nicht. Die Wolke ist mit 120 px weichgezeichnet
 * und reicht bis 680 px hinunter; bei 592 px Abschnittshöhe schneidet der
 * Clip mitten in den sichtbaren Verlauf. Dazu kommt die Kante zwischen
 * #F7F6F5 und dem weißen Abschnitt darunter. Beides ist im Entwurf
 * sichtbar — HIER BEWUSST NICHT.
 *
 * Eine Maske statt zweier Verläufe: sie blendet Hintergrund UND Wolke
 * gemeinsam aus, egal welche Farbe der nächste Abschnitt hat. Ein
 * Verlauf auf den Hintergrund müsste dessen Farbe kennen und stimmte auf
 * jeder zweiten Seite nicht.
 *
 * 240 px Polster, 200 px Ausblendung: der Inhalt endet immer über der
 * Ausblendung, sonst würde er mit verblassen. */
.kv-page .kv-wolkenhero__flaeche.kv-wolke-buehne {
	/* 168/132 statt 240/200 (Kunde, 07.09.2026: „Hier wäre es schön, wenn
	   der Abstand noch etwas weniger wäre"). Das Verhältnis bleibt: das
	   Polster muss GRÖSSER sein als die Ausblendung, sonst verblasst der
	   Inhalt mit — hier 36 px Luft zwischen Textende und Beginn der
	   Ausblendung. */
	padding-bottom: 168px;
	mask-image: linear-gradient(180deg, #000 calc(100% - 132px), transparent 100%);
	-webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 132px), transparent 100%);
}

.kv-page .kv-wolkenhero--flach .kv-wolkenhero__flaeche {
	padding-top: 120px;
}

/* Die flache Fassung brauchte früher einen eigenen Verlauf nach unten.
   Das erledigt jetzt die Maske am Abschnitt — für beide Höhen gleich. */
.kv-wolkenhero__ausblendung {
	display: none;
}

.kv-page .kv-wolkenhero__inhalt {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 32px;
	max-width: 680px;
	text-align: center;
}

/* Der Lead unter der Wolke ist größer als der übrige Lead: 20/32. */
.kv-page .kv-wolkenhero__inhalt .kv-lead {
	font-size: 20px;
	line-height: 32px;
}

/* Der knappe Vorspann: Fließtextmaß statt Hero-Maß — die Rechtsseiten
   und alles, wo der Vorspann nur einordnet. Steht bewusst NACH der
   Wolken-Regel: gleiche Spezifität, also entscheidet die Reihenfolge. */
.kv-page .kv-wolkenhero__inhalt .kv-lead--knapp,
.kv-page .kv-lead--knapp {
	font-size: 16px;
	line-height: 26px;
	max-width: 680px;
}

.kv-wolkenhero__titel {
	font-family: var(--kv-display);
	font-size: 48px;
	line-height: 56px;
	font-weight: 400;
	letter-spacing: -0.5px;
	text-wrap: balance;
	color: var(--kv-ink);
}

.kv-wolkenhero__knoepfe {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	justify-content: center;
}

/* =========================================================================
   18. Medien + Text
   ========================================================================= */

.kv-page .kv-mt {
	width: 100%;
	padding-block: var(--kv-abschnitt);
}

/* Der Podcast-Kopf sitzt enger als eine Inhaltssektion: 64 statt 80. */
.kv-page .kv-mt--knapp  { padding-block: 64px; }
.kv-page .kv-mt--gross  { padding-block: 120px; }

.kv-page .kv-mt--footer { background: var(--kv-footer); }
.kv-page .kv-mt--soft   { background: var(--kv-soft); }
.kv-page .kv-mt--weiss  { background: var(--kv-weiss); }

.kv-page .kv-mt__inner {
	display: flex;
	flex-direction: row;
	gap: 80px;
	align-items: center;
}

.kv-page .kv-mt__inner--links .kv-mt__bild { order: -1; }

.kv-mt__text {
	display: flex;
	flex: 1 1 480px;
	flex-direction: column;
	align-items: flex-start;
	gap: 24px;
	max-width: 564px;
}

.kv-mt__bild {
	flex: 1 1 480px;
	width: 100%;
	border-radius: var(--kv-r-gross);
	overflow: hidden;
}

/* Der Podcast-Kopf: weiter Spalt, kein Deckel auf der Textspalte, und
   der Vorspann bricht bei 520 — so steht es im Entwurf, und nur dort. */
.kv-page .kv-mt__inner--weit { gap: 132px; }

.kv-page .kv-mt__inner--weit .kv-mt__text {
	flex-basis: 448px;
	max-width: none;
	gap: 32px;
}

.kv-page .kv-mt__inner--weit .kv-mt__text .kv-lead,
.kv-page .kv-mt__inner--weit .kv-mt__text .kv-text { max-width: 520px; }

.kv-mt__bild--quadrat { aspect-ratio: 1 / 1; }
.kv-mt__bild--breit   { aspect-ratio: 16 / 10; }
.kv-mt__bild--hoch    { aspect-ratio: 4 / 5; }

.kv-mt__bild img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.kv-mt__bild--mittig img { object-position: center center; }
.kv-mt__bild--oben   img { object-position: center top; }
.kv-mt__bild--unten  img { object-position: center bottom; }

/* =========================================================================
   19. Bildband (Slider)
   ========================================================================= */

.kv-page .kv-band-sec {
	width: 100%;
	padding-block: var(--kv-abschnitt);
	overflow: hidden;
}

.kv-page .kv-band-sec--weiss  { background: var(--kv-weiss); }
.kv-page .kv-band-sec--soft   { background: var(--kv-soft); }
.kv-page .kv-band-sec--footer { background: var(--kv-footer); }

.kv-slider {
	padding-inline: 8px;
	/* Keine seitliche Maske (Kunde, 09.09.2026: „die blassen Overlays
	   weg"). Sie sollte das Band weich auslaufen lassen, machte aber die
	   Motive am Rand ausgewaschen — und ein angeschnittenes Foto liest
	   sich als angeschnitten, nicht als Fehler. Mobil war sie schon am
	   07.09. heraus; jetzt auf allen Breiten. */
}

.kv-track {
	animation-duration: var(--kv-slider-dauer, 60s);
}

/* Stehendes Band: die Bilder teilen sich die Breite, 400 px hoch wie im
   Entwurf. Ein einzelnes Bild fuellt damit die ganze Inhaltsbreite. */
.kv-standband {
	display: flex;
	flex-direction: row;
	gap: 16px;
}

/* Im stehenden Band zählt die Breitenklasse nicht: die Bilder teilen
   sich die Reihe. Ohne das !important gewinnt `.kv-track__bild--breit`
   mit seinen 560 px, und ein einzelnes Bild füllte die Reihe nicht. */
.kv-page .kv-standband .kv-track__bild {
	flex: 1 1 0;
	width: auto !important;
	min-width: 0;
	height: 400px;
	border-radius: var(--kv-r-gross);
}

.kv-track__bild {
	flex: 0 0 auto;
	height: 480px;
	overflow: hidden;
	border-radius: var(--kv-r-mittel);
	background-color: var(--kv-ink);
}

.kv-track__bild--breit  { width: 560px; }
.kv-track__bild--schmal { width: 380px; }

/* Das Motiv liegt seit dem 08.09.2026 als <img> im Kasten (srcset), der
   Bildausschnitt wandert damit von `background-position` auf
   `object-position` — dieselbe Wahl im Panel, dieselbe Wirkung. */
.kv-page .kv-track__motiv {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: inherit;
}

.kv-track__bild--mittig .kv-track__motiv { object-position: center center; }
.kv-track__bild--oben   .kv-track__motiv { object-position: center top; }
.kv-track__bild--unten  .kv-track__motiv { object-position: center bottom; }

/* =========================================================================
   20. Textzeile
   ========================================================================= */

.kv-page .kv-textzeile {
	width: 100%;
}

.kv-page .kv-textzeile--sektion {
	padding-block: var(--kv-abschnitt);
}

.kv-page .kv-textzeile__inner {
	display: flex;
	flex-direction: row;
	gap: 64px;
	justify-content: space-between;
	align-items: flex-start;
	padding-inline: 64px;
}

.kv-textzeile__titel {
	flex: 1 1 380px;
	max-width: 460px;
}

/* Die 56er-Stufe steht enger: bei 460 px liefe die Zeile auf zwei statt
   drei Zeilen, und der Umbruch traegt hier die Aussage. */
.kv-textzeile__titel.kv-h2--56 { max-width: 418px; }

.kv-textzeile__text {
	flex: 1 1 480px;
	max-width: 752px;
}

.kv-textzeile__text .kv-lead + .kv-lead {
	margin-top: 20px;
}

/* =========================================================================
   21. Team
   ========================================================================= */

.kv-page .kv-team {
	width: 100%;
	padding-block: var(--kv-abschnitt);
}

.kv-page .kv-team--soft  { background: var(--kv-soft); }
.kv-page .kv-team--weiss { background: var(--kv-weiss); }

.kv-page .kv-team__inner {
	display: flex;
	flex-direction: column;
	gap: 72px;
}

.kv-team__kopf {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 16px;
}

.kv-team__kopf .kv-h2  { max-width: 900px; }
.kv-team__kopf .kv-lead { max-width: 620px; }

.kv-team__gruppe {
	display: flex;
	flex-direction: column;
	gap: 28px;
}

/* Die Gruppenbeschriftung steht im Entwurf über einer Linie — sie
   trennt Vorstand und Beirat, ohne eine zweite Überschrift zu setzen. */
.kv-team__label {
	display: flex;
	align-items: baseline;
	gap: 16px;
	padding-bottom: 16px;
	border-bottom: 1px solid rgba(35, 31, 35, 0.16);
}

/* Steht die Reihe mittig, steht die Gruppenüberschrift mit ihr — die
   Trennlinie behält ihre volle Breite, sie trennt den Abschnitt. */
.kv-team__label--mitte {
	justify-content: center;
}

.kv-team__raster {
	gap: 16px;
}

/* Mittig: aus dem Raster wird eine Flexzeile, die Karten behalten die
   Spaltenbreite. Kundenwunsch (08.09.2026): „dass die Bilder zentriert
   sind — also entweder links oder mittig anordnen." Sichtbar wird es nur
   bei einer unvollständigen Reihe; eine volle Reihe füllt die Breite. */
.kv-page .kv-team__raster--mitte {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
}

.kv-page .kv-team__raster--mitte > * {
	flex: 0 1 calc(
		(100% - (var(--kv-team-spalten, 4) - 1) * 16px) / var(--kv-team-spalten, 4)
	);
	min-width: 0;
}

/* Unter 700 px rechnet das Team mit zwei Spalten — nachgesehen, nicht
   geraten: die Regel dafür steht in der 700er-Stufe, nicht in der 900er.
   Mit der falschen Grenze waren die Karten bei 768 px plötzlich 344
   statt 224 px breit, also breiter als im linksbündigen Raster. */
@media (max-width: 700px) {
	.kv-page .kv-team__raster--mitte > * {
		flex: 0 1 calc((100% - 16px) / 2);
	}
}

.kv-person {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.kv-person__bild {
	aspect-ratio: 4 / 5;
	border-radius: var(--kv-r-mittel);
	overflow: hidden;
}

.kv-person__bild img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* Ohne Portrait bleibt die gestreifte Flaeche stehen. Absicht: eine
   Luecke ist ehrlicher als ein erfundenes Bild. */
.kv-person__bild--leer {
	display: flex;
	align-items: flex-end;
	padding: 14px;
	background: repeating-linear-gradient(135deg, #E7E4E0 0 10px, #DFDBD7 10px 20px);
}

.kv-person__bild--leer span {
	font-family: var(--kv-mono);
	font-size: 11px;
	font-weight: 400;
	letter-spacing: 0.75px;
	color: rgba(35, 31, 35, 0.45);
}

.kv-person__text {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.kv-person__name {
	font-size: 17px;
	line-height: 24px;
	font-weight: 500;
	color: var(--kv-ink);
}

.kv-person__rolle {
	font-size: 15px;
	line-height: 22px;
	font-weight: 300;
	color: var(--kv-ink-64);
}

/* Fünf Spalten sind schmaler als vier: der Entwurf setzt die Namen dort
   eine Stufe kleiner, damit sie nicht umbrechen. */
.kv-page .kv-raster--5 .kv-person__name  { font-size: 15px; line-height: 22px; }
.kv-page .kv-raster--5 .kv-person__rolle { font-size: 13px; line-height: 20px; }

/* =========================================================================
   22. Podcast-Folgen
   ========================================================================= */

.kv-page .kv-folgen {
	width: 100%;
	background: var(--kv-soft);
	padding-block: var(--kv-abschnitt);
}

.kv-page .kv-folgen__inner {
	display: flex;
	flex-direction: column;
	gap: 40px;
}

.kv-folgen__liste {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.kv-folge {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: 32px;
	padding: var(--kv-karte-pad);
	border-radius: var(--kv-r-klein);
	background: var(--kv-weiss);
	transition: box-shadow var(--kv-t-flaeche);
}

.kv-folge:hover {
	box-shadow: var(--kv-schatten-karte);
}

.kv-folge__cover {
	flex: 0 0 auto;
	width: 96px;
	height: 96px;
	overflow: hidden;
	border-radius: var(--kv-r-mini);
	background-color: var(--kv-ink);
}

/* Das Cover liegt seit dem 08.09.2026 als <img> im Kasten (srcset). */
.kv-page .kv-folge__motiv {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: inherit;
}

.kv-folge__cover--leer {
	background: repeating-linear-gradient(135deg, #E7E4E0 0 10px, #DFDBD7 10px 20px);
}

.kv-folge__text {
	display: flex;
	flex: 1 1 320px;
	flex-direction: column;
	gap: 6px;
}

/* Die Folgenüberschrift trägt im Entwurf keine Laufweite — anders als
   die Karten-h3 sonst. */
.kv-folge__titel { letter-spacing: normal; }

.kv-folge__meta {
	font-family: var(--kv-mono);
	font-size: 12px;
	line-height: 16px;
	font-weight: 400;
	letter-spacing: 0.75px;
	color: var(--kv-rot);
}

.kv-folge__aktion {
	flex: 0 0 auto;
}

/* =========================================================================
   23. Vorteilskarten
   ========================================================================= */

.kv-page .kv-vorteile {
	width: 100%;
	padding-block: var(--kv-abschnitt);
}

.kv-page .kv-vorteile--weiss { background: var(--kv-weiss); }
.kv-page .kv-vorteile--soft  { background: var(--kv-soft); }

.kv-page .kv-vorteile__inner {
	display: flex;
	flex-direction: column;
	gap: 40px;
}

/* Auch hier die flexible Reihe des Entwurfs statt eines starren Rasters. */
.kv-vorteile__raster {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	gap: 16px;
}

/* KEINE Deckelung auf ein Drittel.
   -----------------------------------------------------------------------
   Hier stand `max-width: max(360px, calc((100% - 32px) / 3))`. Damit
   blieben die zwei Karten der letzten Zeile 448 px breit, und rechts
   blieb ein Drittel der Zeile leer. Der Entwurf setzt nur
   `flex: 1 1 320px` — dort füllen zwei Karten die Zeile (gemessen im
   Referenzdokument: 680 px je Karte bei 1376 px Inhaltsbreite, bei uns
   448). Vom Kunden gemeldet: „Bei ‚Mitglied werden' ist der Aufbau der
   Vorteile noch anders als im ursprünglichen Design."

   Die Karte wächst also mit — genau das ist der Sinn von `flex-grow`. */
.kv-vorteile__raster > * {
	flex: 1 1 320px;
	min-width: 0;
}

.kv-vorteil {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: 24px;
	min-height: 220px;
	padding: var(--kv-karte-pad);
	border-radius: var(--kv-r-klein);
	background: var(--kv-soft);
}

.kv-vorteile--soft .kv-vorteil {
	background: var(--kv-weiss);
}

/* Wie die Symbolflaechen der Karten: pastellfarbenes Quadrat, roter
   Punkt darin — sechs rote Bloecke waeren lauter als die Texte. */
.kv-vorteil__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border-radius: var(--kv-r-mini);
	background: var(--kv-creme);
	flex: 0 0 auto;
}

.kv-vorteile__raster > *:nth-child(3n + 2) .kv-vorteil__icon { background: var(--kv-aprikose); }
.kv-vorteile__raster > *:nth-child(3n + 3) .kv-vorteil__icon { background: var(--kv-rose); }

.kv-page .kv-vorteile__titel--mitte {
	align-self: center;
	max-width: 760px;
	text-align: center;
}

.kv-vorteil__text {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

/* Der Text IN einer Karte ist kleiner als Fließtext im Abschnitt:
   13/20 statt 16/26, und eine Stufe blasser. */
.kv-page :where(.kv-vorteil, .kv-kkarte, .kv-folge) .kv-text {
	font-size: 13px;
	line-height: 20px;
	color: var(--kv-ink-64);
}

.kv-vorteil__titel {
	font-family: var(--kv-text);
	font-size: 16px;
	line-height: 24px;
	font-weight: 500;
	color: var(--kv-ink);
}

/* --- Bildlinks (Plattform-Badges) ------------------------------------- */

.kv-badges {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 12px;
	margin-top: 4px;
}

.kv-page .kv-badge {
	display: block;
	line-height: 0;
	border-radius: var(--kv-r-mini);
	transition: opacity var(--kv-t-flaeche);
}

.kv-page .kv-badge:hover {
	opacity: 0.78;
}

.kv-badge img {
	height: var(--kv-badge-hoehe, 44px);
	width: auto;
	display: block;
}

/* Der Verein: Textzeile schliesst direkt an das Bildband an. Die
   Referenz setzt dort 96 px Abstand, nicht die 80 des Abschnitts. */
.kv-page .kv-band-sec:has(+ .kv-textzeile) {
	padding-bottom: 0;
}

.kv-page .kv-band-sec + .kv-textzeile {
	padding-top: 96px;
	padding-bottom: var(--kv-abschnitt);
	background: var(--kv-weiss);
}

/* h1 in einem Zweispalter: kleiner als der Bild-Hero, sonst sprengt er
   die 564-px-Spalte. */
.kv-h1--seite {
	font-size: 64px;
	line-height: 68px;
	letter-spacing: -1px;
	text-wrap: balance;
}

/* -------------------------------------------------------------------------
   24. Flex-Kinder duerfen schrumpfen

   `flex: 1 1 480px` allein reicht nicht: die Vorgabe fuer min-width ist
   `auto`, also die Inhaltsbreite. Unter 480 px Platz ragt das Kind dann
   hinaus, statt umzubrechen. Gemessen auf „Der Verein" (+118 px bei 320)
   und Podcast (+32 px bei 320).
   ------------------------------------------------------------------------- */

.kv-page :where(
	.kv-hero__text,
	.kv-fokus__bild,
	.kv-fokus__text,
	.kv-mt__text,
	.kv-mt__bild,
	.kv-band__text,
	.kv-textzeile__titel,
	.kv-textzeile__text,
	.kv-folge__text
) {
	min-width: 0;
}

/* -------------------------------------------------------------------------
   25. Responsive Stufen der Innenseiten
   ------------------------------------------------------------------------- */

@media (max-width: 1100px) {
	.kv-page .kv-textzeile__inner { padding-inline: 32px; }
}

@media (max-width: 900px) {
	.kv-page .kv-mt__inner {
		flex-direction: column;
		gap: 48px;
	}

	/* Gestapelt hat „Bild links" keine Bedeutung mehr — das Bild gehoert
	   unter den Text, sonst startet die Sektion mit einem Motiv ohne
	   Zusammenhang. */
	.kv-page .kv-mt__inner--links .kv-mt__bild { order: 0; }

	.kv-mt__text { flex-basis: auto; max-width: 640px; }

	.kv-page .kv-textzeile__inner {
		flex-direction: column;
		gap: 24px;
		padding-inline: 0;
	}

	.kv-textzeile__titel,
	.kv-textzeile__text { flex-basis: auto; max-width: 752px; }

	.kv-page .kv-wolkenhero { padding-top: 96px; }

	.kv-wolkenhero__titel { font-size: 36px; line-height: 44px; }

	.kv-track__bild { height: 360px; }
	.kv-track__bild--breit  { width: 420px; }
	.kv-track__bild--schmal { width: 290px; }

	.kv-page .kv-team__inner { gap: 48px; }
}

@media (max-width: 700px) {
	.kv-folge {
		flex-wrap: wrap;
		gap: 20px;
	}

	/* Cover und Text nebeneinander, der Button darunter über die ganze
	   Breite. Vorher trug der TEXT `order: 3` — gedacht für das
	   Umbruchlayout, in dem Cover und Button die erste Zeile teilen. Der
	   Button „Anhören" stand damit ÜBER dem Titel der Folge, zu der er
	   gehört. */
	.kv-folge__text { flex: 1 1 160px; order: 0; }

	.kv-folge__aktion { flex: 1 1 100%; order: 3; }

	.kv-folge__aktion .kv-btn { width: 100%; }

	.kv-track__bild { height: 280px; }
	.kv-track__bild--breit  { width: 320px; }
	.kv-track__bild--schmal { width: 220px; }

	.kv-wolkenhero__titel { font-size: 30px; line-height: 38px; }

	.kv-page .kv-wolkenhero__inhalt { gap: 24px; }
}

@media (max-width: 480px) {
	.kv-folge {
		flex-direction: column;
		align-items: flex-start;
	}

	/* In der Spalte zählt die Reihenfolge im Fluss: Cover, Text, Button. */
	.kv-folge__text   { order: 0; }
	.kv-folge__aktion { order: 1; width: 100%; }
}

/* =========================================================================
   26. Kontaktkarten
   ========================================================================= */

.kv-page .kv-kontakt {
	width: 100%;
	padding-block: var(--kv-abschnitt);
}

.kv-page .kv-kontakt--soft  { background: var(--kv-soft); }
.kv-page .kv-kontakt--weiss { background: var(--kv-weiss); }

/* Die Kartenreihe ist im Entwurf bei 1028 px gedeckelt und zentriert,
   nicht auf voller Inhaltsbreite. Vier Karten über 1512 px wirken sonst
   verloren. */
.kv-kontakt__raster {
	gap: 16px;
	max-width: 1028px;
	margin-inline: auto;
}

.kv-kkarte {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: 32px;
	min-height: 220px;
	padding: var(--kv-karte-pad);
	border-radius: var(--kv-r-klein);
	background: var(--kv-weiss);
	transition: box-shadow var(--kv-t-flaeche);
}

.kv-kontakt--weiss .kv-kkarte {
	background: var(--kv-soft);
}

.kv-kkarte:hover {
	box-shadow: var(--kv-schatten-karte);
}

.kv-kkarte__kopf {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
}

.kv-kkarte__wer {
	display: flex;
	flex-direction: column;
	gap: 4px;
	min-width: 0;
}

/* Kartenüberschriften sind KEINE Display-Zeile: Satoshi 16/24 in 500,
   wie im Entwurf. Ich hatte sie zuerst als 20/28 in der Displayschrift
   gesetzt — das machte die Karten optisch schwerer als die Vorlage. */
.kv-kkarte__titel {
	font-family: var(--kv-text);
	font-size: 16px;
	line-height: 24px;
	font-weight: 500;
	color: var(--kv-ink);
}

.kv-kkarte__adresse {
	font-size: 16px;
	line-height: 24px;
	font-weight: 300;
	color: var(--kv-ink-64);
	overflow-wrap: anywhere;
}

.kv-page .kv-kkarte__adresse a {
	color: var(--kv-rot);
}

/* Icon-Box 44x44. Die Symbole stecken als Datenurl in der Maske: drei
   kleine Pfade rechtfertigen keine drei Dateien. */
/* Die Symbolkachel ist im Entwurf hell mit dunklem Zeichen, nicht rot:
   vier rote Quadrate nebeneinander waeren lauter als die Adressen. */
.kv-kkarte__symbol {
	flex: 0 0 auto;
	width: 44px;
	height: 44px;
	border-radius: var(--kv-r-klein);
	background: var(--kv-soft);
	position: relative;
}

.kv-page .kv-kontakt--soft .kv-kkarte__symbol { background: var(--kv-soft); }

.kv-kkarte__symbol::after {
	content: '';
	position: absolute;
	inset: 12px;
	background: var(--kv-ink);
	mask-position: center;
	mask-repeat: no-repeat;
	mask-size: contain;
	-webkit-mask-position: center;
	-webkit-mask-repeat: no-repeat;
	-webkit-mask-size: contain;
}

.kv-kkarte__symbol--mail::after {
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='4' width='20' height='16' rx='2'/%3E%3Cpath d='m2 7 10 6 10-6'/%3E%3C/svg%3E");
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='4' width='20' height='16' rx='2'/%3E%3Cpath d='m2 7 10 6 10-6'/%3E%3C/svg%3E");
}

.kv-kkarte__symbol--instagram::after {
	mask-image: url("../img/icon-instagram.svg");
	-webkit-mask-image: url("../img/icon-instagram.svg");
}

.kv-kkarte__symbol--facebook::after {
	mask-image: url("../img/icon-facebook.svg");
	-webkit-mask-image: url("../img/icon-facebook.svg");
}

.kv-kkarte__symbol--telefon::after {
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6A19.8 19.8 0 0 1 2 4.2 2 2 0 0 1 4 2h3a2 2 0 0 1 2 1.7c.1 1 .4 1.9.7 2.8a2 2 0 0 1-.5 2.1L8 9.8a16 16 0 0 0 6 6l1.2-1.2a2 2 0 0 1 2.1-.4c.9.3 1.8.6 2.8.7a2 2 0 0 1 1.7 2z'/%3E%3C/svg%3E");
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6A19.8 19.8 0 0 1 2 4.2 2 2 0 0 1 4 2h3a2 2 0 0 1 2 1.7c.1 1 .4 1.9.7 2.8a2 2 0 0 1-.5 2.1L8 9.8a16 16 0 0 0 6 6l1.2-1.2a2 2 0 0 1 2.1-.4c.9.3 1.8.6 2.8.7a2 2 0 0 1 1.7 2z'/%3E%3C/svg%3E");
}

.kv-kkarte__symbol--ort::after {
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0z'/%3E%3Ccircle cx='12' cy='10' r='3'/%3E%3C/svg%3E");
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0z'/%3E%3Ccircle cx='12' cy='10' r='3'/%3E%3C/svg%3E");
}

.kv-kkarte__symbol--whatsapp::after {
	mask-image: url('../img/icon-whatsapp.svg');
	-webkit-mask-image: url('../img/icon-whatsapp.svg');
}

/* =========================================================================
   27. Ortsband
   ========================================================================= */

.kv-page .kv-ortsband {
	width: 100%;
	background: var(--kv-soft);
	padding-block: var(--kv-rand) var(--kv-abschnitt);
	padding-inline: var(--kv-rand);
}

.kv-ortsband__buehne {
	position: relative;
	display: flex;
	align-items: flex-end;
	width: 100%;
	max-width: var(--kv-breite);
	margin-inline: auto;
	min-height: 600px;
	border-radius: var(--kv-r-gross);
	overflow: hidden;
	isolation: isolate;
}

.kv-ortsband__motiv {
	position: absolute;
	inset: 0;
	z-index: 0;
}

.kv-ortsband__motiv img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.kv-ortsband__buehne--mittig .kv-ortsband__motiv img { object-position: center center; }
.kv-ortsband__buehne--oben   .kv-ortsband__motiv img { object-position: center top; }
.kv-ortsband__buehne--unten  .kv-ortsband__motiv img { object-position: center bottom; }

.kv-ortsband__ton,
.kv-ortsband__unten {
	position: absolute;
	z-index: 1;
	pointer-events: none;
}

.kv-ortsband__ton   { inset: 0; background: rgba(35, 31, 35, 0.32); }

/* In PIXELN verankert — vierter Fall derselben Sorte (Hero, Bildkacheln,
   Mitgliedschaftsband, Ortsband). Mit 80 % und Prozentstopps stand die
   Überschrift auf 390 px bei 1,88:1 und der Fließtext bei 2,45:1: weiße
   Schrift auf hellem Foto, praktisch unlesbar. Am Desktop war es
   unauffällig (6,7 bzw. 8,6), weil die Bühne dort flacher ist und der
   Text weiter unten sitzt. */
.kv-ortsband__unten {
	left: 0;
	right: 0;
	bottom: 0;
	height: 100%;
	background: linear-gradient(
		0deg,
		rgba(35, 31, 35, 0.88) 0px,
		rgba(35, 31, 35, 0.8) 200px,
		rgba(35, 31, 35, 0.55) 340px,
		rgba(35, 31, 35, 0.2) 460px,
		rgba(35, 31, 35, 0) 580px
	);
}

.kv-page .kv-ortsband__inhalt {
	position: relative;
	z-index: 2;
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: 40px;
	padding: var(--kv-bildbox-pad);
}

.kv-ortsband__text {
	display: flex;
	flex: 1 1 480px;
	min-width: 0;
	flex-direction: column;
	gap: 20px;
	max-width: 620px;
}

/* Auf dem abgedunkelten Bild steht der Satz voll hell — 0.82 wie im
   uebrigen Fliesstext waere hier zu leise. */
.kv-page .kv-ortsband__text .kv-text { color: var(--kv-soft); }

.kv-ortsband__karte {
	display: flex;
	flex: 0 0 auto;
	flex-direction: column;
	align-items: flex-start;
	gap: 16px;
}

.kv-ortsband__glas {
	align-items: flex-start;
}

.kv-ortsband__adresse {
	display: flex;
	flex-direction: column;
	gap: 2px;
	font-style: normal;
	font-size: 16px;
	line-height: 24px;
	color: var(--kv-soft);
}

/* Die Glaskarte des Ortsbands ist eine Spur zurückhaltender als die
   Infoleiste im Hero. */
.kv-page .kv-ortsband__glas .kv-glas__label {
	font-size: 12px;
	line-height: 16px;
	color: rgba(247, 246, 245, 0.6);
}

.kv-page .kv-ortsband .kv-eyebrow--hell { color: rgba(247, 246, 245, 0.85); }

/* =========================================================================
   28. Rechtstexte
   ========================================================================= */

.kv-page .kv-recht {
	width: 100%;
	background: var(--kv-weiss);
	padding-block: var(--kv-abschnitt);
}

.kv-page .kv-recht__inner {
	display: flex;
	flex-direction: row;
	gap: 80px;
	align-items: flex-start;
}

.kv-recht__text {
	flex: 1 1 520px;
	min-width: 0;
	max-width: 752px;
}

.kv-page .kv-recht__text :where(h2) {
	font-family: var(--kv-display);
	font-size: 32px;
	line-height: 40px;
	font-weight: 400;
	letter-spacing: -0.02em;
	margin-top: 56px;
	margin-bottom: 16px;
}

.kv-page .kv-recht__text > :first-child {
	margin-top: 0;
}

/* Die Zwischenüberschrift eines Rechtstextes ist Fließschrift in 500,
   keine Displayzeile — sie soll gliedern, nicht auftreten. */
.kv-page .kv-recht__text :where(h3) {
	font-family: var(--kv-text);
	font-size: 18px;
	line-height: 26px;
	font-weight: 500;
	margin-top: 32px;
	margin-bottom: 12px;
}

/* 0.8 statt 0.72: ein langer Rechtstext soll lesbar bleiben. */
.kv-page .kv-recht__text :where(p, ul, ol) {
	font-size: 16px;
	line-height: 26px;
	font-weight: 300;
	color: rgba(35, 31, 35, 0.8);
	margin-bottom: 16px;
}

.kv-page .kv-recht__text :where(ul, ol) {
	padding-left: 20px;
}

.kv-page .kv-recht__text li {
	margin-bottom: 8px;
}

.kv-recht__rand {
	position: sticky;
	top: calc(var(--kv-kopf-hoehe) + 32px);
	display: flex;
	flex: 1 1 300px;
	min-width: 0;
	flex-direction: column;
	gap: 20px;
	max-width: 380px;
	padding: 32px;
	border-radius: var(--kv-r-gross);
	background: var(--kv-soft);
}

.kv-recht__links {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.kv-page .kv-recht__link {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding-bottom: 12px;
	border-bottom: 1px solid var(--kv-ink-12);
	font-size: 16px;
	line-height: 24px;
	color: var(--kv-ink);
	transition: color var(--kv-t-schnell);
}

/* Der Pfeil rechts — dieselbe Marke wie an jedem anderen Verweis. */
.kv-page .kv-recht__link::after {
	content: '';
	width: 16px;
	height: 16px;
	flex-shrink: 0;
	background: currentColor;
	mask: url("../img/icon-chevron-right.svg") center / contain no-repeat;
	-webkit-mask: url("../img/icon-chevron-right.svg") center / contain no-repeat;
}

/* Im Inhaltsverzeichnis kein Pfeil und keine Linie: zehn Zeilen mit
   Trennern waeren ein Kasten voller Striche. */
.kv-page .kv-recht__rand--verzeichnis .kv-recht__link {
	display: block;
	padding-bottom: 0;
	border-bottom: 0;
}

.kv-page .kv-recht__rand--verzeichnis .kv-recht__link::after { content: none; }

.kv-page .kv-recht__link:hover,
.kv-page .kv-recht__link--aktiv {
	color: var(--kv-rot);
}

/* Das Inhaltsverzeichnis einer langen Seite steht kleiner als eine
   Verweisliste: zehn Zeilen sollen nicht so laut sein wie drei. */
.kv-recht__rand--verzeichnis {
	flex-basis: 340px;
	max-width: 340px;
	padding: 28px;
	gap: 16px;
}

.kv-page .kv-recht__rand--verzeichnis .kv-recht__link {
	font-size: 14px;
	line-height: 20px;
	font-weight: 300;
}

/* Kernaussage über dem Text: im Entwurf eine rote Fläche, keine
   Trennlinie. Die Displayzeile darin trägt ausnahmsweise keine negative
   Laufweite — sie steht in 24px und würde sonst gedrängt wirken. */
.kv-hervor {
	display: flex;
	flex-direction: column;
	gap: 12px;
	margin-bottom: 48px;
	padding: 32px;
	border-radius: var(--kv-r-gross);
	background: var(--kv-rot);
}

.kv-page .kv-hervor .kv-rubrik { color: var(--kv-licht-70); }

.kv-hervor__satz {
	font-family: var(--kv-display);
	font-size: 24px;
	line-height: 32px;
	font-weight: 400;
	letter-spacing: 0;
	color: var(--kv-soft);
	text-wrap: pretty;
}

.kv-hervor__zusatz {
	font-size: 14px;
	line-height: 22px;
	font-weight: 300;
	color: var(--kv-licht-86);
}

/* Anschrift am Ende eines Rechtstextes. */
/* Anschrift im Fließtext eines Rechtstextes. */
.kv-page .kv-rechtadresse {
	display: flex;
	flex-direction: column;
	gap: 4px;
	margin-bottom: 16px;
	font-style: normal;
	font-size: 16px;
	line-height: 26px;
	font-weight: 400;
	color: var(--kv-ink);
}

.kv-rechtkontakt address {
	display: flex;
	flex-direction: column;
	gap: 4px;
	font-style: normal;
	font-size: 16px;
	line-height: 26px;
	font-weight: 400;
	color: var(--kv-ink);
}

/* Hinweiskasten unter einem ungeprüften Entwurf. */
.kv-hinweiskasten {
	display: flex;
	flex-direction: column;
	gap: 8px;
	margin-top: 48px;
	padding: var(--kv-karte-pad);
	border-radius: var(--kv-r-klein);
	background: var(--kv-soft);
}

.kv-hinweiskasten span:last-child {
	font-size: 14px;
	line-height: 22px;
	font-weight: 300;
	color: rgba(35, 31, 35, 0.8);
}

/* Ungeprüfter Entwurf — muss auffallen, sonst geht er live. */
.kv-entwurf {
	display: flex;
	flex-direction: column;
	gap: 6px;
	margin-bottom: 40px;
	padding: 16px 20px;
	border-radius: var(--kv-r-klein);
	box-shadow: inset 0 0 0 1px var(--kv-rot);
	background: rgba(140, 29, 24, 0.06);
}

.kv-entwurf strong {
	font-family: var(--kv-mono);
	font-size: 12px;
	line-height: 16px;
	font-weight: 400;
	letter-spacing: 0.75px;
	text-transform: uppercase;
	color: var(--kv-rot);
}

.kv-entwurf span {
	font-size: 15px;
	line-height: 22px;
	color: var(--kv-ink-72);
}

/* =========================================================================
   29. Formular
   ========================================================================= */

.kv-page .kv-formular {
	width: 100%;
	padding-block: var(--kv-abschnitt);
}

.kv-page .kv-formular--soft  { background: var(--kv-soft); }
.kv-page .kv-formular--weiss { background: var(--kv-weiss); }

.kv-formular__karte {
	width: 100%;
	max-width: 1028px;
	margin-inline: auto;
	padding: var(--kv-formkarte-pad);
	border-radius: var(--kv-r-gross);
	background: var(--kv-weiss);
}

.kv-formular--weiss .kv-formular__karte {
	background: var(--kv-soft);
}

.kv-formular__kopf {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 12px;
	margin-bottom: 32px;
}

@media (max-width: 900px) {
	.kv-page .kv-recht__inner {
		flex-direction: column;
		gap: 40px;
	}

	.kv-recht__rand {
		position: static;
		flex-basis: auto;
		max-width: 100%;
	}

	.kv-page .kv-ortsband__inhalt {
		flex-direction: column;
		align-items: flex-start;
		padding: 32px;
	}

	.kv-ortsband__buehne { min-height: 520px; }
}

@media (max-width: 700px) {
	.kv-formular__karte { padding: 24px; }
	.kv-page .kv-recht__text :where(h2) { margin-top: 40px; font-size: 24px; line-height: 32px; }
}

/* --- Impressum: beschriftete Angaben mit Trennlinien ------------------- */

.kv-angaben {
	display: flex;
	flex-direction: column;
	margin: 0;
}

.kv-angabe {
	display: flex;
	flex-direction: column;
	gap: 10px;
	padding-block: 28px;
	border-bottom: 1px solid var(--kv-ink-12);
}

.kv-angabe:first-child { padding-top: 0; }
.kv-angabe:last-child  { border-bottom: 0; }

.kv-page .kv-angabe dt { margin: 0; }

.kv-angabe__werte {
	display: flex;
	flex-direction: column;
	gap: 4px;
	margin: 0;
	/* Größer und dunkler als Fließtext: die Pflichtangaben sollen
	   lesbar sein, nicht dezent. */
	font-size: 18px;
	line-height: 30px;
	font-weight: 400;
	color: var(--kv-ink);
}

/* Rechtsseiten und Kontakt setzen die grosse Ueberschrift. */
.kv-wolkenhero--titel-gross .kv-wolkenhero__titel {
	font-size: 64px;
	line-height: 68px;
	letter-spacing: -1px;
}

/* Ohne Wolke braucht der Kopf weniger Polster — und keine Ausblendung. */
.kv-page .kv-wolkenhero__flaeche:not(.kv-wolke-buehne) {
	padding-block: 100px 64px;
}

@media (max-width: 900px) {
	.kv-wolkenhero--titel-gross .kv-wolkenhero__titel {
		font-size: 40px;
		line-height: 46px;
	}
}

/* -------------------------------------------------------------------------
   30. Deutsche Komposita brechen lassen

   „Beitrittserklärung" und „Datenschutzerklärung" passen bei 40 px Schrift
   nicht in 320 px Viewport — gemessen +14 bzw. +5 px Überbreite. Die
   Antwort ist Silbentrennung, nicht kleinere Schrift: WordPress setzt
   lang="de-DE", damit trennt der Browser nach deutschen Regeln.

   `overflow-wrap` als Rückfall für Browser ohne deutsche Trennmuster —
   dann bricht es hart statt hinauszuragen.
   ------------------------------------------------------------------------- */

.kv-page :where(h1, h2, h3, h4, h5, h6) {
	overflow-wrap: break-word;
}

@media (max-width: 700px) {
	.kv-page :where(h1, h2, h3) {
		hyphens: auto;
		-webkit-hyphens: auto;
	}
}

/* Rechtstexte enthalten lange URLs (Datenschutzhinweise fremder Dienste).
   Ohne Umbruchpunkt ragen sie hinaus — gemessen +40 px bei 320. */
.kv-page .kv-recht__text :where(p, li, td) {
	overflow-wrap: anywhere;
}

/* =========================================================================
   31. Veranstaltungsliste und Filter
   ========================================================================= */

.kv-page .kv-eliste {
	width: 100%;
	background: var(--kv-weiss);
	padding-block: var(--kv-abschnitt);
}

.kv-page .kv-eliste__inner {
	display: flex;
	flex-direction: column;
	gap: 40px;
}

/* Die Filterleiste steht im Entwurf in einem eigenen Abschnitt über der
   Reihe: links die Chips, rechts das Ergebnis, darunter eine Linie. */
.kv-page .kv-eliste-filter {
	width: 100%;
	background: var(--kv-weiss);
	padding-block: 40px 0;
	padding-inline: var(--kv-rand);
}

.kv-filter {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	padding-bottom: 24px;
	border-bottom: 1px solid var(--kv-ink-12);
}

/* Mit Beschriftungen über den Chips (Archiv) beginnen die Spalten oben,
   sonst stünde „Ergebnis" auf Höhe der zweiten Chipreihe. */
.kv-filter:has(.kv-filter__reihe .kv-rubrik) {
	align-items: flex-start;
}

.kv-filter__reihen {
	display: flex;
	flex: 1 1 480px;
	min-width: 0;
	flex-direction: column;
	gap: 16px;
}

.kv-filter__reihe {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 8px;
}

.kv-filter__chips {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.kv-filter__ergebnis {
	display: flex;
	flex: 0 0 auto;
	flex-direction: column;
	align-items: flex-end;
	gap: 8px;
}

.kv-page .kv-chip {
	display: inline-flex;
	align-items: center;
	height: 36px;
	padding: 0 14px;
	border-radius: var(--kv-r-mini);
	background: rgba(35, 31, 35, 0.06);
	font-family: var(--kv-mono);
	font-size: 12px;
	line-height: 20px;
	font-weight: 400;
	letter-spacing: 0.75px;
	text-transform: uppercase;
	color: var(--kv-ink);
	white-space: nowrap;
	transition: background var(--kv-t-flaeche), color var(--kv-t-flaeche),
	            box-shadow var(--kv-t-flaeche);
}

.kv-page .kv-chip:hover {
	background: rgba(35, 31, 35, 0);
	box-shadow: inset 0 0 0 1px rgba(35, 31, 35, 0.4);
	color: var(--kv-ink);
}

.kv-page .kv-chip--aktiv,
.kv-page .kv-chip--aktiv:hover {
	background: var(--kv-ink);
	box-shadow: none;
	color: var(--kv-soft);
}

.kv-filter__zaehler {
	font-family: var(--kv-label);
	font-size: 12px;
	line-height: 16px;
	letter-spacing: 1px;
	text-transform: uppercase;
	color: var(--kv-ink-50);
}

/* Im Archiv ist die Zahl die Aussage, nicht die Beschriftung. */
.kv-page .kv-filter__zaehler--gross {
	font-family: var(--kv-display);
	font-size: 24px;
	line-height: 32px;
	letter-spacing: 0;
	text-transform: none;
	color: var(--kv-ink);
}

/* --- Karte ------------------------------------------------------------- */

.kv-eliste__raster {
	gap: 48px 16px;
}

.kv-ekarte {
	display: flex;
	flex-direction: column;
	gap: 24px;
}

.kv-ekarte[hidden] {
	display: none;
}

.kv-page .kv-ekarte__bild {
	display: block;
	height: 440px;
	overflow: hidden;
	border-radius: var(--kv-r-gross);
	background-color: var(--kv-soft);
	transition: filter var(--kv-t-bild), box-shadow var(--kv-t-flaeche);
}

/* Das Motiv der Terminzeile — aus demselben Grund ein <img>: nur so
   wählt der Browser die passende Größe. Der Kasten gibt Höhe und Radius
   vor, das Bild füllt ihn. */
.kv-page .kv-ekarte__motiv {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: inherit;
}

/* Entsaettigt, auf Hover farbig — eine leise Andeutung von Vergangenheit. */
[data-entsaettigt="1"] .kv-ekarte__bild {
	filter: grayscale(0.15);
}

[data-entsaettigt="1"] .kv-ekarte:hover .kv-ekarte__bild {
	filter: grayscale(0);
}

.kv-ekarte:hover .kv-ekarte__bild {
	box-shadow: var(--kv-schatten-bild);
}

.kv-ekarte__text {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.kv-ekarte__aktion,
.kv-ekarte__meta { align-self: stretch; }

.kv-page .kv-ekarte__aktion .kv-btn { align-self: flex-start; }

.kv-ekarte__meta {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 16px;
}

/* Der Termin auf der Karte ist Fließschrift, nicht Mono: er steht neben
   dem Kategorie-Tag, und zwei Monoschriften nebeneinander lesen sich wie
   eine Tabelle. */
.kv-ekarte__datum {
	font-size: 13px;
	line-height: 20px;
	font-weight: 300;
	color: var(--kv-ink-64);
}

/* Kartentitel ohne negative Laufweite: in 24 px wirkt sie gedrängt, und
   der Entwurf setzt sie hier auch nicht. */
.kv-ekarte__titel {
	letter-spacing: 0;
	text-wrap: pretty;
}

.kv-page .kv-ekarte__titel a {
	color: var(--kv-ink);
}

.kv-page .kv-ekarte__titel a:hover {
	color: var(--kv-rot);
}

/* 16 px Zwischenraum plus 8 px ergeben die 24 des Entwurfs — der Button
   sitzt eine Stufe weiter unten als die Zeilen darüber. */
.kv-ekarte__aktion {
	display: flex;
	margin-top: 8px;
}

/* Die kompakte Karte: nur Tag, Datum und Titel — auf der Detailseite
   unter „Weitere Veranstaltungen". */
.kv-page .kv-ekarte--kompakt .kv-ekarte__bild { height: 380px; }

/* Die Archivkarte: flacheres Bild, engere Zeilen, kein Button. */
.kv-ekarte--archiv { gap: 20px; }

.kv-page .kv-ekarte--archiv .kv-ekarte__bild { height: 320px; }

.kv-ekarte--archiv .kv-ekarte__text { gap: 12px; }

/* --- Zeilenrhythmus: 1 bis 3 Karten je Zeile ---------------------------

   Sechs Spalten als Grundraster, weil sich daraus SOWOHL Drittel (2)
   als auch Hälften (3) und die volle Breite (6) exakt aufgehen — mit
   demselben Zwischenraum wie im festen Dreierraster. Eine Drittelkarte
   ist deshalb genau so breit wie vorher, das Bild des Entwurfs bleibt
   unangetastet.

   Die Breitenklasse steht an der Karte, gerechnet in PHP (und nach dem
   Filtern in `kv.js`) — CSS allein kann nicht zählen, wie viele Karten
   ein Filter übrig lässt.
   --------------------------------------------------------------------- */

.kv-eliste__raster--rhythmus {
	grid-template-columns: repeat(6, minmax(0, 1fr));
}

.kv-eliste__raster--rhythmus .kv-ekarte             { grid-column: span 2; }
.kv-eliste__raster--rhythmus .kv-ekarte--drittel    { grid-column: span 2; }
.kv-eliste__raster--rhythmus .kv-ekarte--halb       { grid-column: span 3; }
.kv-eliste__raster--rhythmus .kv-ekarte--voll       { grid-column: span 6; }

/* Breitere Karte, höheres Bild: bei gleicher Höhe würde aus dem quadratischen
   Motiv des Entwurfs ein Briefkastenschlitz. Die Verhältnisse sind je
   Kartenart gesetzt, weil Archiv- und Kompaktkarte flacher beginnen. */
/* --- Die Terminliste als Bildkachel -----------------------------------

   Kundenwunsch (08.09.2026): die Termine sollen aussehen wie die Kacheln
   auf der Startseite. Die Karte trägt dafür BEIDE Klassen — `.kv-kachel`
   für das Aussehen, `.kv-ekarte` für Filterung, Zeilenrechnung und
   Rasterspalten. Hier steht nur, was aus dem Zusammentreffen der beiden
   folgt:

   - `.kv-ekarte` bringt `gap: 24px` mit; die Kachel verteilt Kopf und
     Fuß mit `space-between`, ein Gap dazwischen wäre eine zweite
     Rechnung.
   - Die Höhe: das Dreierraster übernimmt die 560 px der Startseite.
     Breitere Karten aus dem Zeilenrhythmus bekommen ein Verhältnis
     statt einer festen Höhe — sonst wäre die volle Breite ein Band mit
     einem Titel darin. Dieselben Werte wie an der Terminzeile
     (`--kv-ekarte-halb/voll`), damit beide Formen gleich hoch bauen.
   - Die Trennlinie des Rhythmus-Rasters gilt für die Zeile, nicht für
     die Kachel: Kacheln stehen als eigene Flächen da, eine Linie
     zwischen ihnen wäre ein Strich im Nichts. */
.kv-page .kv-ekarte--kachel {
	gap: 0;
	min-height: 560px;
	min-width: 0;
}

/* KEIN `aspect-ratio` an der Kachel — und das ist die Lehre aus zwei
   Fehlversuchen:

   Die Terminzeile rechnet für breitere Karten ein Verhältnis (3/2 halb,
   12/5 voll), weil sonst aus dem quadratischen Motiv ein
   Briefkastenschlitz würde. An der Kachel klingt dasselbe naheliegend
   und geht schief: ein Kasten mit `aspect-ratio` wird in der Achse, die
   das Verhältnis bestimmt, NICHT mehr auf die Rasterspalte gestreckt.
   Mit `min-height: 560px` leitet der Browser daraus die Breite ab —
   560 bei 3/2 sind 840 px. Die halbe Karte wollte 840 statt 680, und die
   Zeile trug 1696 px in einem 1376 px breiten Raster. `min-width: 0`
   half nicht: es begrenzt die Mindestbreite, nicht die vom Verhältnis
   abgeleitete.

   Gemeldet hat es `pruefung/rhythmus.js` mit seiner geometrischen Prüfung
   („2 Karten füllen 1696.0 von 1376.0px") — im Bild war es kaum zu
   sehen, weil der Abschnitt den Überhang abschneidet. Ohne diesen Test
   wäre es durchgegangen.

   Gebraucht wird das Verhältnis hier ohnehin nicht: die Kachel trägt
   ihren Text selbst, 560 px sind auch über die volle Breite ein ruhiges
   Bild (1376 × 560 ≈ 2,46:1 — fast genau die 12/5 der Terminzeile). Alle
   Kacheln sind damit gleich hoch, wie auf der Startseite. */

/* Die Trennlinie des Rhythmus-Rasters gilt für die Zeile, nicht für die
   Kachel — und ihr `padding-top: 32px` würde das Innenpolster der Kachel
   überschreiben. Beides zurück. */
.kv-page .kv-eliste__raster .kv-ekarte--kachel:not([hidden]) ~ .kv-ekarte--kachel:not([hidden]) {
	padding-top: var(--kv-karte-pad);
	border-top: 0;
}

/* Dieselbe Höhe wie die Kacheln der Startseite: dort gilt 420 px ab
   **700**, nicht ab 900 (nachgesehen, nicht geraten — die Regel steht in
   der 700er-Stufe). Nötig ist die Wiederholung, weil `.kv-kachel` dort
   gegen unser `.kv-page .kv-ekarte--kachel` verliert: eine Klasse mehr.
   Gemessen vorher: 328 × 560 in der Liste gegen 328 × 420 auf der
   Startseite. */
@media (max-width: 700px) {
	.kv-page .kv-ekarte--kachel {
		min-height: 420px;
	}

}



.kv-ekarte           { --kv-ekarte-halb: 3 / 2;  --kv-ekarte-voll: 12 / 5; }
.kv-ekarte--archiv   { --kv-ekarte-halb: 2 / 1;  --kv-ekarte-voll: 16 / 5; }
.kv-ekarte--kompakt  { --kv-ekarte-halb: 7 / 4;  --kv-ekarte-voll: 14 / 5; }

.kv-page .kv-ekarte--halb .kv-ekarte__bild,
.kv-page .kv-ekarte--voll .kv-ekarte__bild {
	height: auto;
}

.kv-page .kv-ekarte--halb .kv-ekarte__bild { aspect-ratio: var(--kv-ekarte-halb); }
.kv-page .kv-ekarte--voll .kv-ekarte__bild { aspect-ratio: var(--kv-ekarte-voll); }

/* Der Text folgt der Karte, nicht der Bildbreite: über 1376 px gelesen
   wäre eine Zeile Fließtext unlesbar. */
.kv-ekarte--voll .kv-ekarte__text { max-width: 680px; }

/* --- Letzte Zeile füllen ----------------------------------------------

   Flexbox statt Grid: eine ausgeblendete Karte fällt einfach heraus und
   die übrigen teilen die Zeile neu — dafür braucht es kein JavaScript,
   also stimmt es auch bei einem gefilterten Stand ohne Skript.
   --------------------------------------------------------------------- */

.kv-eliste__raster--fuellen {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: 48px 16px;
}

.kv-eliste__raster--fuellen > .kv-ekarte {
	flex: 1 1 calc((100% - 32px) / 3);
	min-width: 0;
}

.kv-eliste__raster--fuellen--s2 > .kv-ekarte {
	flex-basis: calc((100% - 16px) / 2);
}

/* Kopfzeile über einer Reihe: Überschrift links, Verweis rechts. */
.kv-page .kv-eliste__kopf .kv-link {
	font-size: 14px;
	line-height: 16px;
}

.kv-eliste__kopf {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 24px;
	padding-bottom: 24px;
	border-bottom: 1px solid var(--kv-ink-12);
}

.kv-eliste__leer {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 12px;
	padding: 80px 24px;
	border-radius: var(--kv-r-gross);
	background: var(--kv-soft);
	text-align: center;
}

.kv-eliste__leer[hidden] {
	display: none;
}

.kv-eliste__leer .kv-text {
	max-width: 460px;
}

/* =========================================================================
   32. Veranstaltung — Kopfbild
   ========================================================================= */

/* Der Kopf endet buendig: der Abschnitt darunter bringt sein eigenes
   Polster mit (64 px), zusammen waeren es sonst 96. */
.kv-page .kv-ekopf {
	width: 100%;
	background: var(--kv-weiss);
	padding-block: var(--kv-rand) 0;
}

.kv-krume {
	margin-bottom: 24px;
}

.kv-krume ol {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.kv-krume li {
	display: flex;
	align-items: center;
	gap: 8px;
	/* Inconsolata mit 1 px Laufweite — die Brotkrume ist eine
	   Rubrik-Beschriftung, kein Eyebrow. */
	font-family: var(--kv-label);
	font-size: 12px;
	line-height: 16px;
	font-weight: 400;
	letter-spacing: 1px;
	text-transform: uppercase;
	color: var(--kv-ink-50);
}

.kv-krume li + li::before {
	content: '/';
	color: var(--kv-ink-12);
}

.kv-page .kv-krume a {
	color: var(--kv-ink-50);
}

.kv-page .kv-krume a:hover {
	color: var(--kv-rot);
}

.kv-ekopf__buehne {
	position: relative;
	display: flex;
	align-items: flex-end;
	min-height: 560px;
	border-radius: var(--kv-r-gross);
	overflow: hidden;
	isolation: isolate;
}

/* `<picture>` ist nur eine Hülle für die Motivwahl (zweites Bild für
   schmale Flächen, siehe `kv_picture()`). Als Inline-Element hätte es
   keine Höhe, und ein `height: 100%` am `<img>` darin bezöge sich auf
   nichts — das Motiv wäre auf seine Eigenhöhe zusammengefallen.
   `display: contents` nimmt die Hülle aus dem Layout heraus: das `<img>`
   verhält sich wie ein direktes Kind. */
.kv-page picture {
	display: contents;
}

.kv-ekopf__motiv {
	position: absolute;
	inset: 0;
	z-index: 0;
}

.kv-ekopf__motiv img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.kv-ekopf__buehne--mittig .kv-ekopf__motiv img { object-position: center center; }
.kv-ekopf__buehne--oben   .kv-ekopf__motiv img { object-position: center top; }
.kv-ekopf__buehne--unten  .kv-ekopf__motiv img { object-position: center bottom; }

.kv-ekopf__ton,
.kv-ekopf__unten {
	position: absolute;
	z-index: 1;
	pointer-events: none;
}

.kv-ekopf__ton { inset: 0; background: rgba(35, 31, 35, 0.3); }

.kv-ekopf__unten {
	left: 0;
	right: 0;
	bottom: 0;
	height: 60%;
	background: linear-gradient(0deg, rgba(35, 31, 35, 0.82) 0%, rgba(35, 31, 35, 0) 100%);
}

.kv-ekopf__inhalt {
	position: relative;
	z-index: 2;
	display: flex;
	flex-direction: column;
	gap: 20px;
	padding: var(--kv-bildbox-pad);
	max-width: 984px;
}

.kv-ekopf__tags {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 12px;
}

.kv-ekopf__datum {
	font-family: var(--kv-mono);
	font-size: 12px;
	line-height: 16px;
	font-weight: 400;
	letter-spacing: 0.75px;
	color: var(--kv-soft);
}

/* =========================================================================
   33. Veranstaltung — Inhalt und Infospalte
   ========================================================================= */

.kv-page .kv-edetail {
	width: 100%;
	background: var(--kv-weiss);
	padding-block: 64px var(--kv-abschnitt);
}

.kv-page .kv-edetail__inner {
	display: flex;
	flex-direction: row;
	gap: 80px;
	align-items: flex-start;
	justify-content: space-between;
}

.kv-edetail__text {
	flex: 1 1 520px;
	min-width: 0;
	max-width: 984px;
	display: flex;
	flex-direction: column;
	gap: 28px;
}

.kv-edetail__text .kv-lead--gross {
	max-width: 820px;
	color: var(--kv-ink);
}

/* Zwei Textspalten wie im Entwurf. break-inside verhindert, dass ein
   Absatz mitten im Satz die Spalte wechselt. */
.kv-edetail__fliess--zwei {
	column-count: 2;
	column-gap: 48px;
}

.kv-page .kv-edetail__fliess :where(p) {
	font-size: 16px;
	line-height: 26px;
	font-weight: 300;
	color: var(--kv-ink-72);
	margin-bottom: 20px;
	break-inside: avoid-column;
	text-wrap: pretty;
}

/* Importierter Text darf das Layout nicht sprengen.
 *
 * Die 99 Beschreibungen kommen aus acht Jahren The Events Calendar. In einer
 * stand ein base64-Block eines Page-Builders — eine Zeichenkette ohne
 * Umbruchstelle, 3944 px breit, und die ganze Seite scrollte seitwärts.
 * Eine Spalte, die nur mit sauberem Inhalt hält, hält nicht. */
.kv-page .kv-edetail__fliess,
.kv-page .kv-edetail__text .kv-lead {
	overflow-wrap: anywhere;
}

.kv-page .kv-edetail__fliess :where(img, iframe, video, table) {
	max-width: 100%;
	height: auto;
}

.kv-page .kv-edetail__fliess table {
	display: block;
	overflow-x: auto;
}

.kv-edetail__rand {
	position: sticky;
	top: calc(var(--kv-kopf-hoehe) + 32px);
	display: flex;
	flex: 1 1 340px;
	min-width: 0;
	flex-direction: column;
	gap: 16px;
	max-width: 448px;
}

.kv-infokarte {
	display: flex;
	flex-direction: column;
	gap: 28px;
	padding: 32px;
	border-radius: var(--kv-r-gross);
	background: var(--kv-soft);
}

.kv-infokarte__datum {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.kv-infokarte__tag {
	display: flex;
	align-items: baseline;
	gap: 10px;
}

.kv-infokarte__zahl {
	font-family: var(--kv-display);
	font-size: 64px;
	line-height: 64px;
	font-weight: 400;
	letter-spacing: -2px;
	color: var(--kv-ink);
}

/* Der Strich zwischen zwei Tagen eines Zeitraums. Etwas Luft links und
   rechts, in em — dann wächst sie mit der Zahl mit. */
.kv-infokarte__strich {
	display: inline-block;
	margin: 0 0.06em;
}

.kv-infokarte__monat {
	display: flex;
	flex-direction: column;
	font-size: 16px;
	line-height: 20px;
	color: var(--kv-ink);
}

.kv-infokarte__jahr {
	font-family: var(--kv-mono);
	font-size: 12px;
	font-weight: 400;
	letter-spacing: 1.5px;
	color: var(--kv-ink-64);
}

.kv-infokarte__meta {
	display: flex;
	flex-direction: column;
	gap: 14px;
	margin: 0;
}

.kv-infokarte__meta > div {
	display: flex;
	justify-content: space-between;
	gap: 16px;
	/* 12 px bis zur Trennlinie, 14 px danach — im Entwurf nachgemessen. */
	padding-bottom: 12px;
	border-bottom: 1px solid var(--kv-ink-12);
}

.kv-infokarte__meta > div:last-child {
	padding-bottom: 0;
	border-bottom: 0;
}

.kv-page .kv-infokarte__meta dt {
	margin: 0;
	font-size: 14px;
	line-height: 20px;
	font-weight: 300;
	color: var(--kv-ink-64);
}

.kv-page .kv-infokarte__meta dd {
	margin: 0;
	font-size: 14px;
	line-height: 20px;
	color: var(--kv-ink);
	text-align: right;
}

.kv-infokarte__tickets {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.kv-infokarte__knoepfe {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.kv-page .kv-infokarte__knoepfe .kv-btn {
	width: 100%;
}

/* Ohne align-items: flex-start — die Zeilen füllen die Karte, nur der
   Verweis darunter sitzt links. */
.kv-mitgliedkarte {
	display: flex;
	flex-direction: column;
	gap: 12px;
	padding: var(--kv-karte-pad);
	border-radius: var(--kv-r-klein);
	background: var(--kv-rot);
	color: var(--kv-soft);
}

/* Fließschrift in 500, keine Displayzeile: die Karte ist ein Hinweis,
   keine Überschrift. */
.kv-mitgliedkarte__titel {
	font-family: var(--kv-text);
	font-size: 16px;
	line-height: 24px;
	font-weight: 500;
	color: var(--kv-soft);
}

.kv-page .kv-mitgliedkarte .kv-link { align-self: flex-start; }

.kv-mitgliedkarte .kv-klein {
	color: rgba(247, 246, 245, 0.8);
}

/* --- Bold Tickets: nur die Variablen setzen, nichts überschreiben ------
   Das Plugin-Stylesheet legt bewusst fast nichts fest und leitet alle
   Töne aus currentColor ab. Zwölf Zeilen statt 374 (siehe DOKUMENTATION
   von Bold Tickets, §1 „Optik"). */

.kv-page .bold-tickets,
.kv-page .bold-event-meta {
	--bold-accent: var(--kv-rot);
	--bold-line: var(--kv-ink-12);
	--bold-soft: var(--kv-weiss);
	--bold-muted: var(--kv-ink-64);
	--bold-focus: var(--kv-rot);
	--bold-radius: var(--kv-r-mini);
	--bold-gap: 12px;
	--bold-gap-lg: 20px;

	font-family: var(--kv-text);
	font-size: 15px;
	line-height: 22px;
}

/* Die Angaben-Seite (/ticket-angaben/) ist eine ganze Seite, keine Karte in
   der Seitenspalte — dort sind 12/20 px zu eng. Zwei Klassen, damit es die
   Regel darüber schlägt; das Plugin bringt dieselben Werte als Vorgabe mit,
   aber unsere Regel oben ist spezifischer und würde sonst gewinnen. */
.kv-page .bold-tickets.bold-tickets--data {
	--bold-gap: 20px;
	--bold-gap-lg: 36px;
}

/* Die Angaben-Seite hat keine eigene Bricks-Vorlage: WordPress gibt Titel und
   Inhalt direkt aus, und die Überschrift klebte am Header (gemessen 0 px).
   Die Klasse setzt das Plugin selbst — so hängt die Regel nicht an einer
   Seiten-ID, die sich beim Neuanlegen ändert. */
body.bold-tickets-details-page article {
	padding-top: 56px;
	padding-bottom: 24px;
}

/* Die Ticketzeile des Entwurfs: Name über Preis, rechts das Mengenfeld.
   Das Plugin liefert eine Tabelle (Name | Preis | Menge) — dieselben drei
   Zellen, per Grid neu angeordnet. So bleibt das Markup des Plugins
   unangetastet und ein Update ändert daran nichts. */
.kv-page .kv-infokarte__tickets .bold-tickets__table,
.kv-page .kv-infokarte__tickets .bold-tickets__table tbody { display: block; }

.kv-page .kv-infokarte__tickets .bold-tickets__row {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	grid-template-areas:
		"name menge"
		"preis menge";
	align-items: center;
	column-gap: 12px;
	padding: 0;
	border: 0;
}

.kv-page .kv-infokarte__tickets .bold-tickets__name {
	grid-area: name;
	padding: 0;
	border: 0;
	font-size: 15px;
	line-height: 20px;
	font-weight: 400;
	text-align: left;
	color: var(--kv-ink);
}

.kv-page .kv-infokarte__tickets .bold-tickets__price {
	grid-area: preis;
	padding: 0;
	border: 0;
	font-size: 13px;
	line-height: 18px;
	font-weight: 300;
	text-align: left;
	color: var(--kv-ink-64);
}

.kv-page .kv-infokarte__tickets .bold-tickets__qty {
	grid-area: menge;
	padding: 0;
	border: 0;
}

/* Die Mengenwahl: im Entwurf eine Auswahlliste mit Chevron, kein
   Zahlenfeld mit Pfeilchen. Das Element baut das <input type=number> des
   Plugins in ein <select> um; hier steht nur, wie es aussieht. */
.kv-page .kv-infokarte__tickets .bold-tickets__qty input,
.kv-page .kv-infokarte__tickets .bold-tickets__qty select {
	height: 40px;
	border: 0;
	border-radius: var(--kv-r-mini);
	background: #EAE9E1;
	padding: 0 12px 0 14px;
	font-family: var(--kv-text);
	font-size: 15px;
	line-height: 20px;
	color: var(--kv-ink);
	cursor: pointer;
}

.kv-page .kv-infokarte__tickets .bold-tickets__qty input { width: 72px; }

.kv-page .kv-infokarte__tickets .bold-tickets__qty select {
	appearance: none;
	-webkit-appearance: none;
	padding-right: 38px;
	background-image: url("../img/icon-chevron-down.svg");
	background-repeat: no-repeat;
	background-position: right 14px center;
	background-size: 12px;
	min-width: 66px;
}

/* Der Fokusring hier in der Haustinte, nicht in Rot.
   -----------------------------------------------------------------------
   Chrome behält `:focus-visible` an einer Auswahlliste, nachdem man mit
   der MAUS etwas gewählt hat — der Ring bleibt also sichtbar stehen. In
   Rot liest sich das an einem Formularfeld wie eine Fehlermeldung, und
   genau so wurde es gemeldet.

   Weglassen ist keine Option: ohne sichtbaren Fokus findet sich niemand
   mit der Tastatur zurecht (§7.2). Also bleibt der Ring, nur in der
   Tinte des Hauses — „hier stehe ich" statt „hier ist etwas falsch". */
.kv-page .kv-infokarte__tickets .bold-tickets__qty select:focus-visible,
.kv-page .kv-infokarte__tickets .bold-tickets__qty input:focus-visible {
	outline: 2px solid var(--kv-ink);
	outline-offset: 2px;
}

/* Auch das Plugin färbt seinen Fokus über eine Variable ein. */
.kv-page .kv-infokarte__tickets .bold-tickets { --bold-focus: var(--kv-ink); }

/* Die Mengenspalte hat eine FESTE Breite.
   -----------------------------------------------------------------------
   Vorher stand dort `auto`, und ein auto-Raster folgt dem Inhalt: eine
   Ticketart, die zweistellige Mengen erlaubt, macht ihr Auswahlfeld
   13 px breiter (die Eigenbreite eines Selects richtet sich nach dem
   längsten Eintrag). Damit stand eine von drei Zeilen versetzt.

   78 px, weil zwei Ziffern plus Pfeil hineinpassen müssen. */
.kv-page .kv-infokarte__tickets .bold-tickets__row {
	grid-template-columns: minmax(0, 1fr) 78px;
}

/* Die Zelle braucht eine ausdrückliche Breite.
   -----------------------------------------------------------------------
   Sie ist ein `<td>` und streckt sich in ihrer Rasterspalte NICHT — sie
   blieb bei 0,77 px, gemessen und durchprobiert (`display: block`,
   `justify-self: stretch`, Tabelle auf `block`: alles ohne Wirkung). Die
   Auswahlliste ragte einfach aus der Zelle heraus. Solange die Spalte
   `auto` war, hing ihre Position damit an der Eigenbreite des Feldes —
   und die richtet sich nach dem längsten Eintrag: eine Ticketart mit
   zweistelliger Höchstmenge stand 13 px versetzt.

   Mit 78 px an Spalte UND Zelle sitzen alle Felder auf derselben Kante,
   und zwei Ziffern plus Pfeil passen hinein. */
.kv-page .kv-infokarte__tickets .bold-tickets__qty {
	width: 78px;
}

.kv-page .kv-infokarte__tickets .bold-tickets__qty select {
	width: 100%;
	min-width: 0;
}

/* Zwischen den Zeilen 16 px wie im Entwurf, kein Kasten drumherum. */
.kv-page .kv-infokarte__tickets .bold-tickets__row + .bold-tickets__row {
	margin-top: 16px;
}

.kv-page .kv-infokarte__tickets .bold-tickets__card {
	padding: 0;
	border: 0;
	background: transparent;
	box-shadow: none;
}

/* Der Kaufknopf ist unser Primärknopf — bis auf die Breite.
   Bold Tickets zeichnet ihn in `:where(.bold-tickets__submit)`, also mit
   Spezifität 0: Radius `calc(var(--bold-radius) / 2)` = 4 statt 8 px,
   `font-weight: 600` und Polster in em, was 46 px Höhe ergibt. Neben
   „Zum Kalender hinzufügen" (44 px, Radius 8, Gewicht 400) sah er nach
   einem anderen Bauteil aus — gesehen vom Kunden am 08.09.2026, nicht
   vom Messplatz: `geometrie.js` vergleicht Typografie über den Text und
   kennt die Rundung nicht.

   Angeglichen wird hier und nicht über `--bold-radius`: die Variable
   trägt schon die 8 px, das Halbieren steht in der Regel des Plugins. */
.kv-page .kv-infokarte__tickets .bold-tickets__submit {
	box-sizing: border-box;
	width: 100%;
	height: 44px;
	padding: 12px 18px;
	border-radius: var(--kv-r-mini);
	font-family: var(--kv-text);
	font-size: 16px;
	line-height: 20px;
	font-weight: 400;
}

.kv-page .kv-infokarte__tickets .bold-tickets__hint {
	/* 16 px unter dem Button, im Entwurf nachgemessen. Ohne den Abstand
	   klebte der Hinweis an der Buttonkante. */
	margin-top: 16px;
	font-size: 12px;
	line-height: 18px;
	font-weight: 300;
	color: var(--kv-ink-64);
}

/* Der Videoplatzhalter des Entwurfs ist schraffiert, nicht leer grau. */
@media (max-width: 1000px) {
	.kv-page .kv-edetail__inner {
		flex-direction: column;
		gap: 48px;
	}

	.kv-edetail__rand {
		position: static;
		flex-basis: auto;
		max-width: 100%;
	}

	.kv-edetail__fliess--zwei { column-count: 1; }
}

@media (max-width: 900px) {
	.kv-ekopf__buehne { min-height: 440px; }
	.kv-ekopf__inhalt { padding: 32px; }
	.kv-page .kv-ekarte__bild { height: 320px; }
}

@media (max-width: 700px) {
	.kv-infokarte { padding: 24px; }
	.kv-infokarte__zahl { font-size: 52px; line-height: 52px; }
	.kv-page .kv-ekarte__bild { height: 260px; }
	.kv-eliste__leer { padding: 48px 20px; }
}

/* Der Link in der Mitgliederkarte ist kleiner als der übrige Textlink:
   14/16 statt 16/24 — die Karte soll nicht mit der Ticketauswahl
   konkurrieren. */
.kv-page .kv-mitgliedkarte .kv-link {
	font-size: 14px;
	line-height: 16px;
}

/* -------------------------------------------------------------------------
   34. Polster-Stufen

   Gegenstück zu kv_polster_controls(): das vertikale Polster eines
   Abschnitts ist im Panel wählbar, weil der Entwurf es nicht überall
   gleich setzt.

   MIT !important, und das ist hier kein Notnagel: eine Hilfsklasse muss
   den Komponentenwert per Definition schlagen. Ohne sie verlor
   `.kv-po-80` gegen `.kv-wolkenhero:not(.kv-wolke-buehne)` — die
   Verneinung zählt in der Spezifität mit, und die Einstellung aus dem
   Panel blieb wirkungslos.
   Mit .kv-page davor, damit sie die Sektionsregeln schlagen — die stehen
   weiter oben in dieser Datei und haben dieselbe Spezifität.
   ------------------------------------------------------------------------- */

.kv-page .kv-po-0 { padding-top: 0px !important; }
.kv-page .kv-pu-0 { padding-bottom: 0px !important; }
.kv-page .kv-po-24 { padding-top: 24px !important; }
.kv-page .kv-pu-24 { padding-bottom: 24px !important; }
.kv-page .kv-po-32 { padding-top: 32px !important; }
.kv-page .kv-pu-32 { padding-bottom: 32px !important; }
.kv-page .kv-po-40 { padding-top: 40px !important; }
.kv-page .kv-pu-40 { padding-bottom: 40px !important; }
.kv-page .kv-po-48 { padding-top: 48px !important; }
.kv-page .kv-pu-48 { padding-bottom: 48px !important; }
.kv-page .kv-po-64 { padding-top: 64px !important; }
.kv-page .kv-pu-64 { padding-bottom: 64px !important; }
.kv-page .kv-po-80 { padding-top: 80px !important; }
.kv-page .kv-pu-80 { padding-bottom: 80px !important; }
.kv-page .kv-po-96 { padding-top: 96px !important; }
.kv-page .kv-pu-96 { padding-bottom: 96px !important; }
.kv-page .kv-po-120 { padding-top: 120px !important; }
.kv-page .kv-pu-120 { padding-bottom: 120px !important; }
.kv-page .kv-po-140 { padding-top: 140px !important; }
.kv-page .kv-po-200 { padding-top: 200px !important; }
.kv-page .kv-pu-140 { padding-bottom: 140px !important; }
.kv-page .kv-pu-200 { padding-bottom: 200px !important; }

/* Breite des Textblocks im Wolken-Hero — im Entwurf je Seite anders. */
.kv-page .kv-wolkenhero--b680  .kv-wolkenhero__inhalt { max-width: 680px; }
.kv-page .kv-wolkenhero--b760  .kv-wolkenhero__inhalt { max-width: 760px; }
.kv-page .kv-wolkenhero--b1028 .kv-wolkenhero__inhalt { max-width: 1028px; }
.kv-page .kv-wolkenhero--b1512 .kv-wolkenhero__inhalt { max-width: var(--kv-breite); }

/* Der Zwischenraum im Kopf ist nicht überall gleich: 32 auf „Der Verein",
   „Mitglied werden", „Kinderkunsttage" und „Events", 24 auf „Archiv" und
   „Kontakt", 20 über die volle Breite (Rechtsseiten). */
.kv-page .kv-wolkenhero--zeilen-24 .kv-wolkenhero__inhalt { gap: 24px; }
.kv-page .kv-wolkenhero--zeilen-20 .kv-wolkenhero__inhalt { gap: 20px; }

/* Über die volle Breite steht der Kopf linksbündig und enger gesetzt —
   so machen es die Rechtsseiten im Entwurf. Ein zentrierter Titel über
   1512 px hätte keinen Bezug mehr zum Text darunter. */
.kv-page .kv-wolkenhero--b1512 .kv-wolkenhero__inhalt {
	align-items: flex-start;
	gap: 20px;
	text-align: left;
}

/* „Kultur:Hören" bei 64 px passt nicht in 320 px Fenster — und der
   Doppelpunkt gibt der Silbentrennung keinen Ansatz. Gemessen +11 px. */
@media (max-width: 700px) {
	.kv-h1--seite {
		font-size: 40px;
		line-height: 46px;
	}
}

/* =========================================================================
   35. Kartenraster (frei befüllbar)
   Gleiche Kachel wie die Vorteile, ohne Bindung an einen Inhaltstyp.
   ========================================================================= */

.kv-page .kv-karten {
	width: 100%;
	padding-block: var(--kv-abschnitt);
}

.kv-page .kv-karten--weiss  { background: var(--kv-weiss); }
.kv-page .kv-karten--soft   { background: var(--kv-soft); }
.kv-page .kv-karten--footer { background: var(--kv-footer); }

.kv-page .kv-karten__inner {
	display: flex;
	flex-direction: column;
	gap: 40px;
}

/* Überschriften und Fließtext füllen ihre Spalte.
 *
 * Meine Textspalten stehen auf `align-items: flex-start`, damit die
 * Eyebrow-Kapsel nur so breit wird wie ihr Wort. Das trifft aber auch die
 * Überschrift: sie war so breit wie ihr Text, und `text-wrap: balance`
 * brach an anderer Stelle als im Entwurf. Der Entwurf lässt alles füllen
 * und setzt nur die Kapsel und die Buttons auf flex-start.
 *
 * Also: Kapsel bleibt schmal, Text spannt. Zentrierte Köpfe sind
 * ausgenommen — dort ist die Mitte der Zweck. */
.kv-page :where(
	.kv-karten__kopf,
	.kv-kacheln__kopf,
	.kv-team__kopf,
	.kv-formular__kopf,
	.kv-hband__text,
	.kv-mt__text,
	.kv-fokus__text,
	.kv-recht__text
):not(.kv-karten__kopf--mitte) > :where(h1, h2, h3, p, .kv-lead, .kv-text, .kv-h1, .kv-h2, .kv-h3) {
	align-self: stretch;
}

.kv-karten__kopf {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 16px;
}

.kv-karten__kopf .kv-lead { max-width: 752px; }

/* Mittig gesetzter Kopf — im Entwurf ueber den Faechern der
   Kinderkunsttage. Schmaler, damit die Zeilen nicht auseinanderlaufen. */
.kv-karten__kopf--mitte {
	align-items: center;
	max-width: 760px;
	margin-inline: auto;
	gap: 24px;
	text-align: center;
}

.kv-karten__kopf--mitte .kv-lead { max-width: 100%; }

/* Die Kartenreihen des Entwurfs sind KEIN starres Raster: die Karten
   haben eine Mindestbreite und brechen um, wenn der Platz nicht reicht.
   Bei 1280 px stehen deshalb drei nebeneinander, bei 1440 vier — mit
   `repeat(4, 1fr)` waeren es immer vier und ab 1024 zu schmal. */
.kv-karten__raster,
.kv-kontakt__raster {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	gap: 16px;
}

/* KEINE Deckelung — die Karte wächst, wie im Entwurf.
   -----------------------------------------------------------------------
   Hier stand `max-width: max(360px, …)`. Damit blieb die letzte Karte
   einer unvollständigen Reihe schmal: auf der Kontaktseite war
   „Facebook" 360 px breit, im Referenzdokument **1028** (bei 1024 px
   Fenster: 360 gegen 960). Vom Kunden gemeldet („Der Kontakt sieht auch
   noch anders aus, als im Entwurf") — und es ist derselbe Fehler wie bei
   den Vorteilen auf „Mitglied werden", nur zwei Stellen weiter.

   Alles andere stimmte auf den Pixel: Polster 24, Gap 32, Mindesthöhe
   220, Radius 12, Weiß, `space-between`. */
.kv-karten__raster > *,
.kv-kontakt__raster > * {
	flex: 1 1 300px;
	min-width: 0;
}

/* Eine einzelne Karte nimmt die ganze Reihe — der Aufruf „Offline
   beitreten" steht im Entwurf ueber die volle Breite. */
.kv-karten__raster.kv-raster--1 > * {
	flex-basis: 100%;
	max-width: none;
}

.kv-karte {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: 24px;
	min-height: var(--kv-karte-hoehe, 200px);
	padding: var(--kv-karte-pad);
	border-radius: var(--kv-r-klein);
	background: var(--kv-soft);
}

.kv-page .kv-karten--soft .kv-karte,
.kv-page .kv-karten--footer .kv-karte {
	background: var(--kv-weiss);
}

/* Die Akzentkarte: im Entwurf der Aufruf am Ende einer Reihe. */
.kv-page .kv-karte--akzent,
.kv-page .kv-karten--soft .kv-karte--akzent,
.kv-page .kv-karten--footer .kv-karte--akzent {
	background: var(--kv-rot);
}

/* Die Symbolflaeche: pastellfarbenes Quadrat mit rotem Punkt. Der Ton
   wechselt der Reihe nach — Creme, Aprikose, Rose — wie im Entwurf. Wer
   einen festen Ton will, setzt ihn an der Karte. */
.kv-karte__symbol {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border-radius: var(--kv-r-mini);
	background: var(--kv-creme);
	flex: 0 0 auto;
}

.kv-karte__punkt {
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background: var(--kv-rot);
}

.kv-karten__raster > .kv-karte:nth-child(3n + 2) .kv-karte__symbol,
.kv-karte__symbol--aprikose { background: var(--kv-aprikose); }

.kv-karten__raster > .kv-karte:nth-child(3n + 3) .kv-karte__symbol,
.kv-karte__symbol--rose     { background: var(--kv-rose); }

.kv-karte__symbol--creme    { background: var(--kv-creme); }

.kv-page .kv-karte--akzent .kv-karte__symbol {
	background: color-mix(in srgb, var(--kv-soft) 18%, transparent);
}

.kv-page .kv-karte--akzent .kv-karte__punkt { background: var(--kv-creme); }

/* KEIN align-items: flex-start. Der Entwurf lässt die Zeilen die
   Kartenbreite füllen; nur der Verweis darunter sitzt links. Mit
   flex-start war jede Zeile so breit wie ihr Text — der Umbruch fiel
   dadurch an anderer Stelle als im Entwurf. */
.kv-karte__text {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.kv-page .kv-karte__text .kv-link { align-self: flex-start; }

.kv-karte__titel {
	font-family: var(--kv-text);
	font-size: 16px;
	line-height: 24px;
	font-weight: 500;
	color: var(--kv-ink);
}

.kv-page .kv-karte .kv-text {
	font-size: 13px;
	line-height: 20px;
	color: var(--kv-ink-64);
}

/* Nach der allgemeinen Kartenschrift, sonst gewinnt sie: gleich lang,
   gleiche Spezifität. */
.kv-page .kv-karte--akzent .kv-karte__titel { color: var(--kv-soft); }
.kv-page .kv-karte--akzent .kv-text         { color: var(--kv-licht-82); }

.kv-page .kv-karte .kv-link {
	font-size: 14px;
	line-height: 16px;
	margin-top: 4px;
}

/* --- Hinweisband --------------------------------------------------------
   Weiße Karte auf hellem Grund: links die Aussage, rechts der Button. */
.kv-page .kv-hband {
	width: 100%;
	padding-block: var(--kv-abschnitt);
}

.kv-page .kv-hband--soft  { background: var(--kv-soft); }
.kv-page .kv-hband--weiss { background: var(--kv-weiss); }

.kv-hband__karte {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 40px;
	padding: 40px;
	border-radius: var(--kv-r-gross);
	background: var(--kv-weiss);
}

.kv-page .kv-hband--weiss .kv-hband__karte { background: var(--kv-soft); }

.kv-hband__karte--unten {
	flex-direction: column;
	align-items: flex-start;
	gap: 24px;
}

/* Ohne align-items: flex-start — die Rubrik darüber ist keine Kapsel,
   und die Überschrift soll die Spalte füllen, damit sie dort umbricht,
   wo sie im Entwurf umbricht. */
.kv-hband__text {
	display: flex;
	flex: 1 1 420px;
	min-width: 0;
	flex-direction: column;
	gap: 12px;
}

.kv-page .kv-hband__karte > .kv-btn { flex: 0 0 auto; }

/* Kleine Monozeile — Bildunterschriften, Beschriftung im Videoplatzhalter. */
.kv-page .kv-mono {
	font-family: var(--kv-mono);
	font-size: 12px;
	line-height: 16px;
	font-weight: 400;
	letter-spacing: 0.75px;
	text-transform: uppercase;
	color: var(--kv-ink-50);
}

/* Summenzeile im Ticketformular. */
.kv-summe {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 16px;
	/* 16 px ÜBER der Linie, 16 darunter. Ohne den oberen Abstand saß die
	   Linie direkt auf der Unterkante des letzten Preises — sie schnitt
	   die Unterlängen von „17,00 €" an. Derselbe Abstand wie zwischen den
	   Ticketzeilen, dadurch wirkt die Linie als Zäsur und nicht als
	   Unterstreichung. */
	margin-top: 16px;
	padding-top: 16px;
	margin-bottom: 16px;
	border-top: 1px solid var(--kv-ink-12);
}

.kv-summe__label {
	font-size: 15px;
	line-height: 20px;
	font-weight: 400;
	color: var(--kv-ink-64);
}

.kv-summe__wert {
	font-family: var(--kv-display);
	font-size: 24px;
	line-height: 28px;
	letter-spacing: -0.02em;
	font-weight: 400;
	color: var(--kv-ink);
}

/* --- Video auf der Veranstaltungsseite ---------------------------------- */
.kv-video {
	display: flex;
	flex-direction: column;
	gap: 16px;
	margin-top: 48px;
}

.kv-video__rahmen {
	width: 100%;
	aspect-ratio: 16 / 9;
	border-radius: var(--kv-r-gross);
	overflow: hidden;
	background: var(--kv-soft);
}

.kv-video__rahmen iframe,
.kv-video__rahmen video,
.kv-video__rahmen .kv-video__quelle {
	width: 100%;
	height: 100%;
	border: 0;
	display: block;
	object-fit: cover;
}

/* Ohne Adresse eine leere Flaeche mit Beschriftung: sichtbar offen. */
/* Der Platzhalter des Entwurfs ist schraffiert, nicht leer grau — man
   sieht auf einen Blick, dass hier etwas fehlt. */
.kv-video__rahmen--leer {
	display: flex;
	align-items: center;
	justify-content: center;
	background: repeating-linear-gradient(135deg, #EDEBE8 0 10px, #E5E2DE 10px 20px);
	text-align: center;
	padding: 24px;
}

/* Spielort in der Infospalte. */
.kv-infokarte__ort {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 8px;
}

/* Veranstaltungsort und Tickets sind eigene Abschnitte der Karte, und
   sie standen mit 4 px unter der Angabenliste — deren Zeilen haben
   untereinander 14 px UND eine Trennlinie. Die Rubrik „Veranstaltungs-
   ort" klebte dadurch am Eintrittspreis.

   Dieselbe Linie wie zwischen den Angaben, und sie sitzt mittig: 12 px
   Rand plus die 4 px Abstand der Karte davor, 16 px danach. Die letzte
   Angabenzeile trägt selbst keine Linie mehr (`:last-child`) — die hier
   ist also keine zweite. */
.kv-infokarte__ort,
.kv-infokarte__tickets {
	margin-top: 12px;
	padding-top: 16px;
	border-top: 1px solid var(--kv-ink-12);
}

.kv-infokarte__ortfeld {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.kv-infokarte__ortname {
	font-size: 16px;
	line-height: 24px;
	font-weight: 400;
	color: var(--kv-ink);
}

.kv-infokarte__ortadresse {
	font-size: 16px;
	line-height: 24px;
	font-weight: 300;
	color: var(--kv-ink-64);
}

/* Kennzahlenzeile unter einem Medien+Text-Abschnitt. */
.kv-kennzahlen {
	display: flex;
	flex-wrap: wrap;
	gap: 32px;
	margin: 8px 0 0;
	padding-top: 24px;
	border-top: 1px solid var(--kv-ink-12);
	width: 100%;
}

.kv-kennzahlen > div {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.kv-page .kv-kennzahlen dt { margin: 0; }

.kv-page .kv-kennzahlen dd {
	margin: 0;
	font-size: 16px;
	line-height: 24px;
	font-weight: 400;
	color: var(--kv-ink);
}

/* Kopfzeile der Bildkacheln: Überschrift links, Link rechts. */
.kv-kacheln__kopf {
	flex-direction: row;
	align-items: baseline;
	justify-content: space-between;
	gap: 24px;
	flex-wrap: wrap;
}

.kv-kacheln__kopftext {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 16px;
}

.kv-kachel__meta {
	color: var(--kv-licht-82);
}

/* =========================================================================
   36. Ticketverwaltung

   Das Plugin bringt seine eigene Optik mit und steuert sie über
   Variablen — zwölf Zeilen statt 638 (siehe DOKUMENTATION von Bold
   Tickets, §1 „Optik").
   ========================================================================= */

.kv-page .kv-verwaltung {
	padding-block: 0 var(--kv-abschnitt);
}

.kv-page .bold-ta {
	--bold-ta-accent: var(--kv-rot);
	--bold-ta-accent-rgb: 140, 29, 24;
	--bold-ta-accent-dark: var(--kv-rot-dunkel);
	--bold-ta-bg: var(--kv-weiss);
	--bold-ta-surface: var(--kv-soft);
	--bold-ta-line: var(--kv-ink-12);
	--bold-ta-font: var(--kv-text);
	--bold-ta-size: 16px;
	--bold-ta-size-sm: 13px;
	--bold-ta-radius: var(--kv-r-mini);
	--bold-ta-radius-lg: var(--kv-r-gross);
	--bold-ta-radius-pill: 100px;
	--bold-ta-shadow: var(--kv-schatten-karte);

	/* Das Plugin setzt an seiner Wurzel `color: var(--bold-ta-accent)` —
	   die Akzentfarbe IST bei ihm die Textfarbe der ganzen Seite. Das geht
	   mit seinem mittleren Blau auf; mit unserem Rot stand jeder Absatz,
	   jede Kennzahl und jeder Hinweis in Signalfarbe.

	   Deshalb hier zwei Zeilen mehr als die reine Tokenliste: Text in der
	   Haustinte, Rot bleibt den Verweisen und Buttons. Ohne das ist die
	   Seite lesbar, aber sie schreit. */
	color: var(--kv-ink);
}

/* Verweise rot — ABER KEINE KNÖPFE.
   -----------------------------------------------------------------------
   `.kv-page .bold-ta a` (0,3,0) schlägt `.bold-ta .bold-ta-btn`
   (0,2,0) des Plugins. Ein Knopf, der ein `<a>` ist, bekam damit rote
   Schrift auf rotem Grund: „Einlassliste als PDF" war ein leerer roter
   Block. Gemeldet vom Kunden am 08.09.2026, nachgemessen
   `color: rgb(140,29,24)` auf `background: rgb(140,29,24)`.

   Dass es nicht überall auffiel, liegt an der Auszeichnung: „Einchecken"
   ist ein `<button>` und wurde von unserer Regel nie getroffen. Derselbe
   Fehler wie „Weiter zur Kasse unsichtbar" — dort ein `<a>` ohne
   Themefarbe, hier eines mit zu viel davon. */
.kv-page .bold-ta a:not(.bold-ta-btn) {
	color: var(--kv-rot);
}

.kv-page .bold-ta a:not(.bold-ta-btn):hover {
	color: var(--kv-rot-dunkel);
}

/* Die Umrissknöpfe bleiben rot — Rahmen UND Schrift.
   Unsere Wurzelregel `.bold-ta { color: var(--kv-ink) }` (0,2,0) und die
   Plugin-Regel für `--outline` (0,2,0) sind gleich stark; unser
   Stylesheet lädt später und gewinnt. Ohne diese Zeile stand
   „Teilnehmer als CSV" in Tinte in einem roten Rahmen. */
.kv-page .bold-ta .bold-ta-btn--outline,
.kv-page .bold-ta .bold-ta-btn--outline-sm {
	color: var(--kv-rot);
}

/* --- Felder: Rahmen in Tinte, nicht in Signalrot ----------------------

   Das Plugin zieht seine Feldrahmen aus `--bold-ta-accent` — bei ihm ein
   mittleres Blau, bei uns Hausrot. Damit stand jedes Feld der
   Ticketverwaltung und des Anmeldeformulars in einem roten Rahmen und
   sah aus wie ein Fehler. Dieselbe Entscheidung wie an der Mengenauswahl
   im Ticketformular: rot bleibt Verweisen und Knöpfen. */
.kv-page .bold-ta input,
.kv-page .bold-ta select,
.kv-page .bold-ta textarea {
	border-color: var(--kv-ink-12);
}

.kv-page .bold-ta input:focus,
.kv-page .bold-ta input:focus-visible,
.kv-page .bold-ta select:focus,
.kv-page .bold-ta select:focus-visible,
.kv-page .bold-ta textarea:focus,
.kv-page .bold-ta textarea:focus-visible {
	border-color: var(--kv-ink-64);
	outline: 2px solid var(--kv-ink-64);
	outline-offset: 1px;
}

/* --- Und der Inhalt braucht Abstand zum Kopf -------------------------

   Gemessen: der Wolken-Hero endet bei 407 px, `.bold-ta` beginnt bei
   407 px — der Abschnitt trägt kein Polster, weil sein Inhalt ein
   Shortcode ist und nicht eine unserer Sektionen. „Die Bestände passen
   nach oben nicht" (Kunde): die Veranstaltungsauswahl klebte am
   Kopfband, die Kennzahlen saßen zu hoch.

   Dieselbe Abstandsstufe wie unter einem Wolken-Hero anderswo. */
.kv-page .kv-verwaltung {
	padding-block: 64px 96px;
}

@media (max-width: 900px) {
	.kv-page .kv-verwaltung {
		padding-block: 40px 64px;
	}
}

/* --- Warteliste und Ausverkauft ----------------------------------------

   `[bold_ticket_form]` schaltet selbst um: sind die Plätze weg, steht an
   der Stelle der Ticketauswahl entweder das Wartelistenformular oder ein
   Ausverkauft-Hinweis (Bold Tickets, §2). Beide tragen `.bold-wl` und
   dasselbe Stylesheet — dieselben zwölf Zeilen Tokens wie überall, statt
   fremde Regeln zu überschreiben.

   Das Wartelistenformular ist der Weg, auf dem PERSONENBEZOGENE Daten
   hereinkommen. Es darf nicht aussehen wie ein fremder Einschub.
   ----------------------------------------------------------------------- */

.kv-page .bold-wl {
	--bold-wl-accent: var(--kv-rot);
	--bold-wl-text: var(--kv-ink);
	--bold-wl-bg: var(--kv-weiss);
	--bold-wl-line: var(--kv-ink-12);
	--bold-wl-font: var(--kv-text);
	--bold-wl-size: 15px;
	--bold-wl-radius: var(--kv-r-mini);
}

/* In der Infokarte sitzt das Formular bereits in einer weißen Karte —
   eine zweite Fläche darin wäre eine Karte in der Karte. */
.kv-page .kv-infokarte__tickets .bold-wl {
	padding: 0;
	border: 0;
	background: transparent;
	box-shadow: none;
}

.kv-page .kv-infokarte__tickets .bold-wl__titel {
	font-family: var(--kv-label);
	font-size: 12px;
	line-height: 16px;
	font-weight: 400;
	letter-spacing: 1px;
	text-transform: uppercase;
	color: var(--kv-ink-50);
}

/* „Ausverkauft" ist kein Feldtitel.

   Die beiden Regeln darüber gelten dem WARTELISTEN-FORMULAR: dort ist „keine
   Fläche in der Fläche" richtig, und „Auf die Warteliste" darf als Label über
   dem Formular stehen. Der Ausverkauft-Hinweis trägt dieselbe Klasse und erbt
   das mit — er landete damit auf derselben Stufe wie „TICKETS" und
   „VERANSTALTUNGSORT" und las sich wie eine Beschriftung.

   Er ist aber die Auskunft, wegen der jemand aufhört zu suchen. Also
   Schriftgrad und Gewicht zurück, ohne eine zweite Karte aufzumachen — das
   Prinzip der Infokarte bleibt, nur die Rangfolge stimmt wieder. */

.kv-page .kv-infokarte__tickets .bold-wl--sold-out .bold-wl__titel {
	font-family: var(--kv-text);
	font-size: 19px;
	line-height: 25px;
	font-weight: 600;
	letter-spacing: 0;
	text-transform: none;
	color: var(--kv-ink);
	gap: 8px;
}

.kv-page .kv-infokarte__tickets .bold-wl--sold-out .bold-wl__titel::before {
	width: 0.42em;
	height: 0.42em;
	opacity: 0.4;
}

.kv-page .kv-infokarte__tickets .bold-wl--sold-out .bold-wl__text {
	font-size: 14px;
	line-height: 20px;
	color: var(--kv-ink-72);
}

/* „Tickets verfügbar ab …" — dieselbe Lage, anderer Kasten.

   Der kommt mit einem eigenen Rahmen aus dem Plugin (`--soon`), und ein
   Rahmen in der Karte ist hier vertretbar: er grenzt eine Ankündigung ab,
   keine Fläche. Nur die Maße sind für eine 390 px schmale Spalte zu großzügig
   gedacht. */

.kv-page .kv-infokarte__tickets .bold-tickets--closed p {
	padding: 12px 14px;
	font-size: 14px;
	line-height: 20px;
}

/* =========================================================================
   37. WPForms

   Plugin-Basisstile sind abgeschaltet („Base styles only/None", §8.3), die
   Optik kommt von hier. Was dabei anfällt, steht als Kommentar an der
   jeweiligen Regel — WPForms gewinnt je nach Ladereihenfolge, deshalb ist
   `!important` hier die dokumentierte Ausnahme.
   ========================================================================= */

.kv-page .wpforms-container {
	margin: 0;
	max-width: 100%;
}

.kv-page .wpforms-form {
	display: flex;
	flex-direction: column;
	gap: 24px;
}

/* --- Gruppenüberschrift ------------------------------------------------
   Im Entwurf eine Inconsolata-Rubrik, KEINE h3. WPForms rendert für den
   „Section Divider" trotzdem ein h3 — also bekommt das h3 die Rubrik. */
.kv-page .wpforms-field-divider {
	padding: 0;
	border: 0;
	border-top: 1px solid var(--kv-ink-12);
	padding-top: 28px;
	margin-top: 4px;
}

.kv-page .wpforms-field-divider:first-child {
	border-top: 0;
	padding-top: 0;
	margin-top: 0;
}

.kv-page .wpforms-field-divider h3 {
	font-family: var(--kv-label);
	font-size: 12px;
	line-height: 16px;
	font-weight: 400;
	letter-spacing: 1px;
	text-transform: uppercase;
	color: var(--kv-ink-50);
	margin: 0;
}

/* --- Feld und Beschriftung --------------------------------------------- */

.kv-page .wpforms-field {
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.kv-page .wpforms-field-label {
	font-family: var(--kv-text);
	font-size: 14px;
	line-height: 20px;
	font-weight: 400;
	color: var(--kv-ink);
	margin: 0;
	display: block;
}

.kv-page .wpforms-required-label {
	color: var(--kv-rot);
	border: 0;
}

/* Layout-Zeilen rendern eine h3-Beschriftung („Zeile 1"). Sie ist im
   Felddatensatz als label_hide gesetzt — WPForms überschreibt die eigene
   Klasse aber teils wieder (§8.3). */
.kv-page .wpforms-field-layout > .wpforms-field-label,
.kv-page .wpforms-label-hide {
	display: none !important;
}

/* .wpforms-field-layout-columns bringt margin: 0 -10px mit und ragt sonst
   aus dem Container (§8.3). */
.kv-page .wpforms-field-layout-columns {
	margin: 0 !important;
	display: flex;
	flex-wrap: wrap;
	gap: 20px;
	width: 100%;
}

/* Die Spaltenbreite gibt WPForms über eigene Klassen vor. Ein pauschales
   `flex: 1 1 240px` hier machte aus der 67-33-Zeile eine 50-50 — die
   Straße soll aber zwei Drittel bekommen (im Entwurf flex 2 1 320px). */
.kv-page .wpforms-layout-column {
	padding: 0 !important;
	min-width: 0;
}

.kv-page .wpforms-layout-column-50 { flex: 1 1 240px; }
.kv-page .wpforms-layout-column-67 { flex: 2 1 320px; }
.kv-page .wpforms-layout-column-33 { flex: 1 1 180px; }
.kv-page .wpforms-layout-column-25 { flex: 1 1 160px; }

/* --- Eingabefelder ----------------------------------------------------- */

.kv-page .wpforms-form input[type="text"],
.kv-page .wpforms-form input[type="email"],
.kv-page .wpforms-form input[type="tel"],
.kv-page .wpforms-form input[type="url"],
.kv-page .wpforms-form input[type="number"],
.kv-page .wpforms-form select,
.kv-page .wpforms-form textarea {
	box-sizing: border-box;
	width: 100%;
	height: 48px;
	padding: 0 16px;
	border: 0;
	border-radius: var(--kv-r-mini);
	background: var(--kv-feld);
	font-family: var(--kv-text);
	font-size: 16px;
	/* Ohne eigene Zeilenhöhe schlägt Bricks' 1.7 durch (§8.3/§9.3). */
	line-height: 24px;
	font-weight: 300;
	color: var(--kv-ink);
}

.kv-page .wpforms-form textarea {
	height: auto;
	min-height: 120px;
	padding: 14px 16px;
	resize: vertical;
}

/* Der Entwurf begrenzt die Auswahlliste auf 420 px — über die ganze
   Formularbreite gezogen sieht sie aus wie ein Textfeld.
   Mit .wpforms-field davor, weil das Stylesheet von WPForms NACH diesem
   geladen wird und bei gleicher Spezifität gewinnen würde. */
.kv-page .wpforms-form .wpforms-field select { max-width: 420px; }

/* Native Auswahlpfeile, wie im Entwurf: dort steht die Liste als graues
   Feld ohne eigenes Zeichen. Der Chevron bleibt der Ticketauswahl auf der
   Veranstaltungsseite, wo der Entwurf ihn setzt. */
.kv-page .wpforms-form select {
	padding-right: 16px;
}

.kv-page .wpforms-form :where(input, select, textarea):focus-visible {
	outline: 2px solid var(--kv-rot);
	outline-offset: 2px;
}

.kv-page .wpforms-form ::placeholder {
	color: var(--kv-ink-50);
	opacity: 1;
}

/* --- Kästchen ---------------------------------------------------------- */

.kv-page .wpforms-field-checkbox ul,
.kv-page .wpforms-field-gdpr-checkbox ul,
.kv-page .wpforms-field-radio ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.kv-page .wpforms-field-checkbox li,
.kv-page .wpforms-field-gdpr-checkbox li,
.kv-page .wpforms-field-radio li {
	display: flex;
	flex-direction: row;
	align-items: flex-start;
	gap: 12px;
	margin: 0;
}

.kv-page .wpforms-form input[type="checkbox"],
.kv-page .wpforms-form input[type="radio"] {
	width: 18px;
	height: 18px;
	margin: 3px 0 0;
	flex-shrink: 0;
	accent-color: var(--kv-rot);
}

.kv-page .wpforms-field-checkbox label,
.kv-page .wpforms-field-gdpr-checkbox label,
.kv-page .wpforms-field-radio label {
	font-size: 13px;
	line-height: 20px;
	font-weight: 300;
	color: var(--kv-ink-72);
	margin: 0;
}

/* --- Absenden ---------------------------------------------------------- */

.kv-page .wpforms-submit-container {
	padding: 0;
	margin-top: 8px;
}

.kv-page .wpforms-form button[type="submit"] {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	height: 44px;
	padding: 12px 18px;
	border: 0;
	border-radius: var(--kv-r-mini);
	background: var(--kv-rot);
	box-shadow: inset 0 0 0 1px var(--kv-rot);
	font-family: var(--kv-text);
	font-size: 16px;
	line-height: 20px;
	font-weight: 400;
	color: var(--kv-soft);
	cursor: pointer;
	transition: background var(--kv-t-flaeche), color var(--kv-t-flaeche);
}

.kv-page .wpforms-form button[type="submit"]:hover {
	background: rgba(140, 29, 24, 0);
	color: var(--kv-rot);
}

/* --- Meldungen --------------------------------------------------------- */

.kv-page .wpforms-error,
.kv-page .wpforms-field-label-inline em {
	font-size: 13px;
	line-height: 20px;
	color: var(--kv-rot);
	font-style: normal;
}

.kv-page .wpforms-confirmation-container-full {
	padding: 20px 24px;
	border-radius: var(--kv-r-klein);
	background: var(--kv-soft);
	box-shadow: inset 0 0 0 1px var(--kv-ink-12);
	color: var(--kv-ink);
}

/* Einspaltige Karte: die Überschrift steht dann im Entwurf größer und der
   Text daneben, nicht darunter. */
.kv-raster--1 { grid-template-columns: minmax(0, 1fr); }

.kv-raster--1 .kv-karte {
	min-height: 0;
	max-width: 1028px;
	margin-inline: auto;
	width: 100%;
}

.kv-raster--1 .kv-karte__titel {
	font-family: var(--kv-display);
	font-size: 24px;
	line-height: 32px;
	font-weight: 400;
	letter-spacing: -0.02em;
}

/* In der einspaltigen Karte ist der Link so groß wie ein Textlink im
   Abschnitt, nicht wie einer in einer Kachel. */
.kv-page .kv-raster--1 .kv-karte .kv-link {
	font-size: 16px;
	line-height: 20px;
}

/* =========================================================================
   Zeilenrhythmus: Responsive-Stufen

   Diese Stufen stehen bewusst am Dateiende. Eine Media-Query erhöht die
   Spezifität NICHT — eine gleich starke Regel weiter unten in der Datei
   gewinnt trotzdem. Die Grundregeln des Rhythmus stehen in Abschnitt 5,
   also müssen ihre Ausnahmen danach kommen.
   ========================================================================= */

/* --- bis 900: zwei Spalten -----------------------------------------------

   Hier wird aus dem Raster eine Flexzeile. Der Rhythmus ist für DREI
   Spalten gerechnet und in PHP entstanden — das Fenster kennt er nicht.
   Bei zwei Spalten stünde eine Drittelkarte allein in der letzten Zeile
   und daneben eine Lücke.

   Flexbox löst das ohne zweite Rechnung: eine einzelne Karte am Zeilenende
   wächst auf die ganze Breite, zwei teilen sie. Was auf dem großen Bild
   voll oder halb war, nimmt hier die ganze Zeile.
   ----------------------------------------------------------------------- */
@media (max-width: 900px) {
	.kv-eliste__raster--rhythmus {
		display: flex;
		flex-wrap: wrap;
		align-items: flex-start;
	}

	.kv-eliste__raster--rhythmus > .kv-ekarte {
		flex: 1 1 calc((100% - 16px) / 2);
		min-width: 0;
	}

	/* Bei zwei Spalten ist jede Karte eine Hälfte — auch die „volle".
	   -------------------------------------------------------------------
	   Vorher behielt `--voll` hier 100 %, und das brach die eine Regel,
	   die den Rhythmus ruhig hält: bei sechs Terminen (Muster 2·3·1)
	   standen auf 900 px ZWEI einzelne Karten hintereinander — die
	   übrige Drittelkarte, gewachsen auf die ganze Breite, und darunter
	   die volle. Aufgefallen ist es erst mit dem sechsten Termin des
	   Vereins; `pruefung/rhythmus.js` prüft die Regel und hat es gemeldet.

	   Mit 50 % teilt sich die volle Karte die Zeile mit ihrer Nachbarin;
	   bleibt sie am Ende allein, wächst sie über `flex-grow` ohnehin auf
	   die ganze Breite. */
	.kv-eliste__raster--rhythmus > .kv-ekarte--voll {
		flex-basis: calc(50% - 8px);
	}

	.kv-eliste__raster--fuellen > .kv-ekarte,
	.kv-eliste__raster--fuellen--s2 > .kv-ekarte { flex-basis: calc((100% - 16px) / 2); }
}

/* --- bis 700: einspaltig ------------------------------------------------ */
@media (max-width: 700px) {
	.kv-eliste__raster--rhythmus { gap: 24px; }

	.kv-eliste__raster--rhythmus > .kv-ekarte,
	.kv-eliste__raster--rhythmus > .kv-ekarte--drittel,
	.kv-eliste__raster--rhythmus > .kv-ekarte--halb,
	.kv-eliste__raster--rhythmus > .kv-ekarte--voll { flex-basis: 100%; }

	/* Einspaltig gibt es keine breite Karte mehr — das Motiv bekommt
	   wieder die Höhe des Entwurfs, sonst wird es zum flachen Band. */
	.kv-page .kv-ekarte--halb .kv-ekarte__bild,
	.kv-page .kv-ekarte--voll .kv-ekarte__bild {
		height: 440px;
		aspect-ratio: auto;
	}

	.kv-page .kv-ekarte--archiv.kv-ekarte--halb .kv-ekarte__bild,
	.kv-page .kv-ekarte--archiv.kv-ekarte--voll .kv-ekarte__bild { height: 320px; }

	.kv-page .kv-ekarte--kompakt.kv-ekarte--halb .kv-ekarte__bild,
	.kv-page .kv-ekarte--kompakt.kv-ekarte--voll .kv-ekarte__bild { height: 380px; }

	.kv-ekarte--voll .kv-ekarte__text { max-width: none; }

	.kv-eliste__raster--fuellen { gap: 24px; }

	.kv-eliste__raster--fuellen > .kv-ekarte,
	.kv-eliste__raster--fuellen--s2 > .kv-ekarte { flex-basis: 100%; }
}

/* =========================================================================
   38. WooCommerce-Seiten (Kasse, Warenkorb, Bestellbestätigung)

   Diese Seiten baut WooCommerce selbst — sein Inhalt landet in
   `#brx-content`, dem Rückfall von Bricks, ohne Abschnitt und ohne
   Container. Ohne die Regeln hier klebt die Überschrift am Kopf, der
   Inhalt läuft auf 1100 px in einer fremden Breite, und die Meldung
   „Vielen Dank" steht in WooCommerce-Grün.

   Bewusst nur das Nötige: Breite, Luft und die Meldungen. Die Tabellen
   darunter bleiben, wie WooCommerce sie setzt — sie sind sachlich und
   niemand hat sie beanstandet.
   ========================================================================= */

/* --- Der leere Warenkorb --------------------------------------------

   Linksbündig, ohne Smiley und mit Luft (Kunde, 09.09.2026). Ausrichtung
   und Smiley stehen im Blockinhalt der Seite und sind dort geändert;
   hier stehen nur die Abstände — und die Größe der Überschrift, die als
   h2 von WooCommerce keine bekommt und deshalb aussah wie ihr eigener
   Fließtext.
   --------------------------------------------------------------------- */
.kv-page .wc-block-cart__empty-cart__title {
	margin: 0 0 12px;
	font-size: 24px;
	line-height: 32px;
	font-weight: 400;
}

.kv-page .wp-block-woocommerce-empty-cart-block p {
	margin: 0 0 32px;
	max-width: 640px;
}

.kv-page .wp-block-woocommerce-empty-cart-block .wp-block-buttons {
	margin: 0;
}

.kv-page.woocommerce-page #brx-content,
.kv-page.woocommerce-order-received #brx-content {
	width: 100%;
	/* 1028 und nicht die volle Inhaltsbreite: es ist eine Bestätigung mit
	   Angaben, kein Schaufenster. Dieselbe schmale Spur, die der Entwurf
	   für Kontaktkarten und Formulare benutzt. */
	max-width: calc(1028px + 2 * var(--kv-rand));
	margin-inline: auto;
	padding: var(--kv-abschnitt) var(--kv-rand) calc(var(--kv-abschnitt) * 1.5);
}

.kv-page.woocommerce-page #brx-content > h1 {
	font-family: var(--kv-display);
	font-size: 48px;
	line-height: 56px;
	font-weight: 400;
	letter-spacing: -0.02em;
	color: var(--kv-ink);
	margin: 0 0 12px;
}

/* --- Meldungen ---------------------------------------------------------
   Alle drei Arten dieselbe Form: eine ruhige Fläche mit einem Punkt in
   der Hausfarbe. Der Punkt ist dasselbe Zeichen wie im Eyebrow der
   Sektionen — er sagt „hier spricht die Seite", ohne Ampelfarben.

   Grün und Blau sind hier fremd: sie stammen aus WooCommerce und tauchen
   in diesem Entwurf nirgends sonst auf. */
.kv-page .woocommerce-notice,
.kv-page .woocommerce-info,
.kv-page .woocommerce-message,
.kv-page .woocommerce-error {
	display: flex;
	align-items: flex-start;
	/* WooCommerce setzt `space-between`, weil rechts ein Button sitzen kann.
	   Mit dem Punkt links rutschte der Text dadurch nach rechts. */
	justify-content: flex-start;
	flex-wrap: nowrap;
	gap: 14px;
	margin: 0 0 40px;
	padding: 24px 28px;
	/* WooCommerce zentriert den Text der Dankesmeldung. Mit dem Punkt
	   links davor stand er dadurch weder links noch mittig, sondern in
	   der Restbreite zentriert — auf dem Telefon über zwei Zeilen
	   sichtbar schief. Der Punkt gehört an die erste Zeile, der Text
	   linksbündig daneben. */
	text-align: left;
	border: 0;
	border-radius: var(--kv-r-gross);
	background: var(--kv-soft);
	color: var(--kv-ink);
	font-family: var(--kv-text);
	font-size: 17px;
	line-height: 26px;
	list-style: none;
}

.kv-page .woocommerce-notice::before,
.kv-page .woocommerce-info::before,
.kv-page .woocommerce-message::before,
.kv-page .woocommerce-error::before {
	content: "";
	flex: 0 0 auto;
	width: 8px;
	height: 8px;
	margin-top: 9px;
	border-radius: 50%;
	background: var(--kv-rot);
	/* WooCommerce setzt hier eine Zeichensatz-Ikone; die muss weg, sonst
	   stehen zwei Zeichen nebeneinander. */
	font-size: 0;
	line-height: 0;
}

/* Auf 402 px ist die Meldung zweizeilig: ohne `min-width: 0` drückt der
   Text den Punkt aus dem Kasten. */
.kv-page .woocommerce-notice > *,
.kv-page .woocommerce-message > * {
	min-width: 0;
}

/* Die Bestätigung nach der Bestellung ist die wichtigste Zeile der Seite
   — sie darf Platz haben und in der Größe des Lead stehen. */
.kv-page .woocommerce-thankyou-order-received {
	margin-bottom: 48px;
	padding: 28px 32px;
	font-size: 19px;
	line-height: 30px;
}

.kv-page .woocommerce-error {
	background: var(--kv-rose, #F7E9E8);
}

/* Verweise in den Meldungen wie überall im Text. */
.kv-page :where(.woocommerce-notice, .woocommerce-info, .woocommerce-message) a {
	color: var(--kv-rot);
	text-decoration: underline;
	text-underline-offset: 3px;
}

@media (max-width: 700px) {
	.kv-page.woocommerce-page #brx-content > h1 { font-size: 34px; line-height: 40px; }

	.kv-page .woocommerce-notice,
	.kv-page .woocommerce-info,
	.kv-page .woocommerce-message,
	.kv-page .woocommerce-error { padding: 20px 22px; font-size: 16px; line-height: 24px; }

	.kv-page .woocommerce-thankyou-order-received { padding: 22px 24px; font-size: 17px; line-height: 26px; }
}

/* --- Fokusring nur für die Tastatur -----------------------------------

   `:focus-visible` soll genau das leisten: Ring für die Tastatur, keiner
   für die Maus. Bei einer AUSWAHLLISTE hält Chrome sich nicht daran — es
   behält den Zustand, nachdem man mit der Maus einen Eintrag gewählt hat.
   Der Ring blieb also stehen.

   Deshalb markiert `kv.js` ein Feld, das mit einem Zeigegerät angefasst
   wurde, und nimmt die Marke bei der ersten Tastatureingabe wieder weg.
   Weglassen wäre keine Lösung: ohne sichtbaren Fokus findet sich niemand
   mit der Tastatur zurecht (§7.2).
   --------------------------------------------------------------------- */

.kv-page [data-kv-maus]:focus-visible {
	/* `!important` ist hier richtig und nicht faul: die Regel muss JEDEN
	   Komponentenring schlagen — der im Ticketformular ist mit vier
	   Klassen spezifischer als jede Marke am Element. Eine Regel, die
	   „für alle gilt, außer wo etwas spezifischer ist", wäre keine. */
	outline: none !important;
}

/* =========================================================================
   39. Der Builder

   Hier steht bewusst KEINE Regel. Das Bedienfeld des Builders bekommt
   dieses Stylesheet gar nicht mehr — `kv_ist_builder_panel()` in der
   `functions.php` hängt es dort aus, und auch die Wurzelklasse
   `.kv-page` bleibt weg. Die Vorschau (ein iframe) bekommt beides.

   Der Umweg, den ich zuerst genommen habe, gehört als Warnung hierher:
   ein Riegel `body.bricks-is-builder … { color: inherit }` griff nie,
   denn Bricks setzt im Panel WEDER `bricks-is-builder` NOCH
   `bricks-is-frontend` an den body (`includes/setup.php`). Wer hier
   wieder etwas ausschließen will, prüft erst, welche Klassen der body
   im Panel wirklich trägt.
   ========================================================================= */

/* =========================================================================
   40. Mobil: Trefferflächen und Polster

   Der Handoff zeigt die Seiten nur am Desktop; für schmale Geräte gibt es
   außer der Navigation keine Vorlage. Dieser Abschnitt folgt deshalb nicht
   einem Entwurf, sondern zwei Regeln, die unabhängig davon gelten:

   1. Was der Finger treffen soll, braucht Fläche. Ein Textlink ist am
      Desktop 16 px hoch — auf dem Telefon ein Nadelstich. WCAG 2.5.8
      verlangt 24 px, empfohlen sind 44. Die Schrift bleibt, das Polster
      wächst: das Bild ändert sich kaum, die Fläche deutlich.
   2. Ein Kasten mit 32 px Polster nimmt auf 390 px Fenster ein Sechstel
      der Breite.

   UND ER STEHT AM DATEIENDE. Eine Media-Query erhöht die Spezifität
   nicht — beim ersten Versuch lag dieser Block bei Zeile 2125, die
   Komponentenregeln stehen weiter unten, und `.kv-hervor` gewann. Genau
   dieselbe Falle wie bei den Responsive-Stufen des Heros.
   ========================================================================= */

@media (max-width: 900px) {
	/* Bis 900, nicht bis 700: ein Tablet bedient man genauso mit dem
	   Finger, und dieselbe Schwelle trägt schon die Navigation. Bei 768 px
	   waren die Fußzeilenlinks sonst weiter 16 px hoch.

	   Textlinks, Fußzeile, Brotkrume, Rechtstexte, Kontaktkarten:
	   Schrift gleich, Fläche größer. */
	.kv-page .kv-link,
	.kv-page .kv-fuss__rechtlink,
	.kv-page .kv-fuss__credit a,
	.kv-page .kv-fuss__nav a,
	.kv-page .kv-krume a,
	.kv-page .kv-kkarte__wert a,
	.kv-page .kv-kkarte__adresse a,
	.kv-page .kv-edetail__fliess a,
	.kv-page .kv-fuss__adresse a,
	.kv-page .kv-recht__text a,
	.kv-page .kv-recht__link,
	.kv-page .kv-video__quelle a {
		padding-block: 6px;
	}

	/* Die Reihe der Rechtstexte in der Fußzeile stünde sonst zu eng
	   untereinander, sobald sie umbricht. */
	.kv-page .kv-fuss__recht { gap: 4px 16px; }

	/* Farbiger Hinweiskasten: mit 32 px Polster stand der Satz auf
	   22 Zeichen je Zeile und flatterte. */
	.kv-page .kv-hervor { padding: 24px 20px; }
	.kv-page .kv-hervor__satz { font-size: 21px; line-height: 28px; }
}

/* --- Die Infoleiste des Heros bricht um ------------------------------

   `white-space: nowrap` an den Werten hält „Fischbrunnenplatz
   Eggenfelden" in einer Zeile — am Desktop richtig, auf dem Telefon
   fatal: die Leiste war 310 px breit in einem 269 px schmalen Kasten,
   und weil die Bühne `overflow: hidden` trägt, wurde der Rest einfach
   ABGESCHNITTEN. Keine Überbreite, kein Scrollbalken, nichts zu sehen —
   die Kategorie fehlte auf schmalen Geräten schlicht.

   Gefunden hat es `mobil.js`, weil es nicht die Seite, sondern jeden
   Kasten auf inneren Überlauf prüft.
   --------------------------------------------------------------------- */
@media (max-width: 900px) {
	.kv-page .kv-hero__leiste .kv-glas {
		flex-wrap: wrap;
		gap: 8px 18px;
	}

	.kv-page .kv-hero__leiste .kv-glas__wert { white-space: normal; }

	/* Die Trennstriche zwischen den Feldern ergeben umgebrochen keinen
	   Sinn mehr — sie standen zwischen Feldern EINER Zeile. */
	.kv-page .kv-hero__leiste .kv-glas__feld { flex: 0 1 auto; }
}

/* --- Sehr kleine Geräte: die Kästen geben Polster ab -----------------

   Auf 320 px bleibt vom Fenster nach Seitenrand (26) und Kastenpolster
   (32–40 je Seite) ein Textfeld von 189 px übrig — 24 Zeichen je Zeile.
   Das liest sich wie eine Spalte im Telefonbuch.

   Deshalb sinken hier die Polster der Bild- und Hinweiskästen. Die
   Tokens stehen dafür ohnehin bereit; verändert wird nur, was auf
   schmalen Geräten INNEN Platz kostet, nicht der Seitenrand.
   --------------------------------------------------------------------- */
@media (max-width: 480px) {
	:root {
		--kv-bildbox-pad: 20px;
		--kv-formkarte-pad: 24px;
	}

	.kv-page .kv-hero__inhalt,
	.kv-page .kv-band__inhalt,
	.kv-page .kv-ortsband__inhalt { padding: 20px; }

	.kv-page .kv-hband__karte { padding: 24px 20px; gap: 24px; }

	/* Der Hinweiskasten mit rotem Grund: 20 statt 24. */
	.kv-page .kv-hervor { padding: 20px 18px; }
}

/* --- WPForms: gestapelte Spalten brauchen keine Höhe -----------------

   WPForms dreht die Layout-Spalten bei 600 px auf `flex-direction:
   column`. Unsere Grundwerte `flex: 1 1 240px` waren für eine ZEILE
   gedacht — in einer Spalte ist `flex-basis` die HÖHE. Jede Spalte war
   damit 240 px hoch für ein 106 px hohes Feld: das Beitrittsformular
   hatte zwischen „Vorname" und „Nachname" 288 px Leerraum.

   Der Fehler war nicht zu sehen, solange man ihn nicht suchte: die Seite
   war einfach lang.
   --------------------------------------------------------------------- */
@media (max-width: 600px) {
	.kv-page .wpforms-layout-column-50,
	.kv-page .wpforms-layout-column-67,
	.kv-page .wpforms-layout-column-33,
	.kv-page .wpforms-layout-column-25 { flex: 0 1 auto; }
}

/* --- Das Team steht mobil zweispaltig --------------------------------

   Einspaltig ergibt jedes Portrait ein Quadrat über die volle Breite:
   „Der Verein" war 11.244 px lang, und man scrollte an dreizehn Bildern
   vorbei. Zwei Spalten halbieren das, und ein Portrait bleibt bei 160 px
   gut erkennbar.
   --------------------------------------------------------------------- */
@media (max-width: 700px) {
	.kv-page .kv-team__raster {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 24px 16px;
	}

	.kv-page .kv-person__name  { font-size: 15px; line-height: 20px; }
	.kv-page .kv-person__rolle { font-size: 13px; line-height: 18px; }
}

/* --- Das Mitgliedschaftsband auf schmalen Geräten --------------------

   Dort stapelt sich alles: Überschrift, Text, zwei Buttons und die
   Vorteilskarten. Die Bühne wird 1026 px hoch, und die Überschrift sitzt
   970 px über der unteren Kante — weit außerhalb des px-verankerten
   Verlaufs, der für 560 px gerechnet ist. Gemessen: 3,7:1.

   Wie beim Hero gilt hier deshalb ein MINDESTWERT statt eines Auslaufs
   auf Null. Auf dem Telefon sieht man vom Motiv ohnehin fast nur den
   Teil, hinter dem Schrift steht.
   --------------------------------------------------------------------- */
@media (max-width: 900px) {
	/* Bis 900, nicht 700: ab dieser Breite stapelt der Bandinhalt
	   (`flex-direction: column`), die Bühne wird hoch und die Überschrift
	   rutscht aus dem px-verankerten Verlauf. Bei 768 px waren es 3,36:1. */
	.kv-band__unten {
		background: linear-gradient(
			0deg,
			rgba(35, 31, 35, 0.9) 0%,
			rgba(35, 31, 35, 0.86) 35%,
			rgba(35, 31, 35, 0.74) 65%,
			rgba(35, 31, 35, 0.66) 100%
		);
	}
}

/* --- Ortsband auf schmalen Geräten -----------------------------------
   Wie beim Mitgliedschaftsband: hier stapeln sich Überschrift, Text und
   Glaskarte, die Bühne wird hoch, und der Text steht weit über der
   unteren Kante. Also ein Mindestwert statt eines Auslaufs auf Null.
   --------------------------------------------------------------------- */
@media (max-width: 700px) {
	.kv-ortsband__unten {
		background: linear-gradient(
			0deg,
			rgba(35, 31, 35, 0.88) 0%,
			rgba(35, 31, 35, 0.84) 40%,
			rgba(35, 31, 35, 0.72) 75%,
			rgba(35, 31, 35, 0.66) 100%
		);
	}
}

/* --- Mitgliedschaftsband: 380 px Loch zwischen Text und Buttons ------

   Derselbe Fehler wie bei den WPForms-Spalten, nur an anderer Stelle:
   `.kv-band__text` trägt `flex: 1 1 480px`. Für die ZEILE gedacht, in
   der Text und Vorteilskarte nebeneinander stehen — ab 900 px stapelt
   der Kopf aber (`flex-direction: column`), und dort ist `flex-basis`
   die HÖHE. Der Textblock war damit 480 px hoch für 190 px Inhalt.

   Dazu `justify-content: space-between`: in einer Spalte verteilt es
   senkrecht. Überschrift also oben, Buttons 380 px darunter, dazwischen
   nichts als Foto. Gemessen bei 390 px: Kopf 616 px hoch, Bühne 1026.

   Beides gilt nur für die Zeile. Gestapelt sitzen Überschrift, Text und
   Buttons zusammen, und die Bühne ist wieder so hoch wie ihr Inhalt.

   Derselbe Wert steht am Hero-Text und am Ortsband-Text, und beide
   Elternteile stapeln bei denselben 900 px — dort dieselbe Wirkung:
   174 px im Hero (768), 324 px im Ortsband (768). `pruefung/luft.js`
   sucht diese Bauform jetzt von selbst.
   --------------------------------------------------------------------- */
@media (max-width: 900px) {
	.kv-page .kv-band__kopf,
	.kv-page .kv-hero__inhalt,
	.kv-page .kv-ortsband__inhalt { justify-content: flex-start; }

	.kv-page .kv-band__text,
	.kv-page .kv-hero__text,
	.kv-page .kv-ortsband__text { flex-basis: auto; }
}

/* --- Kontaktkarten: die 220 px gelten für die REIHE ------------------

   `min-height: 220px` stammt aus dem Entwurf, wo vier Karten
   nebeneinander stehen und gleich hoch sein müssen. Einspaltig gibt es
   keine Reihe mehr, an die sich etwas anzugleichen hätte — die Karte
   „Instagram" hat eine Zeile Anschrift statt drei und riss mit
   `space-between` 80 px zwischen Handle und Beschreibung auf.

   Einspaltig also: Höhe nach Inhalt, Abstand ist der Gap.

   Die Grenze ist 672, nicht 700: das Raster ist eine Flexzeile mit
   `flex: 1 1 300px`, sie bricht von selbst. Gemessen kippt sie zwischen
   670 (eine Spalte) und 680 (zwei). Ab 700 stehen zwei Karten
   nebeneinander — dort gehört die gemeinsame Höhe zurück, sonst steht
   die Reihe ausgefranst da (gemessen 216/196 bei 700 px).
   --------------------------------------------------------------------- */
@media (max-width: 672px) {
	.kv-page .kv-kkarte { min-height: 0; justify-content: flex-start; }
}

/* =========================================================================
   41. Mobiler Rundgang, zweite Runde (Kunde, 07.09.2026)

   Sieben Funde vom iPhone 17. Sie haben eine gemeinsame Wurzel: Werte,
   die für die ZEILE oder für den großen Bildschirm gedacht sind, wirken
   gestapelt anders — als Höhe, als Loch, als Wand.
   ========================================================================= */

/* --- Ein px-Wert in `flex-basis` ist gestapelt eine HÖHE ---------------

   Vierter Fall derselben Falle nach den WPForms-Spalten, dem Hero- und
   dem Band-Text. Gemessen bei 390–402 px:

   | Stelle              | Basis  | Inhalt | Wirkung                     |
   |---------------------|--------|--------|-----------------------------|
   | `.kv-fokus__bild`   | 440 px | 211 px | Motiv auf 440 px gestreckt  |
   |                     |        |        | und von `cover` beschnitten |
   | `.kv-mt__bild`      | 480 px | 235 px | 245 px Weiß unter dem Bild  |
   | `.kv-folge__text`   | 160 px | ~100   | Loch über „Anhören"         |
   | `.kv-recht__text`   | 520 px | —      | ohne Wirkung, aber falsch   |
   | `.kv-edetail__text` | 520 px | —      | ohne Wirkung, aber falsch   |

   Die Schwelle ist je Bauteil die, an der sein Elternteil auf `column`
   dreht — nachgemessen, nicht geraten: Medien+Text, Im Fokus und die
   Rechtstexte bei 900, das Veranstaltungsdetail bei 1000, die
   Podcast-Folge erst bei 700. Ein zu früher Umschalter würde die BREITE
   in der Zeile zerlegen.
   --------------------------------------------------------------------- */
@media (max-width: 1000px) {
	.kv-page .kv-edetail__text { flex-basis: auto; }
}

@media (max-width: 900px) {
	.kv-page .kv-fokus__bild,
	.kv-page .kv-fokus__text,
	.kv-page .kv-mt__bild,
	.kv-page .kv-mt__text,
	.kv-page .kv-recht__text { flex-basis: auto; }
}

@media (max-width: 700px) {
	.kv-page .kv-folge__text { flex-basis: auto; }
}

/* --- Der Hero zeigt mobil das Motiv, nicht die Angaben ----------------

   Auf 402 px füllten Überschrift, Lead, zwei Buttons UND die Infoleiste
   (Termin, Ort, Kategorie) die ganze Bühne — vom Foto blieb nichts
   übrig. Der Kunde: „Da sieht man ja gar nichts mehr vom Bild. Blende
   hier bitte das Element mit Termin, Ort, Kategorie mobil aus."

   Die Angaben sind nicht verloren: der Button „Zur Veranstaltung" führt
   auf die Seite, die sie vollständig zeigt, und die Terminliste
   darunter nennt Datum und Ort je Karte.

   Grenze 700, nicht 900: auf dem Tablet ist Platz für beides.
   --------------------------------------------------------------------- */
@media (max-width: 700px) {
	.kv-page .kv-hero__leiste { display: none; }
}

/* --- Wolken-Hero: kein weißer Streifen, keine leere Halle -------------

   Zwei Funde des Kunden an einem Element.

   OBEN stand ein 96 px hoher WEISSER Streifen zwischen Kopfzeile und
   Wolke: der Abschnitt trägt die Farbe des folgenden (damit die Maske
   weich ausblenden kann), und `padding-top: 96px` an IHM ist deshalb
   sichtbares Weiß — nicht Luft im farbigen Feld. Das Polster gehört an
   die Fläche, und dort sind 140 px auf dem Telefon zu viel.

   UNTEN sind es 240 px Polster plus 200 px Ausblendung. Auf 1440 px ist
   das der Auslauf der Weichzeichnung, auf 402 px eine leere Halle
   zwischen Lead und Filterleiste.

   `!important` und drei Klassen, weil die Polsterstufe aus dem Panel
   (`.kv-po-140`) selbst `!important` trägt: der Wert ist die Absicht für
   den großen Bildschirm, die Stufe hier die für das Telefon.
   Das Verhältnis Polster > Ausblendung bleibt (140 > 120), sonst
   verblasst der Inhalt mit.
   --------------------------------------------------------------------- */
@media (max-width: 900px) {
	.kv-page .kv-wolkenhero { padding-top: 0; }

	.kv-page .kv-wolkenhero .kv-wolkenhero__flaeche {
		padding-top: 88px !important;
	}

	.kv-page .kv-wolkenhero--flach .kv-wolkenhero__flaeche {
		padding-top: 72px !important;
	}

	/* 112/88 statt 140/120 — zweiter Wunsch des Kunden am selben Element
	   („Mobil wäre es nochmal sensationell, wenn wir hier den Abstand noch
	   etwas verringern könnten"). Das Verhältnis bleibt: 24 px Luft
	   zwischen Textende und Beginn der Ausblendung. */
	.kv-page .kv-wolkenhero .kv-wolkenhero__flaeche.kv-wolke-buehne {
		padding-bottom: 112px;
		mask-image: linear-gradient(180deg, #000 calc(100% - 88px), transparent 100%);
		-webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 88px), transparent 100%);
	}
}

/* --- Terminkarten: wo endet die eine, wo beginnt die nächste? ---------

   Einspaltig war der Abstand ZWISCHEN zwei Karten (24 px im Rhythmus-
   Raster) genauso groß wie der Abstand INNERHALB einer Karte zwischen
   Motiv und Text (24 px). Damit ist die Gruppierung aufgehoben — der
   Kunde sah auf dem Telefon nicht, wo eine Veranstaltung aufhört.

   Der Kartenabstand ist jetzt mehr als das Doppelte des inneren. Gilt
   für beide Raster: den wechselnden Rhythmus (Events & Tickets) und die
   Füll-Variante (Archiv und „Weitere Veranstaltungen").
   --------------------------------------------------------------------- */
@media (max-width: 700px) {
	.kv-page .kv-eliste__raster,
	.kv-page .kv-eliste__raster--rhythmus,
	.kv-page .kv-eliste__raster--fuellen,
	.kv-page .kv-eliste__raster--fuellen--s2 { gap: 32px 16px; }

	/* UND EINE LINIE DAZWISCHEN (Kunde: „Ich denke hier wäre eine Linie
	   zur Abgrenzung gut").
	 *
	 * Sie sitzt an der Karte, nicht am Raster: dann trennt sie genau
	 * dort, wo eine Karte auf die nächste folgt.
	 *
	 * `:not([hidden]) ~ :not([hidden])` — der Geschwisterwähler löst das
	 * Problem, das eine Linie am unteren Rand hätte: gefiltert wird über
	 * das `hidden`-Attribut, und `:last-child` kann versteckt sein. So
	 * bekommt jede SICHTBARE Karte, vor der eine sichtbare steht, ihre
	 * Linie — die erste keine, die letzte auch dann keine, wenn die
	 * Karten darunter weggefiltert sind.
	 *
	 * 32 px Gap oben, 32 px Polster unter der Linie: die Trennung sitzt
	 * mittig zwischen zwei Karten. */
	.kv-page .kv-eliste__raster .kv-ekarte:not([hidden]) ~ .kv-ekarte:not([hidden]) {
		padding-top: 32px;
		border-top: 1px solid var(--kv-ink-12);
	}
}

/* --- Brotkrume: mobil eine Zeile -------------------------------------

   „STARTSEITE / EVENTS & TICKETS / LOVESONG COLLECTIVE" braucht auf
   402 px zwei Zeilen. Der Kunde: „Wäre cool, wenn die Breadcrumb in
   eine Zeile geht. Vielleicht lassen wir hier die erste Ebene
   ‚Startseite' weg." — die Kopfzeile führt mit dem Logo dorthin.

   Das allein genügt aber nicht für JEDE Veranstaltung: „Kulturhören
   Live — 70 Jahre BRAVO mit Alex Gernandt" bricht auch zu zweit um.
   Deshalb bleibt die Zeile hier ungebrochen, und die laufende Seite
   kürzt mit Auslassungspunkten. Sie steht unmittelbar darunter als
   Überschrift — verloren geht dadurch nichts.
   --------------------------------------------------------------------- */
@media (max-width: 700px) {
	.kv-page .kv-krume__start { display: none; }

	/* Der Trenner steht per `li + li::before` vor jedem Punkt AUSSER dem
	   ersten. Ist der erste ausgeblendet, hat der zweite trotzdem einen
	   Vorgänger — die Krume begann mit einem einsamen „/". */
	.kv-page .kv-krume__start + li::before { content: none; }

	.kv-page .kv-krume ol { flex-wrap: nowrap; }

	/* Auch die MITTLERE Stufe darf nicht umbrechen: auf 320 px stand
	   „Events & / Tickets" zweizeilig, und damit war die Zeile wieder
	   zwei Zeilen hoch — obwohl Platz für die Krume da war. Sie behält
	   ihre Breite, gekürzt wird nur die laufende Seite. */
	.kv-page .kv-krume li,
	.kv-page .kv-krume li a { white-space: nowrap; }

	.kv-page .kv-krume li:not(:last-child) { flex: 0 0 auto; }

	.kv-page .kv-krume li:last-child {
		min-width: 0;
		overflow: hidden;
	}

	.kv-page .kv-krume li:last-child > * {
		overflow: hidden;
		white-space: nowrap;
		text-overflow: ellipsis;
	}
}

/* --- Filterleiste: mobil zugeklappt ----------------------------------

   Im Archiv stehen zwölf Kategorien und zehn Jahre. Einspaltig füllen
   sie eine halbe Seite, bevor die erste Veranstaltung kommt — der
   Kunde: „Die Filterung bitte ausklappbar machen."

   Der Umschalter ist ein `<summary>`, also Browsersache: ohne
   JavaScript bleibt das `open` aus dem Markup stehen und die Leiste ist
   offen. Auf breiten Geräten ist der Umschalter ausgeblendet und das
   `<details>` nur eine Hülle — deshalb trägt es die Flexwerte, die
   vorher an `.kv-filter__reihen` standen.
   --------------------------------------------------------------------- */
.kv-page .kv-filter__box {
	flex: 1 1 480px;
	min-width: 0;
}

.kv-page .kv-filter__auf {
	display: none;
}

/* Kein Dreieck: die Zeile bekommt ihren eigenen Pfeil (Chevron wie in
   der mobilen Navigation), damit sie zur Seite gehört. */
.kv-page .kv-filter__auf::-webkit-details-marker { display: none; }
.kv-page .kv-filter__auf::marker { content: ''; }

@media (max-width: 700px) {
	.kv-page .kv-filter__box { flex: 1 1 100%; }

	.kv-page .kv-filter__auf {
		display: flex;
		align-items: center;
		gap: 12px;
		min-height: 44px;
		padding: 10px 14px;
		border-radius: var(--kv-r-mini);
		background: var(--kv-soft);
		cursor: pointer;
		font-family: var(--kv-label);
		font-size: 12px;
		line-height: 16px;
		letter-spacing: 1px;
		text-transform: uppercase;
		color: var(--kv-ink);
		list-style: none;
	}

	/* Der aktive Stand steht rechts und ist die Antwort auf „wonach ist
	   gerade gefiltert?" — ohne dass man aufklappen muss. */
	.kv-page .kv-filter__stand {
		margin-left: auto;
		color: var(--kv-ink-50);
		text-transform: none;
		letter-spacing: 0;
		font-family: var(--kv-text);
		font-size: 14px;
	}

	.kv-page .kv-filter__auf::after {
		content: '';
		flex: 0 0 auto;
		width: 12px;
		height: 12px;
		background: currentColor;
		mask: url('../img/icon-chevron-right.svg') center / contain no-repeat;
		-webkit-mask: url('../img/icon-chevron-right.svg') center / contain no-repeat;
		transform: rotate(90deg);
		transition: transform 200ms cubic-bezier(0.2, 0.7, 0.2, 1);
	}

	.kv-page .kv-filter__box[open] .kv-filter__auf::after {
		transform: rotate(-90deg);
	}

	/* Aufgeklappt braucht die Leiste Luft zum Umschalter. */
	.kv-page .kv-filter__box[open] .kv-filter__reihen {
		padding-top: 20px;
	}
}

/* =========================================================================
   42. Warenkorb: Symbol in der Kopfzeile, Weg zurück in der Kasse
       (Kunde, 07.09.2026)

   Der Entwurf kennt keinen Warenkorb — er zeigt eine Seite ohne Verkauf.
   Mit Bold Tickets und WooCommerce gibt es einen, und wer drei Karten
   gewählt hat, muss sehen, dass sie irgendwo liegen. Das Symbol erscheint
   deshalb NUR, wenn etwas drin liegt (die PHP-Seite gibt sonst nichts
   aus); ein dauerhaftes Einkaufswagen-Symbol wäre auf dieser Seite ein
   Fremdkörper.
   ========================================================================= */

.kv-page .kv-warenkorb {
	position: relative;
	display: inline-flex;
	flex: 0 0 auto;
	align-items: center;
	justify-content: center;
	/* 44 × 44 wie der Umschalter: eine Trefferfläche für den Finger,
	   auch wenn das Symbol nur 24 px groß ist. */
	width: 44px;
	height: 44px;
	color: var(--kv-ink);
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
	transition: color var(--kv-t-schnell);
}

/* Als Maske mit `currentColor`, wie das Chevron: dann wechselt das
   Symbol die Farbe mit dem Text und nicht per zweiter Datei. */
.kv-page .kv-warenkorb__symbol {
	width: 24px;
	height: 24px;
	/* Zwei Pixel nach unten links, damit das Abzeichen in der oberen
	   rechten Ecke Platz hat und nicht auf dem Griff der Tasche sitzt. */
	transform: translate(-2px, 2px);
	background: currentColor;
	mask: url('../img/icon-warenkorb.svg') center / contain no-repeat;
	-webkit-mask: url('../img/icon-warenkorb.svg') center / contain no-repeat;
}

/* Das Abzeichen sitzt auf dem Symbol und trägt einen Ring in der
   Grundfarbe: ohne ihn verschwimmen Zahl und Symbolkante. */
.kv-page .kv-warenkorb__zahl {
	position: absolute;
	/* Am Symbol, nicht am Kasten: die Trefferfläche ist 44 px, das Symbol
	   nur 24 — mit `top: 3px` schwebte die Zahl neun Pixel über der
	   Tasche. Diese Werte setzen sie auf ihre obere rechte Ecke. */
	top: 4px;
	right: 3px;
	min-width: 16px;
	height: 16px;
	padding: 0 4px;
	border-radius: 8px;
	background: var(--kv-rot);
	box-shadow: 0 0 0 2px var(--kv-weiss);
	font-family: var(--kv-label);
	font-size: 10px;
	line-height: 16px;
	letter-spacing: 0;
	text-align: center;
	color: var(--kv-weiss);
}

@media (hover: hover) {
	.kv-page .kv-warenkorb:hover { color: var(--kv-rot); }
}

.kv-page .kv-warenkorb:active { color: var(--kv-rot); }

/* Mit Warenkorb stehen auf schmalen Geräten drei Dinge in der Reihe:
   Logo (150), Symbol (44), Umschalter (44). Bei 320 px und 24 px Abstand
   ging das nicht auf — der Umschalter wurde auf 31 px zusammengedrückt
   und war damit keine Trefferfläche mehr. Beide behalten ihre 44 px, der
   Abstand gibt nach. */
@media (max-width: 480px) {
	.kv-page .kv-kopf__rechts { gap: 8px; }
}

.kv-page .kv-burger,
.kv-page .kv-warenkorb { flex: 0 0 auto; }

/* --- Die Kasse steht auf der Achse -----------------------------------

   Die Block-Kasse trägt `alignwide`, und das heißt in WordPress
   `max-width: 120%` — sie ragte 103 px links aus unserer Spur heraus,
   während die Überschrift „Kasse" bei 206 px begann. Zwei Kanten, 103 px
   auseinander, auf derselben Seite.

   Die Kasse folgt jetzt der Spur, die auch das Beitrittsformular und die
   Bestellbestätigung benutzen (1028 px): Überschrift, Formular und
   Bestellübersicht beginnen auf derselben Kante. Der Alternativweg wäre
   gewesen, die Überschrift auf 1234 px zu verbreitern — dann hätte die
   Kasse eine Breite, die auf keiner anderen Seite vorkommt.
   --------------------------------------------------------------------- */
.kv-page.woocommerce-page #brx-content .alignwide,
.kv-page.woocommerce-page #brx-content .wp-block-woocommerce-checkout,
.kv-page.woocommerce-page #brx-content .wp-block-woocommerce-cart {
	max-width: 100%;
	margin-inline: 0;
}

/* --- „Warenkorb bearbeiten" ------------------------------------------

   Die Block-Kasse bringt keinen Weg zurück mit: wer sich verzählt hat,
   kommt nur über den Zurück-Button des Browsers heraus. Der Verweis steht
   über dem Formular, wo man ihn sucht, und trägt sein Chevron nach links.
   --------------------------------------------------------------------- */
.kv-page .kv-kasse__zurueck {
	margin: 0 0 24px;
}

.kv-page .kv-link--zurueck .kv-chevron {
	transform: rotate(180deg);
}

/* =========================================================================
   43. Warenkorb und Kasse: die Blöcke von WooCommerce ins Haus holen
       (Kunde, 07.09.2026)

   Bisher stand hier nur die Breite und die Farbe der Meldungen. Was der
   Kunde am Bildschirm gesehen hat, waren aber die BEDIENTEILE: Buttons im
   Browsergrau, Häkchen und Punkte im WooCommerce-Blau-Grau, und drei
   graue Platzhalter statt Motive.

   Weiter gilt: nur das Nötige. Tabellen und Zwischensummen bleiben, wie
   WooCommerce sie setzt.
   ========================================================================= */

/* --- Die Motive: quadratisch, wie im Rest der Seite -------------------
   Das Bild kommt aus `kv_ticket_produktbild()` (Beitragsbild der
   Veranstaltung). Zugeschnitten wird hier, nicht über eine eigene
   Bildgröße — sonst wären für hundert vorhandene Bilder Miniaturen
   nachzurechnen. */
.kv-page .wc-block-cart-item__image img,
.kv-page .wc-block-components-order-summary-item__image img {
	aspect-ratio: 1 / 1;
	width: 100%;
	height: auto;
	object-fit: cover;
	border-radius: var(--kv-r-mini);
	background: var(--kv-soft);
}

/* --- Häkchen und Punkte: die Bauart des Hauses ------------------------

   WooCommerce zeichnet seine Kästchen selbst (`appearance: none` plus
   Rahmen und ein Pseudoelement für den Haken). Damit stehen auf einer
   Seite zwei Bauarten: die Häkchen im Beitrittsformular sind NATIVE
   Felder mit `accent-color` in der Hausfarbe, die in der Kasse waren
   fremd — und 26 × 20 px, also gestaucht, weil sie als Flex-Kind in die
   Breite gezogen wurden.

   Hier also derselbe Weg wie im Formular: native Felder, 18 px, Akzent
   in Hausrot. Die Zeichnung von WooCommerce wird dafür abgeräumt. */
.kv-page .wc-block-components-checkbox__input,
.kv-page .wc-block-components-radio-control__input {
	appearance: auto;
	-webkit-appearance: auto;
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
	min-width: 18px;
	margin: 2px 8px 0 0;
	border: 0;
	border-radius: 0;
	background: none;
	box-shadow: none;
	accent-color: var(--kv-rot);
}

/* Der selbstgezeichnete Haken von WooCommerce liegt als Pseudoelement
   über dem Feld — mit einem nativen Feld darunter wären es zwei Haken. */
.kv-page .wc-block-components-checkbox__input::before,
.kv-page .wc-block-components-checkbox__input::after,
.kv-page .wc-block-components-checkbox__mark,
.kv-page .wc-block-components-radio-control__input::before,
.kv-page .wc-block-components-radio-control__input::after {
	display: none;
}

/* --- Die Buttons: rot, nicht Browsergrau ------------------------------

   „Weiter zur Kasse" ist ein `<a>` mit `wp-element-button`; ohne die
   Blockdesign-Werte des Themes bleibt davon ein roter Text auf weißem
   Grund — der Kunde hat ihn zu Recht „unsichtbar" genannt. „Zahlungs-
   pflichtig bestellen" ist ein echter Button und kam in #EFEFEF, dem
   Grau des Browsers.

   Beide bekommen den Primärknopf des Entwurfs. Textknöpfe (etwa
   „Bearbeiten" an der Adresse) sind ausgenommen — die sind Verweise. */
.kv-page .wc-block-cart__submit-button,
.kv-page .wc-block-components-checkout-place-order-button,
/* Der Button im leeren Warenkorb („Zu den Veranstaltungen") ist ein
   Block-Button; ohne diese Zeile bleibt davon ein roter Text. Gutenberg
   ist auf dieser Seite abgeschaltet, die Klasse kommt also nur hier vor. */
.kv-page #brx-content .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	width: 100%;
	min-height: 48px;
	padding: 12px 24px;
	border: 0;
	border-radius: var(--kv-r-mini);
	background: var(--kv-rot);
	font-family: var(--kv-text);
	font-size: 16px;
	line-height: 24px;
	font-weight: 400;
	color: var(--kv-weiss);
	text-decoration: none;
	cursor: pointer;
	transition: background var(--kv-t-schnell);
}

@media (hover: hover) {
	.kv-page .wc-block-cart__submit-button:hover,
	.kv-page .wc-block-components-checkout-place-order-button:hover,
	.kv-page #brx-content .wp-block-button__link:hover {
		background: var(--kv-rot-dunkel, #6f1713);
		color: var(--kv-weiss);
	}
}

/* Im leeren Warenkorb ist es ein Angebot, kein Abschluss: der Button
   nimmt nur seine Textbreite. */
.kv-page #brx-content .wp-block-button__link {
	width: auto;
}

.kv-page .wc-block-cart__submit-button:active,
.kv-page .wc-block-components-checkout-place-order-button:active {
	background: var(--kv-rot-dunkel, #6f1713);
}

/* Ein Button, der gerade nicht kann, muss das zeigen — sonst tippt man
   dagegen. */
.kv-page .wc-block-components-checkout-place-order-button:disabled {
	background: var(--kv-ink-12);
	color: var(--kv-ink-50);
	cursor: not-allowed;
}

/* --- Mollie: der Hinweis unter den Kartenfeldern braucht Luft ---------

   „Secure payments provided by mollie" ist das letzte Kind von
   `.mollie-payment-method-container` und trägt **keine Klasse** — die
   Zeile klebte deshalb am Feld darüber und an der Kastenkante darunter.
   Angesprochen wird sie über ihre Stellung; das ist die einzige
   Handhabe, die das Plugin lässt. Kommt dort einmal etwas anderes
   dazu, greift die Regel am falschen Element — dann sitzt hier eine
   Klasse, sobald Mollie eine mitliefert.

   Die Kartenfelder selbst liegen in iframes von Mollie und sind von
   außen nicht gestaltbar. Das Deutsch der Beschriftungen („Name on
   card") kommt ebenfalls von dort.
   --------------------------------------------------------------------- */
.kv-page .mollie-payment-method-container > div:last-child {
	margin-top: 16px;
	padding-bottom: 4px;
}

.kv-page .mollie-component-wrapper {
	margin-bottom: 12px;
}

/* --- WPForms: eine einzeilige Auswahl ist nur 20 px hoch --------------

   `mobil.js` hat es gemeldet: bei 768 px passt die Einwilligung des
   Beitrittsformulars in EINE Zeile, und damit ist die Trefferfläche
   20 px hoch — unter den 24, die als Mindestmaß gelten (WCAG 2.5.8).
   Ein Klick auf die Beschriftung schaltet das Häkchen, also ist die
   Beschriftung die Fläche. Sechs Pixel oben und unten, wie bei den
   Textlinks: Schrift gleich, Fläche größer.
   --------------------------------------------------------------------- */
@media (max-width: 900px) {
	.kv-page .wpforms-field-checkbox label,
	.kv-page .wpforms-field-gdpr-checkbox label,
	.kv-page .wpforms-field-radio label {
		padding-block: 6px;
	}
}

/* --- Der Warenkorb passt auf 320 px ----------------------------------

   Die Positionsliste des Warenkorbs ist eine echte `<table>`. Eine
   Tabelle wächst auf die Breite ihres Inhalts, egal wie eng der Kasten
   ist: Motiv (64) + Titel + Mengenwahl + Summe ergaben 326 px in einem
   269 px breiten Feld — 33 px Überbreite, sichtbar als abgeschnittene
   Preisspalte und ein Button, der rechts hinausläuft.

   `table-layout: fixed` dreht das Verhältnis um: die Spalten teilen sich
   die vorhandene Breite, statt sie zu fordern. Dazu ein Umbruch für
   lange Ticketnamen („Lovesong Collective — Schüler, Studenten &
   Rentner") und eine schmalere Mengenwahl.

   Erst unter 480 px: auf breiteren Geräten hat die Tabelle Platz, und
   `fixed` würde die Spalten unnötig gleich behandeln.
   --------------------------------------------------------------------- */
@media (max-width: 480px) {
	.kv-page .wc-block-cart-items {
		table-layout: fixed;
		width: 100%;
	}

	.kv-page .wc-block-cart-item__image {
		width: 64px;
	}

	.kv-page .wc-block-cart-item__product {
		overflow-wrap: anywhere;
	}

	.kv-page .wc-block-cart-item__total {
		min-width: 0;
		text-align: right;
	}

	/* Die Zeile ist ein Raster mit VIER Spalten — `80px 132px 11px 72px`
	   plus 3 × 16 px Abstand macht 343 px in einem 265 px breiten Feld.
	   Das ist die Vorgabe von WooCommerce und passt auf 320 px nicht.
	   Drei Spalten, die mittlere flexibel: Motiv, Text, Summe. */
	/* Mit `!important` und einer Klasse mehr, weil WooCommerce dieselben
	   Eigenschaften spezifischer setzt: gemessen blieben sonst seine
	   Spalten (80/132/21) und die Summe in Reihe 1 stehen. */
	.kv-page .wc-block-cart-items .wc-block-cart-items__row {
		grid-template-columns: 64px minmax(0, 1fr) !important;
		column-gap: 12px !important;
	}

	/* Zwei Reihen, ausdrücklich zugewiesen: das Motiv links über beide,
	   rechts oben der Name mit Mengenwahl, darunter die Summe. Ohne die
	   Zuweisung setzt das Raster die Summe von selbst in die erste Reihe
	   — dann steht sie ÜBER dem Namen und überlappt ihn. */
	.kv-page .wc-block-cart-items .wc-block-cart-item__image {
		grid-area: 1 / 1 / span 2 / 2 !important;
	}

	.kv-page .wc-block-cart-items .wc-block-cart-item__product {
		grid-area: 1 / 2 / 2 / 3 !important;
	}

	/* Die Summe der Position steht UNTER dem Namen, statt neben ihm um
	   Platz zu ringen: „Julz Giuliani — Schüler, Studenten & Rentner"
	   braucht zwei Zeilen, und die zweite lief in den Preis. */
	.kv-page .wc-block-cart-items .wc-block-cart-item__total {
		grid-area: 2 / 2 / 3 / 3 !important;
		justify-self: start;
		margin-top: 4px;
		text-align: left;
	}

	/* Die Mengenwahl ist ein eigener Kasten mit drei Feldern; ohne
	   Deckelung fordert sie mehr, als die Spalte hat. */
	.kv-page .wc-block-components-quantity-selector {
		max-width: 108px;
		min-width: 0;
	}
}

/* --- Der Hero ist mobil eine Bildkachel ------------------------------

   Wunsch des Kunden (07.09.2026): das erste Element der Startseite soll
   auf dem Telefon nicht die Bühne mit Überschrift, Lead und zwei Buttons
   sein, sondern die Form, die auf derselben Seite schon dreimal vorkommt
   — die Bildkachel. Rubrik und Datum oben, Titel, Ort und Preis unten,
   dazu ein Textlink.

   Beides steht im Markup (siehe `hero-event.php`), umgeschaltet wird
   hier: die Breite kennt nur der Browser. Was nicht gilt, steht auf
   `display: none` und ist damit auch für Screenreader weg — es gibt also
   immer genau EINE Überschrift.

   Die Schwelle ist 700: auf dem Tablet hat die Bühne Platz, und dort
   wirkt die Kachel verloren.
   --------------------------------------------------------------------- */
.kv-page .kv-hero__kachel {
	display: none;
}

@media (max-width: 700px) {
	.kv-page .kv-hero__buehne {
		display: none;
	}

	/* Oben genauso viel Luft wie an den Seiten (Kunde, 07.09.2026): der
	   Abschnitt trägt dort schon `--kv-rand`. Die 24 px, die hier
	   standen, kamen obendrauf — 56 gegen 32. Ohne sie ist der Abstand
	   auf allen drei Seiten derselbe und wandert mit der Breite
	   (26 / 31 / 32 px). */
	.kv-page .kv-hero__kachel {
		display: block;
	}

	/* Etwas höher als die Kacheln in der Reihe: sie ist die erste Fläche
	   der Seite und trägt das Motiv der nächsten Veranstaltung. */
	.kv-page .kv-kachel--hero {
		min-height: 520px;
	}
}

/* --- Die Infokarte füllt gestapelt die Spalte -------------------------

   Ohne Ticketauswahl war die Karte schmaler als mit: gestapelt ist die
   Randspalte ein Flex-Kasten mit `flex-basis: auto`, also so breit wie
   ihr Inhalt — und ohne die breite Ticketliste bleibt nur der Text.
   Gemessen bei 402 px: 269 statt 338, bei 768 px: 285 statt 596.

   Auf der Veranstaltung ohne Tickets (freier Eintritt) sah die Karte
   deshalb aus wie ein Versehen. In der ZEILE (ab 1000 px) ist die Breite
   von der Rasterspalte vorgegeben und stimmte immer — deshalb nur hier.
   --------------------------------------------------------------------- */
@media (max-width: 1000px) {
	.kv-page .kv-edetail__rand,
	.kv-page .kv-edetail__rand .kv-infokarte {
		width: 100%;
	}
}

/* Zwei Polster übereinander sind auf 320 px eines zu viel.
   -----------------------------------------------------------------------
   Die Mitgliederkarte sitzt IN der Infokarte: 269 px Karte − 24 Polster
   = 221, minus ihre eigenen 24 = **173 px Textfeld**, also 27 Zeichen je
   Zeile. `mobil.js` hat es über die Zeilenlänge gemeldet — und erst
   jetzt, weil die Karte erst erscheint, seit es bezahlte Ticketarten
   gibt („Mitglieder zahlen weniger" wirbt mit Ermäßigung).

   Dieselbe Antwort wie bei den anderen engen Kästen: unter 480 px sinkt
   das innere Polster. Textfeld damit 189 px, 30 Zeichen. */
@media (max-width: 480px) {
	.kv-page .kv-mitgliedkarte {
		padding: 16px;
	}
}

/* --- Auswahlfelder im Formular sind als Auswahl erkennbar -------------

   Der Jahresbeitrag ist ein `<select>`, sah aber wie ein Textfeld aus:
   `appearance: none` nimmt den Pfeil des Systems, und ein eigener war
   nie gesetzt — im Entwurf trägt das Feld den nativen Pfeil, den es hier
   nicht mehr gibt. Also derselbe Pfeil wie an der Ticketauswahl und an
   den Filterfeldern: dasselbe Zeichen für dieselbe Sache.
   --------------------------------------------------------------------- */
.kv-page .wpforms-form select {
	appearance: none;
	-webkit-appearance: none;
	padding-right: 36px;
	background-image: url('../img/icon-chevron-down.svg');
	background-repeat: no-repeat;
	background-position: right 14px center;
	background-size: 11px 6px;
	cursor: pointer;
}

/* --- „Im Fokus" gestapelt: Motiv und Text gehören zusammen -----------

   In der Zeile stehen Bild und Text nebeneinander, 48 px Abstand hält
   sie auseinander. Gestapelt ist derselbe Wert eine Lücke: das Motiv
   oben, dann eine leere Fläche, dann eine Rubrik — es sah aus wie zwei
   Sachen statt einer. Der Kunde: „dass man erkennt, was zusammengehört."

   24 px, wie zwischen Überschrift und Fließtext derselben Sektion.
   --------------------------------------------------------------------- */
@media (max-width: 700px) {
	.kv-page .kv-fokus__inner {
		gap: 24px;
	}
}

/* =========================================================================
   44. Die Fußzeile auf dem Telefon, und der Newsletter über MailPoet
       (Kunde, 07.09.2026)
   ========================================================================= */

/* --- Zwei Spalten für die Menüs ---------------------------------------

   Mobil stand die ganze Fußzeile in EINER Spalte: Marke, Newsletter,
   Navigation, Verein, Anschrift, Rechtliches — 1203 px hoch, während der
   Desktop mit 522 auskommt. „Da geht noch mehr", und zwar hier: die
   beiden Menüs haben fünf und vier kurze Punkte, die passen
   nebeneinander.

   Marke samt Newsletter bleibt über die volle Breite (das Feld braucht
   sie), die Anschrift ebenfalls — sie ist eine zusammenhängende Angabe
   und soll nicht in einer halben Spalte umbrechen.
   --------------------------------------------------------------------- */
@media (max-width: 700px) {
	.kv-page .kv-fuss__oben {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 36px 20px;
	}

	.kv-page .kv-fuss__oben > .kv-fuss__marke,
	.kv-page .kv-fuss__oben > .kv-fuss__spalte:last-child {
		grid-column: 1 / -1;
	}
}

/* --- MailPoet in der Hausschrift --------------------------------------

   Die Anmeldung läuft jetzt über MailPoet (es führt die Liste, schickt
   die Bestätigungsmail und kennt die Abmeldung — WPForms hat nur eine
   E-Mail an den Verein geschickt). Sein Formular kommt ungestaltet:
   weißes Feld mit Systemrahmen, grauer Systemknopf.

   Angesprochen wird es über seine eigenen Klassen; die Werte sind
   dieselben wie in `.kv-input` und `.kv-btn--primaer`. Die Feldbreite
   setzt MailPoet inline auf 100 %, das passt.
   --------------------------------------------------------------------- */
/* Feld und Button in EINER Zeile.
   Der Entwurf zeigt nur ein Feld — einen Absendeknopf braucht die
   Anmeldung trotzdem (siehe „Newsletter in der Fußzeile"). Untereinander
   war er ein breiter roter Block und damit das Schwerste in der ganzen
   Fußzeile; in der Zeile bleibt das Feld die Hauptsache. */
.kv-page .kv-fuss__nlform--mailpoet .mailpoet_form {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: 8px;
}

/* MailPoet gibt dem Formular 400 px feste Breite (Vorgabe seiner
   Platzierungs-Einstellungen, gesetzt per Skript — deshalb `!important`,
   ein Inline-Stil schlägt sonst jede Klassenregel). Die Spalte ist im
   Entwurf 448 px breit; jede ungenutzte Pixelbreite geht dem Feld ab. */
.kv-page .kv-fuss__nlform--mailpoet .mailpoet_form_form {
	width: 100% !important;
	max-width: 448px;
}

/* MailPoet legt jeden Block in einen eigenen Absatz. Der mit dem Feld
   wächst, der mit dem Knopf bleibt so breit wie sein Wort. */
.kv-page .kv-fuss__nlform--mailpoet .mailpoet_paragraph:has( input.mailpoet_text ),
.kv-page .kv-fuss__nlform--mailpoet .mailpoet_paragraph:has( input[type="email"] ) {
	/* 130 px als Grundmaß, nicht 200: in der Fußzeile ist die Spalte auf
	   1024 px nur 272 px breit, und mit 200 wäre die Zeile dort
	   umgebrochen — ein 117 px schmaler Knopf unter einem breiten Feld.
	   Nachgemessen bei acht Breiten. */
	flex: 1 1 130px;
	min-width: 0;
}

.kv-page .kv-fuss__nlform--mailpoet .mailpoet_paragraph:has( input.mailpoet_submit ) {
	flex: 0 0 auto;
}

/* Meldungen und alles Übrige stehen unter der Zeile, nicht daneben. */
.kv-page .kv-fuss__nlform--mailpoet > .mailpoet_form > .mailpoet_validate_success,
.kv-page .kv-fuss__nlform--mailpoet > .mailpoet_form > .mailpoet_validate_error,
.kv-page .kv-fuss__nlform--mailpoet .mailpoet_message {
	flex: 1 1 100%;
}

/* MailPoet gibt jedem Absatz 20 px Abstand nach unten — im Flex-Kasten
   ist das eine zweite Rechnung neben dem Gap.

   `!important`, weil MailPoet die Regel als `#mailpoet_form_1
   .mailpoet_paragraph` in ein <style> im Formular schreibt: eine ID
   schlägt jede Klassenkette. In der Zeile fiel das nicht auf, gestapelt
   standen 20 statt 8 px zwischen Feld und Knopf. */
.kv-page .kv-fuss__nlform--mailpoet .mailpoet_paragraph {
	margin: 0 !important;
	line-height: inherit;
}

.kv-page .kv-fuss__nlform--mailpoet input.mailpoet_text,
.kv-page .kv-fuss__nlform--mailpoet input.mailpoet_submit {
	width: 100%;
	height: 48px;
	min-height: 48px;
	padding: 12px 16px;
	border: 0;
	border-radius: var(--kv-r-mini);
	font-family: var(--kv-text);
	/* 16 px, nicht 15: so steht es im Entwurf — und Safari auf dem iPhone
	   zoomt die Seite beim Antippen jedes Feldes unter 16 px hinein. */
	font-size: 16px;
	line-height: 24px;
	font-weight: 300;
}

.kv-page .kv-fuss__nlform--mailpoet input.mailpoet_text {
	background: var(--kv-feld);
	color: var(--kv-ink);
}

.kv-page .kv-fuss__nlform--mailpoet input.mailpoet_text::placeholder {
	color: var(--kv-ink-50);
	opacity: 1;
}

.kv-page .kv-fuss__nlform--mailpoet input.mailpoet_submit {
	width: auto;
	padding-inline: 20px;
	/* Über die ganze Breite (gestapelt) stünde die Beschriftung sonst
	   links am Rand: ein <input type="submit"> erbt die Ausrichtung. */
	text-align: center;
	background: var(--kv-rot);
	color: var(--kv-weiss);
	font-weight: 400;
	white-space: nowrap;
	cursor: pointer;
	transition: background var(--kv-t-schnell);
}

/* Abstände wie im Entwurf: 8 px von der Rubrik zum Feld, 16 px vom Feld
   zur Hinweiszeile. Der Block trägt 8, die Zeile holt sich die restlichen
   8 selbst — mit einem einzigen Gap wären beide gleich. */
.kv-page .kv-fuss__nl {
	gap: 8px;
}

.kv-page .kv-fuss__nlhinweis {
	margin-top: 8px;
}

/* Die Einwilligungszeile ist länger als der eine Satz des Entwurfs —
   drei Zeilen statt einer. Der Verweis auf die Datenschutzerklärung
   bleibt erkennbar, ohne rot zu leuchten: unterstrichen in derselben
   leisen Tinte, rot erst beim Überfahren. */
.kv-page .kv-fuss__nlhinweis {
	max-width: 448px;
	text-wrap: pretty;
}

.kv-page .kv-fuss__nlhinweis a {
	color: inherit;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 2px;
	/* 12px-Schrift ergibt eine 14 px hohe Trefferfläche — zu klein zum
	   Antippen. Der erste Versuch war Polster am Verweis; das hat die
	   ZEILE höher gemacht, in der er steht (vom Kunden gesehen: „die
	   letzte Zeile hat mehr Abstand als die anderen"). Ein Polster an
	   einem Inline-Element wächst nach oben und unten aus der Zeile
	   heraus und schiebt den Zeilenkasten auf.

	   Die Fläche kommt deshalb aus einem Pseudoelement: es liegt über dem
	   Wort und darüber hinaus, ist für den Finger da und für den
	   Textfluss nicht vorhanden. */
	position: relative;
}

.kv-page .kv-fuss__nlhinweis a::after {
	content: '';
	position: absolute;
	inset: -9px -6px;
}

@media (hover: hover) {
	.kv-page .kv-fuss__nlhinweis a:hover {
		color: var(--kv-rot);
	}
}

/* Auf schmalen Geräten untereinander: „Abonnieren" und ein Feld, in das
   eine Adresse passt, gehen sich in einer Zeile sonst aus dem Weg —
   gemessen bleiben unter 400 px keine 150 px für das Feld. */
@media (max-width: 520px) {
	.kv-page .kv-fuss__nlform--mailpoet .mailpoet_paragraph:has( input.mailpoet_submit ),
	.kv-page .kv-fuss__nlform--mailpoet .mailpoet_paragraph:has( input.mailpoet_text ) {
		flex: 1 1 100%;
	}

	.kv-page .kv-fuss__nlform--mailpoet input.mailpoet_submit {
		width: 100%;
	}
}

@media (hover: hover) {
	.kv-page .kv-fuss__nlform--mailpoet input.mailpoet_submit:hover {
		background: var(--kv-rot-dunkel);
	}
}

/* --- Der CAPTCHA-Zustand ---------------------------------------------

   MailPoets eingebautes CAPTCHA (Einstellung des Vereins) tauscht das
   Formular nach dem Absenden gegen Bild, Zeichenfeld und Knopf. Ungestylt
   stand das quer in der Fußzeile: Bild mit rotem Rahmen, zwei winzige
   Symbole, ein 187 px breites Feld und die Beschriftung in der
   Du-Form (die dreht `includes/anrede.php`).

   Alle Teile liegen als Kinder des Flex-Formulars vor, deshalb bekommt
   jedes seine eigene Zeile — sonst reihen sie sich neben Feld und Knopf. */
.kv-page .kv-fuss__nlform--mailpoet .mailpoet_captcha_container {
	display: flex;
	flex: 1 1 100%;
	/* MailPoet: `margin: 0 auto 20px; max-width: 300px; text-align: center`
	   — mittig zentriert und auf 300 px gedeckelt. In einer linksbündigen
	   Fußzeilenspalte stand damit alles in der Mitte und der Knopf war
	   300 px breit, während daneben 148 px leer blieben. */
	max-width: none;
	flex-wrap: wrap;
	align-items: center;
	margin: 0;
	text-align: left;
	justify-content: flex-start;
	gap: 8px;
}

.kv-page .kv-fuss__nlform--mailpoet .mailpoet_captcha_image_wrapper,
.kv-page .kv-fuss__nlform--mailpoet .mailpoet_captcha_label,
.kv-page .kv-fuss__nlform--mailpoet .mailpoet_captcha_submit {
	flex: 1 1 100%;
	/* MailPoet gibt dem Bildkasten 10 px nach unten — im Flex-Kasten wäre
	   das eine zweite Rechnung neben dem Gap (18 statt 8). */
	margin: 0;
}

.kv-page .kv-fuss__nlform--mailpoet img.mailpoet_captcha {
	display: block;
	margin: 0;
	width: 220px;
	max-width: 100%;
	height: auto;
	border: 0;
	border-radius: var(--kv-r-mini);
	background: var(--kv-feld);
}

/* „Neu laden" und „Abspielen": 44 px Trefferfläche, wie überall sonst. */
.kv-page .kv-fuss__nlform--mailpoet button.mailpoet_icon_button {
	display: inline-flex;
	width: 44px;
	height: 44px;
	align-items: center;
	justify-content: center;
	padding: 0;
	border: 0;
	border-radius: var(--kv-r-mini);
	background: transparent;
	cursor: pointer;
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
}

.kv-page .kv-fuss__nlform--mailpoet button.mailpoet_icon_button img {
	width: 20px;
	height: 20px;
	opacity: 0.6;
	transition: opacity var(--kv-t-schnell);
}

@media (hover: hover) {
	.kv-page .kv-fuss__nlform--mailpoet button.mailpoet_icon_button:hover img {
		opacity: 1;
	}
}

.kv-page .kv-fuss__nlform--mailpoet .mailpoet_captcha_label {
	display: flex;
	flex-direction: column;
	gap: 8px;
	margin: 0;
}

.kv-page .kv-fuss__nlform--mailpoet .mailpoet_captcha_label .mailpoet_text_label {
	font-family: var(--kv-text);
	font-size: 13px;
	line-height: 20px;
	font-weight: 300;
	color: var(--kv-ink-72);
}

/* Das Zeichenfeld ist ein `input[type=text]` — die Regel oben greift über
   die Klasse mit, den Rahmen von MailPoet nehmen wir ihm ausdrücklich. */
.kv-page .kv-fuss__nlform--mailpoet .mailpoet_captcha_label input.mailpoet_text {
	/* `!important` gegen `#mailpoet_form_1 .mailpoet_text { width: 200px }`
	   — eine ID schlägt jede Klassenkette. Das E-Mail-Feld entkam dem nur,
	   weil MailPoet ihm ein Inline-`width:100%` mitgibt; das Zeichenfeld
	   bekommt keines. Und `max-width` deckelt MailPoet auf die Bildbreite. */
	width: 100% !important;
	max-width: none !important;
	border: 0;
}

/* Der Fokusring hier in Tinte, nicht in Rot: MailPoet setzt den Fokus
   beim Erscheinen selbst ins Feld — ein roter Rahmen wäre das Erste, was
   man sieht, und liest sich wie ein Fehler. Dieselbe Entscheidung wie an
   der Mengenauswahl im Ticketformular. */
.kv-page .kv-fuss__nlform--mailpoet .mailpoet_captcha_label input.mailpoet_text:focus-visible {
	outline: 2px solid var(--kv-ink-72);
	outline-offset: 2px;
}

.kv-page .kv-fuss__nlform--mailpoet .mailpoet_captcha_submit {
	margin: 0;
	text-align: left;
}

/* Der Knopf trägt ein Inline-`width:100%`; ohne `!important` bliebe er so
   breit wie die Spalte — im gewöhnlichen Zustand ist er 122 px, und beides
   nebeneinander sähe nach zwei verschiedenen Knöpfen aus. */
.kv-page .kv-fuss__nlform--mailpoet .mailpoet_captcha_submit input.mailpoet_submit {
	width: auto !important;
	max-width: none;
}

@media (max-width: 520px) {
	.kv-page .kv-fuss__nlform--mailpoet .mailpoet_captcha_submit input.mailpoet_submit {
		width: 100% !important;
	}
}

/* Meldungen: ruhige Fläche mit dem Punkt in der Hausfarbe, wie auf den
   WooCommerce-Seiten. Ampelfarben kommen im Entwurf nicht vor. */
.kv-page .kv-fuss__nlform--mailpoet .mailpoet_validate_success,
.kv-page .kv-fuss__nlform--mailpoet .mailpoet_validate_error,
.kv-page .kv-fuss__nlform--mailpoet .parsley-errors-list {
	margin: 0;
	padding: 0;
	list-style: none;
	font-family: var(--kv-text);
	font-size: 13px;
	line-height: 20px;
	color: var(--kv-ink-72);
}

/* Rot bleibt den FELD-Fehlern (Parsley). Die Meldung des Formulars ist
   nicht immer ein Fehler: „Bitte bestätigen Sie noch, dass Sie kein
   Automat sind" ist die Ankündigung des nächsten Schritts — in Rot liest
   sie sich wie ein Vorwurf. */
.kv-page .kv-fuss__nlform--mailpoet .parsley-errors-list li {
	color: var(--kv-rot);
}

.kv-page .kv-fuss__nlform--mailpoet .mailpoet_validate_error {
	color: var(--kv-ink-72);
}

/* --- Häkchen und Punkte: selbst gezeichnet ----------------------------

   Dritter Anlauf, und die beiden davor sind die Begründung:

   1. WooCommerces eigene Zeichnung — fremd im Bild („Häkchen und Punkte
      fremd"), dazu als Flex-Kind auf 26 × 20 px gestaucht.
   2. NATIVE Felder mit `accent-color` in Hausrot, wie im
      Beitrittsformular. Auf dem Desktop richtig, in Safari auf dem
      iPhone nicht: dort zeichnet das System einen gefüllten dunkelroten
      Kreis mit hellem Kern, und ein leeres Kästchen sieht nicht wie
      etwas aus, das man antippen kann („Das Feld lässt sich nicht
      anklicken. Zumindest nicht optisch.").
   3. Selbst gezeichnet: `appearance: none` und zwei Pseudoelemente. Auf
      jedem Gerät dasselbe Bild — ein Rahmen, der auf ein leeres Feld
      hinweist, und im Zustand „an" die Hausfarbe.

   Der Haken ist ein gedrehtes Winkelstück aus zwei Rahmenkanten, kein
   Bild und keine Zeichensatz-Ikone: er skaliert mit und braucht keine
   zweite Datei.
   --------------------------------------------------------------------- */
/* Mit einer Klasse mehr und `!important` an den Maßen: WooCommerce setzt
   Breite und Rahmen spezifischer, gemessen blieben sonst 26 × 20 px
   stehen — ein gestauchter Kreis. */
/* KEIN `position` hier!
 *
 * WooCommerce setzt das Feld `absolute` mit einem `top`, das aus der
 * Zeilenhöhe gerechnet ist. Ein `position: relative` von uns lässt
 * denselben `top`-Wert plötzlich als VERSCHIEBUNG wirken — gemessen
 * 302 px: das Feld stand weit unter seiner Beschriftung. Gezeichnet wird
 * deshalb mit `background-image`, nicht mit einem Pseudoelement; dann
 * braucht es keinen Bezugsrahmen. */
.kv-page .wc-block-components-checkbox .wc-block-components-checkbox__input,
.kv-page .wc-block-components-radio-control .wc-block-components-radio-control__input,
.kv-page .wc-block-components-checkbox__input,
.kv-page .wc-block-components-radio-control__input {
	appearance: none;
	-webkit-appearance: none;
	flex: 0 0 auto;
	width: 20px !important;
	height: 20px !important;
	min-width: 20px !important;
	/* WooCommerce gibt dem Feld `padding: 0 12px`. Mit `border-box`
	   gewinnt das Polster gegen die Breite: 12 + 12 + 2 = 26 px, und aus
	   dem Kreis wurde ein Ei. */
	padding: 0 !important;
	margin: 1px 12px 0 0;
	border: 1px solid var(--kv-ink-24) !important;
	background: var(--kv-weiss);
	box-shadow: none;
	cursor: pointer;
	transition: background var(--kv-t-schnell), border-color var(--kv-t-schnell);
}

.kv-page .wc-block-components-checkbox__input { border-radius: 4px; }
.kv-page .wc-block-components-radio-control__input { border-radius: 50%; }

/* Haken als SVG im Hintergrund, weiß auf Hausrot. */
.kv-page .wc-block-components-checkbox__input:checked {
	border-color: var(--kv-rot) !important;
	background-color: var(--kv-rot);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M1.8 6.4l2.9 2.9 5.5-6' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
	background-size: 12px 12px;
	background-position: center;
	background-repeat: no-repeat;
}

/* Punkt als Verlauf: ein harter Farbstopp ist ein Kreis, und der
   braucht kein zweites Element. */
.kv-page .wc-block-components-radio-control__input:checked {
	border-color: var(--kv-rot) !important;
	background-image: radial-gradient(circle at center, var(--kv-rot) 0 5px, transparent 5.5px);
}

.kv-page .wc-block-components-checkbox__input:focus-visible,
.kv-page .wc-block-components-radio-control__input:focus-visible {
	outline: 2px solid var(--kv-ink);
	outline-offset: 2px;
}

/* --- Die Zeichen der Zahlungsarten brauchen Luft ---------------------

   Sie klebten am Wort („Bezahle mit Klarna[Klarna]"). Nur ein Abstand am
   BILD, nichts am Kasten: ein `display: flex` an der Beschriftung hat
   die Zeile zerlegt — das Feld stand plötzlich über dem Wort, weil die
   Beschriftung damit die ganze Breite nahm und umbrach. Die Zeile
   gehört WooCommerce, der Abstand uns.
   --------------------------------------------------------------------- */
.kv-page .wc-block-components-payment-method-label img,
.kv-page .wc-block-components-radio-control__label img {
	margin-left: 10px;
	vertical-align: middle;
}

/* --- Feld links, Beschriftung daneben --------------------------------

   WooCommerce legt das Feld `absolute` in eine Zeile, die es selbst
   ausmisst (`top` aus der Zeilenhöhe, `left` aus einem Polster am
   Kasten). Beides trägt hier nicht: unser Reset nimmt dem Kasten das
   Polster, und damit stand der Punkt 36 px über seiner Beschriftung und
   16 px in sie hinein — der Kunde: „Wenn du die Radios jetzt noch links
   daneben hinbekommst, sieht es gut aus."

   Statt an ihrer Rechnung zu drehen, nehmen wir die Zeile: eine
   Flexzeile mit 12 px Abstand, das Feld wieder IM FLUSS. Das ist die
   Anordnung, die auch das Beitrittsformular und die Fußzeile benutzen.
   --------------------------------------------------------------------- */
.kv-page .wc-block-components-radio-control__option,
.kv-page label.wc-block-components-checkbox {
	display: flex;
	align-items: flex-start;
	gap: 12px;
}

/* WooCommerce reserviert links 48 px — Platz für ein Feld, das bei ihnen
   absolut dort liegt. Im Fluss ist der Platz doppelt: das Feld stand
   48 px von der Kante, dahinter noch der Abstand zur Beschriftung
   („Ist zu viel Abstand"). 16 px, wie oben und unten. */
.kv-page .wc-block-components-radio-control__option {
	padding-left: 16px;
}

.kv-page .wc-block-components-radio-control__input,
.kv-page .wc-block-components-checkbox__input {
	position: static !important;
	top: auto !important;
	left: auto !important;
	right: auto !important;
	bottom: auto !important;
	transform: none !important;
	margin: 2px 0 0 !important;
}

.kv-page .wc-block-components-radio-control__label,
.kv-page .wc-block-components-checkbox__label {
	flex: 1 1 auto;
	min-width: 0;
}

/* --- Der schwarze Punkt in der Beschriftung --------------------------

   WooCommerce zeichnet den gewählten Punkt als `input::before` und
   positioniert ihn ABSOLUT — gerechnet auf ein Feld, das bei ihnen
   selbst absolut liegt. Seit das Feld bei uns im Fluss steht, bezieht
   sich sein Pseudoelement auf die Zeile und landet mitten im Wort:
   „Bezahle mit Kl●rna". Ermittelt mit `elementFromPoint` an der Stelle
   des Punktes — im DOM war dort nichts.

   Unsere frühere Regel dagegen verlor an Spezifität (2 Klassen gegen
   ihre 3 plus `:checked`). Deshalb hier mit Klasse mehr und
   `!important`; dasselbe für das Häkchen, dessen Hintergrund von
   `.wc-block-components-checkbox .…__input[type=checkbox]:checked
   { background: #fff }` überschrieben wurde — Attributwähler zählt mit.
   --------------------------------------------------------------------- */
.kv-page .wc-block-components-radio-control .wc-block-components-radio-control__input::before,
.kv-page .wc-block-components-radio-control .wc-block-components-radio-control__input::after,
.kv-page .wc-block-components-checkbox .wc-block-components-checkbox__input::before,
.kv-page .wc-block-components-checkbox .wc-block-components-checkbox__input::after {
	display: none !important;
	content: none !important;
}

.kv-page .wc-block-components-checkbox .wc-block-components-checkbox__input[type="checkbox"]:checked {
	background-color: var(--kv-rot) !important;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M1.8 6.4l2.9 2.9 5.5-6' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") !important;
	background-size: 12px 12px !important;
	background-position: center !important;
	background-repeat: no-repeat !important;
}

.kv-page .wc-block-components-radio-control .wc-block-components-radio-control__input[type="radio"]:checked {
	background-image: radial-gradient(circle at center, var(--kv-rot) 0 5px, transparent 5.5px) !important;
}

/* --- Der Beschreibungstext klappt mobil auf -------------------------

   Wunsch des Kunden (07.09.2026): „Wenn der ganze Beschreibungstext (nur
   nicht der eingekreiste Excerpt) in einem aufklappbaren Akkordeon ist,
   so dass man schneller zu den Tickets kommt."

   Sichtbar bleibt der Anriss — Überschrift und erster Absatz —, der Rest
   steht in einem `<details>`. Zugeklappt wird von `kv.js` unter 700 px;
   das `open` im Markup ist der Ausfallzustand ohne Skript. Auf dem
   Desktop ist der Umschalter ausgeblendet und der Text steht
   vollständig da, wie im Entwurf.
   --------------------------------------------------------------------- */
.kv-page .kv-edetail__mehr-auf {
	display: none;
}

.kv-page .kv-edetail__mehr-auf::-webkit-details-marker { display: none; }
.kv-page .kv-edetail__mehr-auf::marker { content: ''; }

@media (max-width: 700px) {
	.kv-page .kv-edetail__mehr-auf {
		display: inline-flex;
		align-items: center;
		gap: 8px;
		margin-top: 4px;
		cursor: pointer;
		list-style: none;
		font-family: var(--kv-text);
		font-size: 16px;
		line-height: 24px;
		font-weight: 400;
		color: var(--kv-ink);
		/* Trefferfläche: der Text allein ist 24 px hoch. */
		padding-block: 10px;
	}

	.kv-page .kv-edetail__mehr-auf::after {
		content: '';
		flex: 0 0 auto;
		width: 12px;
		height: 12px;
		background: currentColor;
		mask: url('../img/icon-chevron-right.svg') center / contain no-repeat;
		-webkit-mask: url('../img/icon-chevron-right.svg') center / contain no-repeat;
		transform: rotate(90deg);
		transition: transform 200ms cubic-bezier(0.2, 0.7, 0.2, 1);
	}

	.kv-page .kv-edetail__mehr[open] .kv-edetail__mehr-auf::after {
		transform: rotate(-90deg);
	}

	@media (hover: hover) {
		.kv-page .kv-edetail__mehr-auf:hover { color: var(--kv-rot); }
	}

	.kv-page .kv-edetail__mehr-auf:active { color: var(--kv-rot); }

	/* Aufgeklappt braucht der Text Abstand zum Umschalter. */
	.kv-page .kv-edetail__mehr[open] .kv-edetail__mehr-text {
		padding-top: 8px;
	}

	/* ZUGEKLAPPT AUSDRÜCKLICH AUSBLENDEN.
	 *
	 * Ein geschlossenes `<details>` versteckt seinen Inhalt selbst — aber
	 * Safari behält für `::details-content` eine Ersatzgröße
	 * (`contain-intrinsic-size`) in Höhe des letzten Standes. Gemessen:
	 * der Kasten war 48 px hoch, die Fließspalte trotzdem 902 — 730 px
	 * leere Fläche unter dem Umschalter, genau die Höhe des versteckten
	 * Textes. Mit `display: none` ist er aus dem Fluss. */
	.kv-page .kv-edetail__mehr:not([open]) .kv-edetail__mehr-text {
		display: none;
	}
}

/* =========================================================================
   45. Bildergalerie an der Veranstaltung (Kunde, 08.09.2026)

   „Anstatt dem Video (oder zusätzlich) auch noch die Möglichkeit, eine
   Bildergalerie zu hinterlegen." Sie steht unter der Beschreibung, im
   selben Rhythmus wie der Videoblock: Rubrik, dann die Fläche.

   Die Bilder sind quadratisch beschnitten (`3 / 2` wäre bei gemischten
   Hoch- und Querformaten unruhig, `1 / 1` gibt eine ruhige Reihe) und
   tragen den mittleren Radius der Slider-Bilder — sie sind Motive in
   einer Reihe, keine Karten.
   ========================================================================= */

.kv-page .kv-egalerie {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.kv-page .kv-egalerie__raster {
	display: grid;
	grid-template-columns: repeat(var(--kv-egalerie-spalten, 3), minmax(0, 1fr));
	gap: 16px;
}

.kv-page .kv-egalerie--s2 { --kv-egalerie-spalten: 2; }
.kv-page .kv-egalerie--s3 { --kv-egalerie-spalten: 3; }
.kv-page .kv-egalerie--s4 { --kv-egalerie-spalten: 4; }

.kv-page .kv-egalerie__glied {
	display: block;
	overflow: hidden;
	border-radius: var(--kv-r-mittel);
	background: var(--kv-soft);
	/* Eine feine Kante — und die ist hier kein Zierrat.
	   -------------------------------------------------------------------
	   Der Kunde meldete „Blitzer" an den Bildrändern. Nachgemessen ist es
	   NICHT das Layout: alle neun Kästen 272 × 272, `object-fit: cover`,
	   Spalt zum Bild 0,00 px, kein heller Saum bei 1440, 1920 und 2000 px.
	   Es sind die MOTIVE: mehrere Fotos haben am Rand eine helle Wand, und
	   die verschmilzt mit dem hellen Abschnitt — die Kachel verliert ihre
	   Kante und sieht aus wie ein Fehler.

	   Gegen Motive kann man nichts rechnen, gegen die fehlende Kante
	   schon. `outline` mit negativem Offset, nicht `border`: das Maß der
	   Kachel bleibt unverändert, und die Linie liegt ÜBER dem Bild (ein
	   `box-shadow: inset` am `<img>` läge darunter und wäre unsichtbar). */
}

.kv-page .kv-egalerie__bild {
	display: block;
	width: 100%;
	height: 100%;
	aspect-ratio: 1 / 1;
	object-fit: cover;
	/* Der Ruhezustand ist leicht vergrößert — und das ist der eigentliche
	   Fund hinter den „Blitzern".
	   -------------------------------------------------------------------
	   Mehrere Fotos haben am Rand eine helle Fläche (ein Fenster, eine
	   Wand). Gemessen bei DPR 2 an neun Kacheln: zwei zeigen rechts
	   7 CSS px Weiß (Helligkeit 240 und 247). Beim Überfahren waren sie
	   weg — der Hinweis des Kunden, und der Schlüssel: der Hover-Zoom
	   schneidet je Seite rund 1,5 % ab, und genau so breit war der
	   Streifen.

	   Ein größerer Ruhe-Zuschnitt (1.04) war der erste Versuch und ist
	   ZURÜCKGENOMMEN: nachgemessen blieben die hellen Flächen an drei
	   Kacheln stehen, weil sie keine 7 px schmalen Ränder sind, sondern
	   die STUDIOWAND im Foto — bei Slash und Dr. Dre reicht das Weiß tief
	   ins Bild. Wer da weiter zoomt, schneidet Köpfe ab.

	   Die Antwort steht deshalb am Glied: eine leichte Vignette dunkelt
	   die Kanten, ohne einen Millimeter Motiv zu kosten. */
	transition: transform var(--kv-t-bild), box-shadow var(--kv-t-flaeche);
}

/* Nur wo ein Zeigegerät ist — auf dem Telefon bliebe der Zustand nach dem
   Antippen stehen (siehe „:hover bleibt auf dem Telefon stehen"). */
@media (hover: hover) {
	.kv-page a.kv-egalerie__glied:hover .kv-egalerie__bild {
		transform: scale(1.04);
	}
}

/* Die Vignette: sie liegt ÜBER dem Bild und nimmt hellen Motivkanten
   die Härte — ein weißer Studiohintergrund verschmilzt sonst mit dem
   hellen Abschnitt, und die Kachel sieht aus, als fehlte ihr ein Stück
   (vom Kunden dreimal als „Blitzer" gemeldet).

   Als Pseudoelement, nicht als `box-shadow: inset` am Bild: bei einem
   `<img>` läge der Schatten unter dem Bildinhalt. `pointer-events: none`,
   damit der Klick weiter beim Verweis landet. */
.kv-page .kv-egalerie__glied {
	position: relative;
}

.kv-page .kv-egalerie__glied::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 1;
	border-radius: inherit;
	box-shadow: inset 0 0 0 1px var(--kv-ink-24),
	            inset 0 0 20px 6px rgba(35, 31, 35, 0.16);
	pointer-events: none;
}

/* Der Fokusring gehört an das Glied, nicht an das Bild: das Bild sitzt in
   einem Kasten mit `overflow: hidden`, ein Ring am Bild wäre abgeschnitten. */
.kv-page a.kv-egalerie__glied:focus-visible {
	outline: 2px solid var(--kv-ink);
	outline-offset: 3px;
}

/* Unter 700 px zwei Spalten, egal was im Panel steht: vier Motive
   nebeneinander sind auf 390 px je 84 px breit — das ist kein Bild mehr,
   sondern eine Briefmarke. */
@media (max-width: 700px) {
	.kv-page .kv-egalerie__raster {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 12px;
	}
}

/* =========================================================================
   46. Lichtkasten (Kunde, 08.09.2026)

   „Unbedingt eine Lightbox mit Klick-Funktion zum nächsten Bild."

   Vorher öffnete der Klick das Bild in einem neuen Tab — mit weißem
   Aufblitzen und einer Zoomstufe, die der Browser wählt. Der Kasten legt
   das Bild stattdessen VOLLSTÄNDIG (`contain`) auf einen dunklen Grund:
   die Ausgangsposition ist damit immer dieselbe.

   Ohne JavaScript bleibt der Verweis auf die Bilddatei — der
   Ausfallzustand ist der bisherige.
   ========================================================================= */

.kv-page .kv-lb,
.kv-lb {
	position: fixed;
	inset: 0;
	/* Über allem, auch über dem Vollbildmenü (z-index 30). */
	z-index: 40;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 12px;
	padding: 24px;
	background: rgba(35, 31, 35, 0.94);
	opacity: 1;
	transition: opacity 200ms ease;
}

.kv-lb[hidden] {
	display: none;
}

/* Während der Kasten verschwindet, fängt er keine Klicks mehr ab. */
.kv-lb--geht {
	opacity: 0;
	pointer-events: none;
}

.kv-lb__buehne {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 12px;
	margin: 0;
	max-width: 100%;
	max-height: 100%;
}

.kv-lb__bild {
	display: block;
	max-width: min(1400px, 100%);
	/* 100% der Bühne minus Zähler und Abstand — sonst schiebt ein hohes
	   Motiv den Zähler aus dem Fenster. */
	max-height: calc(100vh - 48px - 40px);
	width: auto;
	height: auto;
	object-fit: contain;
	border-radius: var(--kv-r-mittel);
	background: rgba(247, 246, 245, 0.06);
	cursor: pointer;
}

.kv-lb__zaehler {
	color: rgba(247, 246, 245, 0.72);
	font-size: 12px;
	line-height: 16px;
	letter-spacing: 1px;
}

/* Bedienelemente: 44 px, Symbole als reine Form (kein Zeichensatz —
   ein „×" als Textzeichen sitzt in jeder Schrift anders). */
.kv-lb__zu,
.kv-lb__pfeil {
	position: relative;
	flex: 0 0 auto;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	border-radius: var(--kv-r-mini);
	background: rgba(247, 246, 245, 0.1);
	cursor: pointer;
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
	transition: background var(--kv-t-schnell);
}

.kv-lb__zu {
	position: absolute;
	top: 24px;
	right: 24px;
}

.kv-lb__zu::before,
.kv-lb__zu::after {
	content: '';
	position: absolute;
	left: 13px;
	top: 21px;
	width: 18px;
	height: 2px;
	background: var(--kv-soft);
}

.kv-lb__zu::before { transform: rotate(45deg); }
.kv-lb__zu::after  { transform: rotate(-45deg); }

/* Der Pfeil ist ein gedrehtes Winkel-Paar, wie das Chevron der Seite. */
.kv-lb__pfeil::before {
	content: '';
	position: absolute;
	top: 15px;
	left: 16px;
	width: 12px;
	height: 12px;
	border-right: 2px solid var(--kv-soft);
	border-top: 2px solid var(--kv-soft);
}

.kv-lb__pfeil--weiter::before { transform: rotate(45deg); }
.kv-lb__pfeil--zurueck::before { transform: rotate(-135deg); left: 18px; }

@media (hover: hover) {
	.kv-lb__zu:hover,
	.kv-lb__pfeil:hover {
		background: rgba(247, 246, 245, 0.2);
	}
}

.kv-lb__zu:focus-visible,
.kv-lb__pfeil:focus-visible {
	outline: 2px solid var(--kv-soft);
	outline-offset: 2px;
}

/* Auf dem Telefon stehen die Pfeile unter dem Bild: seitlich nehmen sie
   dem Motiv je 56 px Breite, und gewischt wird dort ohnehin. */
@media (max-width: 700px) {
	.kv-page .kv-lb,
	.kv-lb {
		flex-direction: column;
		justify-content: center;
		padding: 16px;
	}

	.kv-lb__zu {
		top: 16px;
		right: 16px;
	}

	.kv-lb__buehne {
		order: -1;
	}

	.kv-lb__bild {
		max-height: calc(100vh - 32px - 40px - 56px);
	}
}

@media (prefers-reduced-motion: reduce) {
	.kv-page .kv-lb,
	.kv-lb {
		transition: none;
	}
}

/* Der Zeitraum unter dem Datumsblock: „bis 29. September". Mono und
   leise wie die übrigen Angaben der Karte — der Beginn bleibt die
   Hauptsache, das Ende ist die Ergänzung (Kunde, 08.09.2026). */
.kv-page .kv-infokarte__bis {
	display: block;
	margin-top: 4px;
	color: var(--kv-ink-64);
	font-size: 12px;
	line-height: 16px;
	letter-spacing: 1px;
}
