/* ==========================================================================
   PVBB - Bausteine

   Jeder Abschnitt hier entspricht einem Baustein, der in WordPress spaeter
   als eigenes Muster oder als Block vorliegt und damit einzeln ein- und
   ausgeblendet, verschoben und mehrfach eingesetzt werden kann.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Kopfzeile und Navigation (NAVO)
   -------------------------------------------------------------------------- */

.kopfzeile {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgb(255 255 255 / 0.92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--linie);
}

.kopfzeile__innen {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--raum-5);
  min-height: 4.5rem;
}

.kopfzeile__logo {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  padding-block: var(--raum-3);
}

.kopfzeile__logo img {
  display: block;
  width: clamp(9rem, 16vw, 12.5rem);
}

/* Hauptmenue */
.menue {
  display: none;
}

.menue__liste {
  display: flex;
  align-items: center;
  gap: var(--raum-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.menue__liste > li {
  position: relative;
  margin: 0;
}

.menue__punkt {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  padding: var(--raum-2) var(--raum-3);
  border-radius: var(--rund-m);
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-menue);
  font-weight: 600;
  color: var(--blau-800);
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--uebergang), color var(--uebergang);
}

.menue__punkt:hover,
.menue__punkt:focus-visible {
  background: var(--blau-50);
  color: var(--blau-700);
}

.menue__punkt[aria-current="page"] {
  color: var(--blau-700);
}

.menue__punkt[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: var(--raum-3);
  right: var(--raum-3);
  bottom: -0.1rem;
  height: 3px;
  background: var(--akzent);
  border-radius: var(--rund-voll);
}

.menue__pfeil {
  width: 0.7em;
  height: 0.7em;
  fill: currentColor;
  opacity: 0.55;
  transition: transform var(--uebergang);
}

.menue__liste > li:hover .menue__pfeil,
.menue__liste > li:focus-within .menue__pfeil {
  transform: rotate(180deg);
}

/* Untermenue */
.menue__unter {
  position: absolute;
  top: calc(100% + 0.35rem);
  left: 0;
  min-width: 15rem;
  margin: 0;
  padding: var(--raum-2);
  list-style: none;
  background: var(--weiss);
  border: 1px solid var(--linie);
  border-radius: var(--rund-l);
  box-shadow: var(--schatten-l);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-0.35rem);
  transition: opacity var(--uebergang), transform var(--uebergang),
    visibility var(--uebergang);
}

.menue__liste > li:hover > .menue__unter,
.menue__liste > li:focus-within > .menue__unter {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.menue__unter li {
  margin: 0;
}

.menue__unter a {
  display: block;
  padding: var(--raum-2) var(--raum-3);
  border-radius: var(--rund-m);
  font-size: var(--gr-s);
  color: var(--text);
  text-decoration: none;
  transition: background var(--uebergang), color var(--uebergang);
}

.menue__unter a:hover,
.menue__unter a:focus-visible {
  background: var(--blau-50);
  color: var(--blau-700);
}

/* Schalter fuer schmale Geraete */
.menue-schalter {
  display: inline-flex;
  align-items: center;
  gap: var(--raum-2);
  padding: var(--raum-2) var(--raum-3);
  background: none;
  border: 1px solid var(--linie-kraeftig);
  border-radius: var(--rund-m);
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-s);
  font-weight: 600;
  color: var(--blau-800);
  cursor: pointer;
}

.menue-schalter svg {
  width: 1.15rem;
  height: 1.15rem;
  fill: currentColor;
}

.menue-schalter__auf {
  display: none;
}

.menue-schalter[aria-expanded="true"] .menue-schalter__zu {
  display: none;
}

.menue-schalter[aria-expanded="true"] .menue-schalter__auf {
  display: block;
}

@media (min-width: 64rem) {
  .menue {
    display: block;
  }

  .menue-schalter {
    display: none;
  }
}

/* Aufgeklapptes Menue auf schmalen Geraeten */
.menue-mobil {
  display: none;
  border-top: 1px solid var(--linie);
  background: var(--weiss);
  max-height: min(75vh, 40rem);
  overflow-y: auto;
}

.menue-mobil[data-offen] {
  display: block;
}

.menue-mobil ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.menue-mobil > ul {
  padding-block: var(--raum-3);
}

.menue-mobil a {
  display: block;
  padding: var(--raum-3) 0;
  font-family: var(--schrift-ueberschrift);
  font-weight: 600;
  color: var(--blau-800);
  text-decoration: none;
  border-bottom: 1px solid var(--linie);
}

.menue-mobil ul ul a {
  padding-left: var(--raum-4);
  font-family: var(--schrift-text);
  font-weight: 400;
  font-size: var(--gr-s);
  color: var(--text-leise);
}

@media (min-width: 64rem) {
  .menue-mobil {
    display: none !important;
  }
}

/* --------------------------------------------------------------------------
   Knoepfe
   -------------------------------------------------------------------------- */

.knopf {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--raum-2);
  padding: 0.8em 1.5em;
  border: 2px solid transparent;
  border-radius: var(--rund-m);
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-s);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--uebergang), border-color var(--uebergang),
    color var(--uebergang), transform var(--uebergang);
}

.knopf:hover {
  transform: translateY(-1px);
}

.knopf:active {
  transform: translateY(0);
}

.knopf svg {
  width: 1.1em;
  height: 1.1em;
  fill: currentColor;
  flex-shrink: 0;
}

.knopf--haupt {
  background: var(--blau-800);
  border-color: var(--blau-800);
  color: var(--text-invers);
}

.knopf--haupt:hover {
  background: var(--blau-700);
  border-color: var(--blau-700);
  color: var(--text-invers);
}

/* Akzentknopf: dunkler Text auf Gruen - auf Gruen ist Blau mit 8,71:1
   bestens lesbar, weisse Schrift waere es nicht. */
.knopf--akzent {
  background: var(--akzent);
  border-color: var(--akzent);
  color: var(--blau-900);
}

.knopf--akzent:hover {
  background: var(--akzent-hell);
  border-color: var(--akzent-hell);
  color: var(--blau-900);
}

.knopf--rand {
  background: transparent;
  border-color: var(--linie-kraeftig);
  color: var(--blau-800);
}

.knopf--rand:hover {
  border-color: var(--blau-800);
  background: var(--blau-50);
  color: var(--blau-800);
}

/* Auf blauem Grund - alle drei dunklen Umgebungen muessen hier stehen,
   sonst erbt der Knopf sein dunkles Blau und verschwindet im Hintergrund. */
.abschnitt--blau .knopf--rand,
.hero .knopf--rand,
.aufruf .knopf--rand,
.karte--blau .knopf--rand,
.spaltenblock--teaser .knopf--rand {
  border-color: rgb(255 255 255 / 0.45);
  color: var(--text-invers);
}

.abschnitt--blau .knopf--rand:hover,
.hero .knopf--rand:hover,
.aufruf .knopf--rand:hover,
.karte--blau .knopf--rand:hover,
.spaltenblock--teaser .knopf--rand:hover {
  background: rgb(255 255 255 / 0.1);
  border-color: var(--weiss);
  color: var(--text-invers);
}

.knopf--breit {
  width: 100%;
}

.knopf-reihe {
  display: flex;
  flex-wrap: wrap;
  gap: var(--raum-3);
}

/* Fuer einen einzelnen Querverweis-Knopf, der freistehend zentriert werden
   soll - Knopfpaare (z. B. auf der Startseite) bleiben ohne diese Klasse
   linksbuendig (zb/24, zb/25). */
.knopf-reihe--zentriert {
  justify-content: center;
}

/* zb/12: Huelle des Mehrzweckknopfs - regelt die Ausrichtung IM BLOCK
   SELBST, unabhaengig davon, wie die Redaktion ihn im Editor umgibt
   (dieselbe Lehre wie bei ".dateiliste" unten, Erkenntnis 25 in
   docs/VERFAHREN.md: der Block darf sich nicht auf seine Umgebung
   verlassen). "display:flex" + "justify-content" wirkt zuverlaessig, auch
   wenn der Knopf selbst (".knopf") nicht ueber die volle Breite geht - eine
   reine text-align-Loesung waere von der is-layout-*-Klasse des umgebenden
   WordPress-Blocks abhaengig, "justify-content" ist es nicht. */
.mehrzweckknopf {
  display: flex;
}

.mehrzweckknopf--links {
  justify-content: flex-start;
}

.mehrzweckknopf--mittig {
  justify-content: center;
}

.mehrzweckknopf--rechts {
  justify-content: flex-end;
}

/* Textlink mit Pfeil */
.weiterlink {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-s);
  font-weight: 600;
  color: var(--blau-700);
  text-decoration: none;
}

.weiterlink svg {
  width: 0.85em;
  height: 0.85em;
  fill: currentColor;
  transition: transform var(--uebergang);
}

.weiterlink:hover svg {
  transform: translateX(3px);
}

.abschnitt--blau .weiterlink,
.aufruf .weiterlink,
.karte--blau .weiterlink,
.hero .weiterlink {
  color: var(--akzent);
}

/* --------------------------------------------------------------------------
   Vereinsuebersicht: Rahmen um die Vereinsboxen (zb/24)
   -------------------------------------------------------------------------- */

/* Setzt die Vereinsboxen als eigenen, hell hinterlegten Bereich vom
   (seit zb/24 wieder weissen) Abschnitt drumherum ab - vorher trug der ganze
   Abschnitt "abschnitt--papier", jetzt nur noch dieser Rahmen. */
.vereinsrahmen {
  padding: var(--raum-6);
  background: var(--papier);
  border: 1px solid var(--linie);
  border-radius: var(--rund-l);
}

/* --------------------------------------------------------------------------
   Auszeichnungen
   -------------------------------------------------------------------------- */

.abzeichen {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.32em 0.8em;
  border-radius: var(--rund-voll);
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-xs);
  font-weight: 600;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

.abzeichen--mitglied {
  background: var(--blau-50);
  color: var(--blau-700);
}

/* Fuer gruene Auszeichnungen der dunkle Gruenton - auf Weiss waere das
   Verbandsgruen nicht lesbar. */
.abzeichen--anfaenger {
  background: #f2f4d4;
  color: var(--akzent-dunkel);
}

.abzeichen--neu {
  background: var(--akzent);
  color: var(--blau-900);
}

/* --------------------------------------------------------------------------
   Hero der Startseite
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  overflow: hidden;
  background: var(--blau-800);
  color: var(--text-invers);
  isolation: isolate;
}

/* Spielfeldgrafik als ruhiger Hintergrund */
.hero__grund {
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: url("../grafiken/hero-feld.svg");
  background-position: center right;
  background-repeat: no-repeat;
  background-size: cover;
  opacity: 0.9;
}

.hero__innen {
  display: grid;
  gap: var(--raum-8);
  align-items: center;
  padding-block: clamp(3rem, 1.5rem + 7vw, 6.5rem);
}

@media (min-width: 60rem) {
  .hero__innen {
    grid-template-columns: 1.05fr 0.95fr;
    gap: var(--raum-9);
  }
}

.hero h1 {
  margin-bottom: var(--raum-5);
  font-size: var(--gr-hero);
  font-weight: 700;
  color: var(--text-invers);
  letter-spacing: -0.025em;
}

.hero h1 em {
  font-style: normal;
  color: var(--akzent);
}

/* Zwei Schlaeger und ein Ball hinter der Doppelzeile (nu/49).

   WOZU: Am Telefon erscheint die Spielfeldgrafik nicht - .hero__bild steht
   unter 60 rem auf display:none. Damit fehlte dort jeder Hinweis auf den
   Sport.

   WARUM AM h1 UND NICHT AM <em>: `right: 0` ist dadurch der rechte Rand der
   TEXTSPALTE, nicht das Ende der Zeile. Am Rechner steht die Grafik damit
   rechts in der Spalte, am Telefon rechts neben den beiden Zeilen - und
   wenn das Fenster schmaler wird, behaelt sie ihre Lage, waehrend die
   Schrift sich von links darueberschiebt.

   WARUM EIN PSEUDOELEMENT: Es braucht keine Aenderung am Markup und nichts
   Redaktionelles. Ein eigenes Element muesste im Block-Editor gesetzt und
   bei jeder Textaenderung nachgefuehrt werden - und koennte den Umbruch der
   beiden Zeilen veraendern, was ausdruecklich nicht sein soll. Aus dem
   Textfluss heraus kann es das nicht.

   WARUM em UND NICHT px: Die Ueberschrift ist selbst fluessig. In em bleibt
   das Verhaeltnis zur Schrift in JEDER Aufloesung gleich - 2,50 em sind
   rund 109 Prozent der beiden Zeilen (2 x 1,15 em), so wie im Entwurf des
   Auftraggebers. Es braucht dafuer keine einzige Umbruchstelle. */
.hero h1 {
  position: relative;
}

.hero h1::after {
  content: "";
  position: absolute;
  z-index: -1;
  right: 0;
  bottom: -0.18em;
  height: 2.5em;
  width: 2.36em;
  background: url("../grafiken/schlaeger-hero.svg") no-repeat center / contain;
  pointer-events: none;
}

.hero__vorspann {
  max-width: 34rem;
  margin-bottom: var(--raum-7);
  font-size: var(--gr-l);
  line-height: var(--zeile-weit);
  color: var(--blau-100);
}

.hero__bild {
  display: none;
}

@media (min-width: 60rem) {
  .hero__bild {
    display: block;
  }
}

/* Kennzahlen unter dem Hero */
.kennzahlen {
  display: grid;
  gap: var(--raum-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
  padding-block: var(--raum-6);
  border-top: 1px solid rgb(255 255 255 / 0.15);
}

.kennzahl {
  text-align: center;
}

.kennzahl__wert {
  display: block;
  font-family: var(--schrift-ueberschrift);
  font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.4rem);
  font-weight: 700;
  line-height: 1.1;
  color: var(--akzent);
}

.kennzahl__text {
  display: block;
  margin-top: var(--raum-1);
  font-size: var(--gr-s);
  color: var(--blau-100);
}

/* --------------------------------------------------------------------------
   Karten
   -------------------------------------------------------------------------- */

.karte,
.is-style-pvbb-karte {
  display: flex;
  flex-direction: column;
  padding: var(--raum-6);
  background: var(--weiss);
  border: 1px solid var(--linie);
  border-radius: var(--rund-l);
  transition: border-color var(--uebergang), box-shadow var(--uebergang),
    transform var(--uebergang);
}

.karte:hover {
  border-color: var(--linie-kraeftig);
  box-shadow: var(--schatten-m);
  transform: translateY(-2px);
}

.karte h3 {
  margin-bottom: var(--raum-3);
  font-size: var(--gr-h4);
}

.karte p:last-child,
.karte ul:last-child {
  margin-bottom: 0;
}

/* Ein Abzeichen als unmittelbares Kind wuerde sich sonst ueber die ganze
   Kartenbreite dehnen - die Karte ist ein Flex-Behaelter. */
.karte > .abzeichen {
  align-self: flex-start;
  margin-bottom: var(--raum-4);
}

/* Haelt den Weiterlink am unteren Rand, damit er ueber alle Karten einer
   Reihe hinweg auf gleicher Hoehe steht - unabhaengig von der Textlaenge. */
.karte__fuss {
  margin-top: auto;
  padding-top: var(--raum-4);
  margin-bottom: 0;
}

.karte__symbol {
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  margin-bottom: var(--raum-5);
  background: var(--blau-50);
  border-radius: var(--rund-m);
  color: var(--blau-700);
}

.karte__symbol svg {
  width: 1.7rem;
  height: 1.7rem;
  fill: currentColor;
}

/* Hervorgehobene Karte mit Akzentkante */
.karte--akzent {
  border-top: 4px solid var(--akzent);
}

.karte--blau,
.is-style-pvbb-karte-blau {
  background: var(--blau-800);
  border-color: var(--blau-800);
  color: var(--blau-100);
}

.karte--blau h3,
.is-style-pvbb-karte-blau :where(h2, h3, h4) {
  color: var(--text-invers);
}

.karte--blau .karte__symbol {
  background: rgb(255 255 255 / 0.1);
  color: var(--akzent);
}

/* Aufzaehlung mit Haken */
.hakenliste,
.is-style-pvbb-hakenliste {
  margin: 0;
  padding: 0;
  list-style: none;
}

.hakenliste li,
.is-style-pvbb-hakenliste li {
  position: relative;
  padding-left: 1.75rem;
  margin-bottom: var(--raum-3);
}

/* Der Punkt sitzt auf der Mitte der ERSTEN Zeile, nicht auf einem festen
   Abstand von oben.

   Bis 1.5.46 stand hier `top: 0.55em` bei `height: 0.7rem` — eine Mischung aus
   mitwachsender und fester Einheit. Sie stimmte bei keiner Schriftgröße genau
   und lag umso schiefer, je kleiner die Schrift war: In den Spielortzeilen
   (12,9 px, Zeilenhöhe 1,4) saß der Punkt 3,65 px zu tief, der Text wirkte
   dadurch nach oben verschoben. Gemeldet vom Auftraggeber am 14.08.2026,
   danach gemessen.

   `0.5lh` ist die halbe Zeilenhöhe — damit stimmt es bei jeder Kombination aus
   Schriftgröße und Zeilenabstand, ohne dass eine Zahl gepflegt werden muss.
   Die Zeile darüber ist der Rückfall für Browser ohne `lh`; sie rechnet mit
   dem hier üblichen Zeilenabstand 1,65. */
.hakenliste li::before,
.is-style-pvbb-hakenliste li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.475em;
  top: calc(0.5lh - 0.35em);
  width: 0.7em;
  height: 0.7em;
  background: var(--akzent);
  border-radius: var(--rund-voll);
}

.karte--blau .hakenliste li::before {
  background: var(--akzent);
}

/* --------------------------------------------------------------------------
   Meldungen (Aktuelles)
   -------------------------------------------------------------------------- */

.meldung {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--weiss);
  border: 1px solid var(--linie);
  border-radius: var(--rund-l);
  transition: border-color var(--uebergang), box-shadow var(--uebergang),
    transform var(--uebergang);
}

.meldung:hover {
  border-color: var(--linie-kraeftig);
  box-shadow: var(--schatten-m);
  transform: translateY(-2px);
}

.meldung__bild {
  aspect-ratio: 16 / 9;
  background: var(--blau-50);
  object-fit: cover;
  width: 100%;
  /* db/04: Trennlinie zum Textbereich, fest am Bild-Element statt an einer
     eigenen Regel zwischen beiden Bereichen - pvbb_meldungsbild()
     (inc/render.php) liefert IMMER ein <img> zurueck, echtes Bild oder
     Ersatzgrafik, also erscheint die Linie automatisch nur dort, wo auch
     ein Bild steht. Ein einfacher unterer Rahmen genuegt: .meldung ist
     display:flex/column, .meldung__inhalt folgt unmittelbar als naechstes
     Flex-Geschwister ohne gap - der Rahmen sitzt deshalb exakt auf der
     Kante, nicht mit Abstand. Immer 1 px stark, unabhaengig von der
     Aufloesung des Bildes - anders als die vom Auftraggeber beschriebene
     Behelfslinie, die als Teil der Grafik mitskaliert waere. */
  border-bottom: 1px solid var(--linie);
}

.meldung__inhalt {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: var(--raum-5);
}

.meldung__datum {
  display: block;
  margin-bottom: var(--raum-2);
  font-size: var(--gr-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-leise);
}

.meldung__titel {
  margin-bottom: var(--raum-3);
  font-size: var(--gr-h4);
  line-height: var(--zeile-mittel);
}

.meldung__titel a {
  color: inherit;
  text-decoration: none;
}

.meldung__titel a:hover {
  color: var(--blau-600);
}

.meldung__text {
  flex: 1;
  margin-bottom: var(--raum-4);
  font-size: var(--gr-s);
  color: var(--text-leise);
}

/* --------------------------------------------------------------------------
   Seitenspalte (SB1 Mini-Teaser, SB2 Aktionsknoepfe, SB3 Meldungsspiegel)
   -------------------------------------------------------------------------- */

.spaltenblock {
  padding: var(--raum-5);
  background: var(--weiss);
  border: 1px solid var(--linie);
  border-radius: var(--rund-l);
}

.spaltenblock + .spaltenblock {
  margin-top: var(--raum-5);
}

.spaltenblock__titel {
  margin-bottom: var(--raum-4);
  padding-bottom: var(--raum-3);
  border-bottom: 1px solid var(--linie);
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-s);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--blau-700);
}

/* db/05: das Vereinslogo im Block "Der Verein". Nur eine Breitenbegrenzung,
   bewusst KEINE feste Hoehe und kein object-fit - Vereinslogos kommen in
   sehr unterschiedlichen Seitenverhaeltnissen, und ein zweites festes Mass
   wuerde manche verzerren oder beschneiden (Ticket-Vorgabe). height:auto
   haelt das Originalverhaeltnis, unabhaengig davon, ob das Logo hoch, breit
   oder quadratisch ist. display:block entfernt den kleinen Abstand unter
   dem Bild, den ein "inline" <img> sonst durch seine Grundlinie bekommt -
   sichtbar geworden waere das als ein paar Pixel Luft, die wie ein
   zusaetzlicher Aussenrand ausgesehen haetten (der Auftraggeber wollte
   ausdruecklich keinen). */
.spaltenblock__logo {
  display: block;
  max-width: 100%;
  height: auto;
}

/* SB1 - Mini-Teaser */
.spaltenblock--teaser {
  background: var(--blau-800);
  border-color: var(--blau-800);
  color: var(--blau-100);
}

.spaltenblock--teaser .spaltenblock__titel {
  border-color: rgb(255 255 255 / 0.18);
  color: var(--akzent);
}

.spaltenblock--teaser h3 {
  margin-bottom: var(--raum-2);
  font-size: var(--gr-h4);
  color: var(--text-invers);
}

.spaltenblock--teaser p {
  font-size: var(--gr-s);
}

/* Ohne diese Regel erbte der Link das dunkle Blau der Grundeinstellung und
   staende damit dunkelblau auf dunkelblau. */
.spaltenblock--teaser .weiterlink {
  color: var(--akzent);
}

/* SB2 - Aktionsknoepfe */
.aktionsknoepfe {
  display: grid;
  gap: var(--raum-3);
}

/* SB3 - Meldungsspiegel */
.spiegel {
  margin: 0;
  padding: 0;
  list-style: none;
}

.spiegel li {
  margin: 0;
  padding-block: var(--raum-3);
  border-bottom: 1px solid var(--linie);
}

.spiegel li:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

.spiegel__datum {
  display: block;
  margin-bottom: var(--raum-1);
  font-size: var(--gr-xs);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-leise);
}

.spiegel__titel {
  display: block;
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-s);
  font-weight: 600;
  line-height: var(--zeile-mittel);
  color: var(--blau-800);
  text-decoration: none;
}

/* Auch hier das Verbandsgrün (zb/26). Die Überschriften der Seitenspalte sind
   klein gesetzt, und es leuchtet nichts auf — der Farbwechsel ist also der
   einzige Hinweis und darf nicht der schwächste sein. Vom Auftraggeber am
   15.08.2026 ausdrücklich verlangt.

   Das ist kein Widerspruch zur Ausnahme für Überschriften: Die gilt den
   *großen*, die durch Größe und Gewicht ohnehin sprechen. Hier ist es ein
   `<a>` und keine Überschrift, die Regel greift also gar nicht — diese Zeile
   hier tat es. */
.spiegel__titel:hover,
.spiegel__titel:focus-visible {
  color: var(--verweis-hover);
}

.spiegel__anriss {
  margin: var(--raum-1) 0 0;
  font-size: var(--gr-s);
  line-height: var(--zeile-mittel);
  color: var(--text-leise);
}

/* --------------------------------------------------------------------------
   Termine
   -------------------------------------------------------------------------- */

.termin {
  display: flex;
  gap: var(--raum-4);
  padding-block: var(--raum-4);
  border-bottom: 1px solid var(--linie);
}

/* Die Linie unter dem letzten Eintrag entfaellt nur, wenn die Liste das Letzte
   in ihrem Kasten ist. Folgt darunter noch "Alle Termine", bleibt sie stehen
   (zb/04, Punkte 3 und 4).

   Im Entwurf ist das kein Sonderfall, sondern ergibt sich von selbst: Dort
   stehen die Termine unmittelbar im Spaltenblock, und :last-child trifft wegen
   des folgenden Absatzes ohnehin nicht zu. Erst die Huelle .terminliste, die
   nur die WordPress-Ausgabe hat, machte daraus einen Unterschied - dort war
   der letzte Termin sehr wohl das letzte Kind, und die Linie verschwand.
   Am 12.08.2026 vom Auftraggeber gemeldet und an der Vorschau nachgemessen. */
.terminliste:last-child > .termin:last-child,
.spaltenblock > .termin:last-child {
  border-bottom: 0;
}

.termin__tag {
  display: grid;
  place-content: center;
  flex-shrink: 0;
  width: 3.75rem;
  height: 3.75rem;
  background: var(--blau-50);
  border-radius: var(--rund-m);
  text-align: center;
  line-height: 1.1;
}

.termin__tag b {
  display: block;
  font-family: var(--schrift-ueberschrift);
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--blau-800);
}

.termin__tag span {
  display: block;
  font-size: var(--gr-xs);
  font-weight: 600;
  text-transform: uppercase;
  /* War 0.06em - mit Jahreszahl ("Sep 26" statt "Sep") reicht die schmalere
     Sperrung, um den Kasten bei 60x60 px zu halten (zb/05, gemessen). */
  letter-spacing: 0.02em;
  color: var(--text-leise);
}

.termin__titel {
  margin: 0 0 var(--raum-1);
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-m);
  font-weight: 600;
  color: var(--blau-800);
}

.termin__ort {
  margin: 0;
  font-size: var(--gr-s);
  color: var(--text-leise);
}

/* Mehrtages-Marke am Datumsquadrat (zb/05). Die Anhebung sitzt bewusst am
   Modifikator und NICHT an .termin__tag: Der erste Entwurf hob jedes
   Quadrat um 10px an, auch die eintaegigen ohne Marke - die Mehrheit haette
   ihr Datum unzentriert getragen, damit die Minderheit Platz fuer die Marke
   hat. Siehe Ticket, Abschnitt "Der Fund des Auftraggebers". */
.termin__tag--mehrtaegig {
  position: relative;
  padding-block-end: 10px;
}

.termin__dauer {
  position: absolute;
  left: var(--raum-2); /* Versatz nach rechts, 8 px */
  right: -5px; /* ueberlappt den rechten Rand */
  bottom: -5px; /* ueberlappt den unteren Rand */
  padding-block: 1px;
  border-radius: var(--rund-s);
  background: var(--akzent-hell);
  color: var(--blau-800);
  font-style: normal;
  font-weight: 600;
  font-size: var(--gr-xxs);
  line-height: 1.3;
  letter-spacing: 0.01em;
  text-align: center;
  white-space: nowrap;
}

/* Vergangene Termine, ausklappbar unter den kommenden (zb/07). Natives
   <details>/<summary> statt einer eigenen JS-Loesung: Tastatur und
   Vorleseprogramme bekommen den Ausklapp-Zustand vom Browser selbst
   angesagt, und ohne JavaScript bleibt der Inhalt trotzdem erreichbar - er
   steht im Markup, nur eingeklappt. */
.terminliste--mit-vergangenen > .termin:last-child {
  /* Sonst stuende die Linie des letzten kommenden Termins unmittelbar ueber
     der Trennlinie des Ausklapp-Bereichs - zwei Linien mit wenig Abstand
     dazwischen statt einer (siehe die Trennlinien-Regel bei .terminliste
     weiter oben, die hier wegen des nachfolgenden <details> nicht mehr
     greift). */
  border-bottom: 0;
}

.vergangene-termine {
  margin-top: var(--raum-5);
  padding-top: var(--raum-4);
  border-top: 1px solid var(--linie);
}

.vergangene-termine summary {
  cursor: pointer;
  padding-block: var(--raum-2);
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-m);
  font-weight: 600;
  color: var(--blau-800);
}

/* Gedaempfte Darstellung (Abnahmekriterium "als solche erkennbar"):
   dieselben Bausteine wie beim kommenden Termin, nur mit den
   zurueckhaltenden Toenen, die im Projekt bereits fuer Nebensaechliches
   stehen - kein neuer Farbton. --text-leise auf --linie ist neu und steht
   deshalb in kontraste_pruefen.py. */
.termin--vergangen .termin__tag {
  background: var(--linie);
}

.termin--vergangen .termin__tag b,
.termin--vergangen .termin__titel {
  color: var(--text-leise);
}

/* Auch die Mehrtages-Marke wird gedaempft (zb/07, Nachbesserung bei der
   Gegenpruefung). Ohne diese Regel bleibt sie in --akzent-hell stehen und
   ist die einzige leuchtende Stelle in einem bewusst zurueckgenommenen
   Bereich - aufgefallen am Bild, nicht an der Regel (Erkenntnis 11).
   --text-leise auf --papier steht bereits in kontraste_pruefen.py. */
.termin--vergangen .termin__dauer {
  background: var(--papier);
  color: var(--text-leise);
}

/* "Wann"/"Wo"/"Ausrichter" auf der Veranstaltungsseite (zb/09) - vorher ganz
   ohne eigene Regel, damit lief <dl>/<dt>/<dd> auf der reinen Browservorgabe
   (u. a. ein 40px-Einzug an <dd>), und der Auftraggeber nannte die Seite
   "etwas sehr schmucklos". Jetzt: Bezeichnung fett, die eigentlichen Angaben
   als lesbare Paare mit Abstand dazwischen. */
.termindaten {
  margin: 0 0 var(--raum-5);
}

.termindaten dt {
  font-weight: 700;
}

.termindaten dd {
  margin: 0 0 var(--raum-3);
}

.termindaten dd:last-of-type {
  margin-bottom: 0;
}

/* Der Anmelde-Knopf: mehr Luft davor und danach, dazu ein Einzug statt bündig
   am linken Rand (zb/09, Punkte 2 und 3) - derselbe Einzug wie die zweite
   Ebene des mobilen Menüs (.menue-mobil ul ul a oben). Eine eigene Klasse
   statt eines Nachbarschafts-Selektors auf ".termindaten" - siehe render.php,
   pvbb_render_termindaten(). */
.termindaten__anmeldung {
  margin: var(--raum-5) 0 var(--raum-5) var(--raum-4);
}

/* --------------------------------------------------------------------------
   Hinweiskasten und Herunterladbares
   -------------------------------------------------------------------------- */

.hinweis,
.is-style-pvbb-hinweis {
  padding: var(--raum-5);
  border-left: 4px solid var(--akzent);
  border-radius: 0 var(--rund-m) var(--rund-m) 0;
  background: var(--hinweis-grund);
}

.hinweis :last-child {
  margin-bottom: 0;
}

/* nu/26: ".datei" ist seither der AEUSSERE Behaelter - er traegt weiterhin
   GENAU DIESELBE Klasse wie vorher (dateikarteprobe.py misst sie, die
   Breitenregeln aus nu/18 haengen daran: ".dateiliste > .datei" weiter
   unten und die Sonde in dateikarteprobe.py selbst), nur ist er jetzt ein
   "<div>" statt der "<a>" - der Verweis liegt darin als ".datei__verweis".
   Padding/Rahmen/Hintergrund bleiben deshalb HIER (nicht am Verweis): Genau
   dadurch teilt sich die Erlaeuterung weiter unten denselben linken/rechten
   Innenabstand wie der Verweis, ohne ihn eigens nachzubilden - exakt die
   Vorgabe des Auftraggebers ("volle Breite der Karte, exklusive der
   vorhandenen inneren Seitenabstaende"). "gap" ist deshalb ebenfalls
   gewandert: Es soll nur noch Symbol und Text INNERHALB des Verweises
   auseinanderhalten, nicht den Verweis von der Erlaeuterung (die hat ihre
   eigene Trennlinie samt Abstand, siehe ".datei__erlaeuterung"). */
.datei {
  display: flex;
  flex-direction: column;
  padding: var(--raum-4) var(--raum-5);
  background: var(--weiss);
  border: 1px solid var(--linie);
  border-radius: var(--rund-m);
  transition: border-color var(--uebergang), background var(--uebergang);
}

/* Die Karte als Ganzes hebt sich weiter beim Hover hervor - GENAU wie vor
   nu/26 -, jetzt aber ausgeloest vom Hover des INNEREN Verweises, nicht
   mehr vom eigenen Hover (".datei" selbst ist kein Verweis mehr, die
   Erlaeuterung darunter ist nicht klickbar). ":has()" ist in diesem Projekt
   bereits ein etabliertes Muster (siehe die Sperrhuelle der Startseite,
   AGENTS.md/ub/02). */
.datei:has(.datei__verweis:hover) {
  border-color: var(--blau-400);
  background: var(--blau-50);
}

.datei__verweis {
  display: flex;
  align-items: center;
  gap: var(--raum-4);
  text-decoration: none;
  color: inherit;
}

.datei__symbol {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 2.75rem;
  height: 2.75rem;
  background: var(--blau-50);
  border-radius: var(--rund-m);
  color: var(--blau-700);
  /* nu/53: das Vorschaubild einer Foto-Datei soll die abgerundete Ecke der
     Flaeche nicht ueberragen - vorher ohne Wirkung, weil das SVG-Symbol
     ohnehin kleiner als die Flaeche blieb. */
  overflow: hidden;
}

.datei:has(.datei__verweis:hover) .datei__symbol {
  background: var(--weiss);
}

.datei__symbol svg {
  width: 1.4rem;
  height: 1.4rem;
  fill: currentColor;
}

/* nu/57, 19.09.2026: NUR ein Vorschaubild waechst - 10px nach jeder Seite
   ueber seinen Platz hinaus, statt den Platz zu vergroessern. Piktogramm,
   Textanfang und Kartenhoehe bleiben dadurch unveraendert; der weisse
   Rand schrumpft auf 14px links und 6px oben, unten und zum Text hin.
   So vom Auftraggeber am Entwurf gewaehlt (dateisymbolentwurf.py). Die
   erste Umsetzung vergroesserte die ganze Flaeche samt Piktogramm und
   schob den Text nach rechts - Erkenntnis 37. */
.datei__symbol:has(img) {
  width: 4rem;
  height: 4rem;
  margin: -10px;
}

/* nu/53: das Vorschaubild einer Foto-Datei fuellt die ganze Flaeche statt
   klein in ihrer Mitte zu stehen wie das Symbol - genau die Groesse setzt
   dieses CSS (Ticket, Festlegung 1: "Die sichtbare Groesse setzt das CSS"),
   nicht die Pixelmasse des erzeugten Vorschaubilds selbst
   (PVBB_VORSCHAUBILD_KANTE, inc/vorschaubilder.php). */
.datei__symbol img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.datei__name {
  display: block;
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-s);
  font-weight: 600;
  color: var(--blau-800);
}

/* nu/23, Punkt 3: das Schloss hinter dem Namen einer geschuetzten Karte -
   "fill: currentColor" erbt darum automatisch ".datei__name"s Blauton, ohne
   eigene Farbregel. Baseline-Ausrichtung statt der SVG-Grundlinie: Ohne sie
   sitzt das Symbol - wie jedes SVG per Vorgabe - an der TEXT-Grundlinie und
   haengt sichtbar unter die Zeile. */
.datei__schloss {
  width: 0.85em;
  height: 0.85em;
  margin-left: 0.3em;
  vertical-align: -0.05em;
  fill: currentColor;
}

.datei__zusatz {
  display: block;
  margin-top: 0.1rem;
  font-size: var(--gr-xs);
  color: var(--text-leise);
}

/* nu/26: die "Erlaeuterung" - ein optionales zweites Textfeld UNTER dem
   Verweis, durch eine Trennlinie abgesetzt, ueber die volle Breite der Karte
   (== dieselben linken/rechten Abstaende wie ".datei" oben, siehe dortiger
   Kommentar). Erscheint NUR, wenn render.php sie ausgibt - ist das Feld
   leer, fehlt dieses Element vollstaendig (kein leerer Rahmen, keine
   leere Linie). Farbe/Groesse wie normaler Fliesstext (--text auf --weiss:
   15,6:1, kontraste_pruefen.py, Zeile "Fliesstext auf Weiss") - bewusst
   NICHT --text-leise wie ".datei__zusatz": Das ist hier keine beilaeufige
   Zusatzangabe mehr, sondern der eigentliche Erklaertext, den der
   Auftraggeber lesbar haben wollte. */
.datei__erlaeuterung {
  margin-top: var(--raum-4);
  padding-top: var(--raum-4);
  border-top: 1px solid var(--linie);
  font-size: var(--gr-s);
  color: var(--text);
}

/* Absaetze ohne Browser-Standardabstand - der kaeme zusaetzlich zum
   "padding-top" der Trennlinie oben und saehe wie ein doppelter Abstand
   aus. Zwischen mehreren Absaetzen genuegt ein kleiner eigener Abstand. */
.datei__erlaeuterung p {
  margin: 0;
}

.datei__erlaeuterung p + p {
  margin-top: var(--raum-2);
}

/* nu/18: eigener, in sich abgeschlossener Behaelter fuer die Dateikarten des
   Blocks "Dateikarten-Liste" (pvbb/dateikartenliste, inc/bloecke.php) -
   ersetzt die frueheren zwei Anlaeufe, ".raster" selbst per :has()-Selektor
   fuer diesen Fall umzubiegen (siehe die Geschichte im Ticket). Der Block
   liefert IMMER sein eigenes, vollstaendiges Markup - keine InnerBlocks,
   keine vom Editor einfuegbare Verschachtelung dazwischen (siehe
   pvbb_render_dateikartenliste(), render.php) -, deshalb kann keine
   Gruppierung im Editor das Ergebnis mehr veraendern (Erkenntnis 25,
   docs/VERFAHREN.md: die Menge der moeglichen Editor-Gruppierungen ist nicht
   abgeschlossen, eine Regel, die eine bestimmte Verschachtelung voraussetzt,
   trifft immer nur einen Teil der Faelle).

   ZWEI FAELLE, servereitig unterschieden (die eine Weiche, die CSS allein
   nicht treffen kann - siehe render.php), weil sie GEGENSAETZLICHE
   Breitenregeln brauchen:

   ALLE KARTEN SIND GLEICH BREIT - auch eine allein stehende. Sie belegt
   genau EINE Spur des Rasters, nicht mehr und nicht weniger.

   DIE BREITE IST NICHT GESETZT, SONDERN ABGELEITET, und das ist der Kern der
   zweiten Runde (01.09.2026). Vorher stand hier eine feste Zahl - 282px, aus
   dem Ticket uebernommen. Sie war falsch: Sie stammte aus dem 17rem-Minimum
   der alten ".raster"-Regel, nicht aus dem gerenderten Ergebnis. GEMESSEN in
   der freigegebenen Vorschau (vorschau/verband.html, "Unterlagen"):

       Fenster 1280px -> Spalte 793,5px -> 2 Spuren zu 388,7px
       Fenster 1440px -> Spalte 808,0px -> 2 Spuren zu 396,0px
       Fenster 1920px -> Spalte 808,0px -> 2 Spuren zu 396,0px

   Die Vorschau hat also gar keine feste Pixelbreite: Eine Karte ist die
   HAELFTE DER INHALTSSPALTE, abzueglich der Luecke. Deshalb steht hier
   "minmax(24rem, 1fr)" und keine Zahl - 24rem (384px) ist die Untergrenze,
   die Spurbreite ergibt sich aus der verfuegbaren Breite. In der
   Zweispalter-Ansicht kommen damit exakt die gemessenen Werte der Vorschau
   heraus; das ist nachgerechnet und mit dateikarteprobe.py belegt.

   "auto-fill" (bewusst NICHT "auto-fit"): auto-fill BEHAELT eine leere Spur.
   Genau daran haengt, dass eine einzelne Karte so breit ist wie eine von
   zweien - "auto-fit" liesse die leere Spur kollabieren und die Karte die
   ganze Zeile fuellen. Das war in beiden gescheiterten CSS-Anlaeufen die
   eigentliche Fehlerursache (siehe die Geschichte im Ticket und den
   Kommentar bei ".raster" oben).

   DIE SPALTENZAHL braucht keine Deckelung mehr, sie folgt aus der Breite:
   Zwei Spuren brauchen 2*384+16 = 784px, drei 3*384+32 = 1184px, vier
   4*384+48 = 1584px. In der Zweispalter-Ansicht (max. 808px) passen also
   zwei, auf einer vollen Seite (bis 75rem/1200px, design-system.css
   "--breite-inhalt") drei, vier nie. Die frueheren Vorgaben "hoechstens zwei
   mit Seitenspalte, drei ohne" sind damit keine eigene Regel mehr, sondern
   eine Folge der Breite - so, wie der Auftraggeber es am 30.08.2026 verlangt
   hat: "Die vorgegebene Normalbreite ... Daran soll sich auch ausrichten,
   wie viele nebeneinander passen."

   WARUM ES ".dateiliste--einzeln" NICHT MEHR GIBT: Die Klasse liess eine
   einzelne Karte mit ihrem Inhalt wachsen. Am eingespielten Ergebnis hat der
   Auftraggeber am 01.09.2026 gesehen, was das bedeutet - zwei untereinander
   stehende Einzelkarten waren VERSCHIEDEN breit, je nach Laenge ihres
   Dateinamens, und er hat das als Mangel gemeldet. Die Vorgabe "waechst nach
   rechts" vom 31.08.2026 entstand, als die Standardbreite noch fuer 282px
   gehalten wurde und ein langer Name die Karte gesprengt haette; bei 396px
   ist der Anlass entfallen. Und die Vorschau selbst kennt kein Wachsen. */
.dateiliste {
  /* Die Standardbreite einer Karte, gemessen an der freigegebenen Vorschau
     (vorschau/verband.html, "Unterlagen"): dort ist die Inhaltsspalte 808px
     breit und traegt zwei Spuren zu 396px. 24,75rem sind genau diese 396px.
     Sie steht als eigener Wert da, weil zwei Regeln sie brauchen - die
     Spurbreite und die Deckelung darunter. */
  --dateikarte-breite: 24.75rem;

  display: grid;
  gap: var(--raum-4);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 22.5rem), 1fr));
  /* Schuetzt gegen ein Zusammenstauchen, sollte der Block einmal in einem
     vom Editor eingefuegten Flex-Wrapper landen (derselbe Wrapper-Typ, der
     in nu/18 den urspruenglichen CSS-Weg unterlaufen hat). */
  flex-shrink: 0;
}

/* DIE DECKELUNG SITZT AN DER KARTE, NICHT AN DER LISTE - dritter und letzter
   Anlauf, 01.09.2026. Die drei Fassungen der Reihe nach:

     1. "1fr" ohne Deckelung: Auf einer Seite ohne Seitenspalte (1120px)
        wurden die Karten 552px breit - 40 Prozent ueber der Vorschaubreite.
     2. Deckelung an der LISTE (zwei Standardbreiten = 808px): Das behob die
        Ueberbreite, hatte aber zwei Nebenwirkungen. Drei Spalten konnte es
        nie mehr geben, weil die Liste vorher endet. Und unterhalb von rund
        1280px Fensterbreite bleibt nur eine Spur - die dann so breit wurde
        wie die ganze Liste. Genau das hat der Auftraggeber gemeldet:
        "unter ca. 1280 Pixel ... gehen ueber die volle Breite".
     3. Deckelung an der KARTE: Sie ist nie breiter als die Standardbreite,
        gleichgueltig wie breit ihre Spur ist. Damit ist beides erledigt.

   WARUM DAS NICHT SCHON IN FASSUNG 2 SO WAR: Eine Obergrenze an der SPUR
   ("minmax(360px, 396px)") ginge nicht - CSS-Grid rechnet bei "auto-fill"
   mit der Obergrenze, sobald sie definit ist, und bei 793,5px Spaltenbreite
   bliebe nur eine Spur uebrig. Die Karte ist aber kein Grid-Track, sondern
   ein Grid-Element: Ihre max-width beeinflusst die Spurenzahl nicht.

   DIE SPUR-MINDESTBREITE IST DAFUER AUF 22,5rem (360px) GESUNKEN. Damit
   passen auf einer Seite ohne Seitenspalte drei Spuren (3 x 360 + 2 x 16 =
   1112px in 1120px), und die Karten sind dort 362,7px breit statt 396px.
   Vom Auftraggeber am 01.09.2026 ausdruecklich gebilligt: "Beim Wechsel auf
   drei Spalten (wenn die Seitenspalte wegfaellt) waere die etwas schmalere
   Breite in Ordnung."

   Auf Seiten MIT Seitenspalte aendert das nichts: 3 x 360 + 32 = 1112px
   passen nicht in 808px, es bleiben zwei Spuren zu 396px - die gemessene
   Vorschaubreite. */
.dateiliste > .datei {
  max-width: var(--dateikarte-breite);
}

/* --------------------------------------------------------------------------
   Zeitstrahl (Chronik des Verbands)
   -------------------------------------------------------------------------- */

.zeitstrahl {
  position: relative;
  margin: 0;
  padding: 0 0 0 var(--raum-6);
  list-style: none;
  border-left: 2px solid var(--linie);
}

.zeitstrahl li {
  position: relative;
  margin-bottom: var(--raum-6);
}

.zeitstrahl li:last-child {
  margin-bottom: 0;
}

.zeitstrahl li::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--raum-6) - 7px);
  top: 0.45em;
  width: 12px;
  height: 12px;
  background: var(--weiss);
  border: 3px solid var(--akzent);
  border-radius: var(--rund-voll);
}

/* Ueber ".zeitstrahl .zeitstrahl__datum" statt bloss ".zeitstrahl__datum"
   verscopt (va/13): In der Vorschau steht das Datum als <span>, im
   WordPress-Muster als <p class="zeitstrahl__datum"> (bearbeitbarer
   Absatzblock) - und trifft dort zugleich die Regel ".zeitstrahl p" weiter
   unten. Gleiche Klassen-Spezifitaet (0,1,0), aber ".zeitstrahl p" hat durch
   den zusaetzlichen Tag-Selektor (0,1,1) mehr Gewicht und gewinnt: Datum und
   Stationsueberschrift erschienen dadurch beide grau in derselben Groesse
   statt in ihren eigenen Farben. Gemessen an einer lokalen Kopie der
   laufenden Website (werkzeuge/live/verband-va13-lokal.html, siehe va/13) -
   vorher color=rgb(90,102,117) [--text-leise] statt var(--blau-600) bzw.
   var(--blau-800) an beiden Elementen. Die zusaetzliche Verschachtelung
   ".zeitstrahl ..." hebt die Spezifitaet auf (0,2,0) und gewinnt in beiden
   Einsatzorten unabhaengig vom Element-Tag. */
.zeitstrahl .zeitstrahl__datum {
  display: block;
  margin-bottom: var(--raum-1);
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-xs);
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--blau-600);
}

.zeitstrahl .zeitstrahl__titel {
  margin: 0 0 var(--raum-2);
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-m);
  font-weight: 600;
  color: var(--blau-800);
}

.zeitstrahl p {
  margin: 0;
  font-size: var(--gr-s);
  color: var(--text-leise);
}

/* --------------------------------------------------------------------------
   Fusszeile (NAVU)
   -------------------------------------------------------------------------- */

.fusszeile {
  padding-block: var(--raum-9) var(--raum-6);
  background: var(--blau-900);
  color: var(--blau-300);
  font-size: var(--gr-s);
}

.fusszeile__oben {
  display: grid;
  gap: var(--raum-7);
  padding-bottom: var(--raum-7);
  border-bottom: 1px solid rgb(255 255 255 / 0.1);
}

@media (min-width: 48rem) {
  .fusszeile__oben {
    grid-template-columns: 1.4fr repeat(3, 1fr);
    gap: var(--raum-6);
  }
}

/* Die Absätze der oberen Fußzeile stehen enger als der Fließtext der Website.

   Es sind genau drei: die zwei links („Dachverband der …", „Eingetragen im
   Vereinsregister …") und der Anschriftenblock rechts. Alle drei sind kurze,
   fest umbrochene Angaben — bei `--zeile-weit` (1,65) fallen ihre Zeilen
   auseinander, und der Anschriftenblock liest sich nicht mehr als Block.
   Gemeldet vom Auftraggeber am 14.08.2026: dort solle „ein normaler
   einzeiliger Satz" gelten.

   Zuerst stand hier `--zeile-eng` (1,15), seiner Formulierung „normaler
   einzeiliger Satz" folgend. Am eingespielten Ergebnis hat er auf **1,4**
   korrigiert: 1,15 setzte die Absätze zu stark gegen die Menüpunkte daneben
   ab, die weiterhin locker stehen. Der neue Unterschied im selben Bereich
   wirkte drastischer als der zum Fließtext, den die Änderung beheben sollte.

   Ein eigenes Absatzformat für den Editor braucht es dafür nicht: Die Fußzeile
   ist ein Template-Teil, den die Redaktion nicht bearbeitet. Ein Blockstil auf
   Vorrat wäre eine Wahlmöglichkeit, die niemand nutzt — und im Editor eine
   Wahl mehr, die erklärt werden muss. */
.fusszeile__oben p {
  line-height: var(--zeile-mittel);
}

.fusszeile__logo {
  width: 11rem;
  margin-bottom: var(--raum-4);
}

.fusszeile h4 {
  margin-bottom: var(--raum-4);
  font-size: var(--gr-s);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--weiss);
}

.fusszeile ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.fusszeile li {
  margin-bottom: var(--raum-2);
}

.fusszeile a {
  color: var(--blau-300);
  text-decoration: none;
}

.fusszeile a:hover {
  color: var(--akzent);
  text-decoration: underline;
}

.fusszeile__unten {
  display: flex;
  flex-wrap: wrap;
  gap: var(--raum-2) var(--raum-5);
  align-items: center;
  justify-content: space-between;
  padding-top: var(--raum-5);
  font-size: var(--gr-xs);
}

.fusszeile__rechtslinks {
  display: flex;
  flex-wrap: wrap;
  gap: var(--raum-2) var(--raum-5);
}

/* --------------------------------------------------------------------------
   Aufruf-Band
   -------------------------------------------------------------------------- */

.aufruf,
.is-style-pvbb-aufruf {
  position: relative;
  overflow: hidden;
  padding: clamp(2.5rem, 1.5rem + 4vw, 4.5rem);
  background: var(--blau-800);
  border-radius: var(--rund-xl);
  color: var(--text-invers);
  text-align: center;
}

.aufruf h2 {
  max-width: 28ch;
  margin-inline: auto;
  color: var(--text-invers);
}

.aufruf p {
  max-width: 52ch;
  margin-inline: auto;
  margin-bottom: var(--raum-6);
  color: var(--blau-100);
}

.aufruf .knopf-reihe {
  justify-content: center;
}

.aufruf__muster {
  position: absolute;
  right: -4rem;
  bottom: -6rem;
  width: 22rem;
  opacity: 0.09;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   Vereinskarte

   Selbst gehostetes SVG - es wird nichts von fremden Servern nachgeladen.
   Die Liste unter der Karte enthaelt dieselben Angaben und ist gleichwertig
   bedienbar; die Karte ist eine zusaetzliche Sicht, kein alleiniger Zugang.
   -------------------------------------------------------------------------- */

.kartenfeld {
  display: grid;
  gap: var(--raum-6);
  align-items: start;
}

@media (min-width: 60rem) {
  .kartenfeld {
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    gap: var(--raum-7);
  }
}

.kartenbuehne {
  position: relative;
  padding: var(--raum-4);
  background: var(--papier);
  border: 1px solid var(--linie);
  border-radius: var(--rund-l);
}

#pvbb-karte {
  display: block;
  width: 100%;
  height: auto;
  max-height: 34rem;
  transition: none;
}

.flaeche {
  transition: fill var(--uebergang);
}

.flaeche--land {
  fill: #dfe5ee;
  stroke: var(--weiss);
  stroke-width: 1.6;
}

.flaeche--bezirk {
  fill: var(--blau-400);
  stroke: var(--weiss);
  stroke-width: 1.1;
}

.karte--nah .flaeche--bezirk {
  fill: var(--blau-300);
  stroke-width: 2.5;
}

/* nu/44: Im Bezirksausschnitt wird die Linie NICHT mehr mitvergroessert.

   Die Staerke steht in Karteneinheiten, nicht in Bildschirmpunkten - sie
   waechst also mit dem Zoom. Als Anteil der Kartenbreite gemessen: 0,11 % in
   der Gesamtansicht, 1,2 % im Berlin-Ausschnitt, 2,9 % im Pankow-Ausschnitt.
   Der Auftraggeber hat am 09.09.2026 gemeldet, dass Spielorte nahe einer
   Grenze dadurch in einer weissen Zone zu liegen scheinen und nicht mehr
   zuzuordnen sind.

   Ein fester Wert je Ausschnitt traegt nicht: Die Bezirke sind zu
   verschieden gross (Friedrichshain-Kreuzberg rund halb so breit wie
   Pankow, die Uckermark rund fuenfmal so breit). "non-scaling-stroke"
   nimmt die Linie von der Zoom-Skalierung aus - sie behaelt ihre
   Bildschirmbreite, in jedem Bezirk gleich.

   3 px am Bild entschieden (werkzeuge/grenzlinienentwurf.py, Bild
   werkzeuge/live/nu44-grenzlinien.png): Bei 6 px bleibt die Suedspitze
   Pankows ein Band, bei 1,5 px verlieren die blassen Nachbarbezirke ihre
   Trennung.

   NUR "karte--bezirk", nicht "karte--nah": Berlin und Umland behalten ihre
   heutige Linienstaerke - dort ist sie unveraendert richtig. */
.karte--bezirk .flaeche--bezirk,
.karte--bezirk .flaeche--land {
  vector-effect: non-scaling-stroke;
  stroke-width: 3px;
}

/* Der ueber den Filter gewaehlte Bezirk wird auf der Karte hervorgehoben,
   damit Filter und Karte sichtbar zusammengehoeren. */
.flaeche--hervor {
  fill: var(--blau-700);
}

.karte--nah .flaeche--hervor {
  fill: var(--blau-700);
}

/* Marken */
.marke {
  cursor: pointer;
}

.marke__hof {
  fill: var(--akzent);
  fill-opacity: 0.25;
  transition: fill-opacity var(--uebergang), r var(--uebergang);
}

.marke__punkt {
  fill: var(--akzent);
  stroke: var(--blau-900);
  stroke-width: 2.5;
  transition: r var(--uebergang);
}

.marke:hover .marke__hof,
.marke:focus-visible .marke__hof {
  fill-opacity: 0.5;
}

.marke--gewaehlt .marke__hof {
  fill-opacity: 0.65;
}

/* Zurueck auf Weiss (zb/18, Teil 1): Seit zb/16 Punkt 3 leuchtet der Bezirk
   des gewaehlten Punktes selbst auf (--blau-700) - Weiss setzt sich davon
   deutlich besser ab als vom vorherigen hellen Bezirk. Gemessen gegen den
   4px-Rand (--blau-900), die tatsaechliche Grenze nach WCAG 2.2 AA SC 1.4.11:
   Weiss auf dem jetzt aufleuchtenden Bezirk 10,76:1, gegen den eigenen Rand
   17,09:1. Zum Vergleich waere Dunkelblau auf dem aufleuchtenden Bezirk nur
   1,59:1 - Punkt und Flaeche verschmelzen dort fast. Rand, Randstaerke und
   Hof bleiben unveraendert - sie tragen die Unterscheidung mit (WCAG 1.4.1),
   nicht allein die Fuellfarbe. */
.marke--gewaehlt .marke__punkt {
  fill: var(--weiss);
  stroke: var(--blau-900);
  stroke-width: 4;
}

/* nu/43, Teil B: inaktive Marken bleiben klickbar. pointer-events:none ist
   ersatzlos weg - zeichnen() gibt ihnen weiterhin tabindex="0", die
   Klick-/Tastaturhoerer haengen ohnehin schon unbedingt an jeder Marke
   (karte.js). Die Deckkraft steht seit 0,18 bei 0,32 - am Bild entschieden
   (werkzeuge/markenentwurf.py, Bild werkzeuge/live/nu43-graue-punkte.png):
   bei 0,18 verschwinden dicht beieinanderliegende Punkte fast im
   Untergrund, bei 0,32 liest man sie als eigene Punkte, ohne dass der
   aktive seine Sonderstellung verliert. */
.marke--aus {
  opacity: 0.32;
}

.marke:focus-visible {
  outline: 3px solid var(--blau-800);
  outline-offset: 3px;
}

/* Bedienleiste ueber der Karte */
.kartenleiste {
  display: flex;
  flex-wrap: wrap;
  gap: var(--raum-3);
  align-items: flex-end;
  margin-bottom: var(--raum-5);
}

.feld {
  display: flex;
  flex-direction: column;
  gap: var(--raum-1);
  min-width: 11rem;
  flex: 1 1 11rem;
}

.feld label {
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-xs);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-leise);
}

.feld select,
.feld input[type="text"],
.feld textarea {
  padding: 0.6em 0.75em;
  background: var(--weiss);
  border: 1px solid var(--linie-kraeftig);
  border-radius: var(--rund-m);
  font-family: inherit;
  font-size: var(--gr-s);
  color: var(--text);
}

.feld--haken {
  flex-direction: row;
  align-items: center;
  gap: var(--raum-2);
  flex: 0 0 auto;
  padding-bottom: 0.55rem;
}

.feld--haken label {
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--gr-s);
  color: var(--text);
}

.feld--haken input {
  width: 1.1rem;
  height: 1.1rem;
  accent-color: var(--blau-700);
}

.schalter {
  display: inline-flex;
  align-items: center;
  gap: var(--raum-2);
  padding: 0.6em 1em;
  background: var(--weiss);
  border: 1px solid var(--linie-kraeftig);
  border-radius: var(--rund-m);
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-s);
  font-weight: 600;
  color: var(--blau-800);
  cursor: pointer;
}

.schalter svg {
  width: 1em;
  height: 1em;
  fill: currentColor;
}

.schalter:hover {
  border-color: var(--blau-400);
  background: var(--blau-50);
}

.schalter[aria-pressed="true"] {
  background: var(--blau-800);
  border-color: var(--blau-800);
  color: var(--text-invers);
}

/* nu/43, Teil A: der Knopf "Bezirk / Kreis" ist inaktiv, solange nichts
   hervorgehoben ist. disabled allein wuerde nur den Zeiger und die
   Bedienbarkeit aendern - eine sichtbar gedaempfte Darstellung, die sich
   vom blossen "nicht gedrueckt" der uebrigen Knoepfe unterscheidet, gehoert
   ausdruecklich dazu (Ticket, "Entschieden: der Knopf ist inaktiv..."). Der
   :hover-Zustand wird eigens zurueckgenommen, weil er sonst auch bei einem
   disabled-Element optisch ausloest (Chrome tut das). */
.schalter:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.schalter:disabled:hover {
  background: var(--weiss);
  border-color: var(--linie-kraeftig);
}

.kartenzaehler {
  margin: 0 0 var(--raum-4);
  font-size: var(--gr-s);
  color: var(--text-leise);
}

/* Infofeld neben der Karte */
.karte-info {
  padding: var(--raum-5);
  background: var(--blau-800);
  border-radius: var(--rund-l);
  color: var(--blau-100);
}

.karte-info h3 {
  margin: 0 0 var(--raum-2);
  font-size: var(--gr-h4);
  color: var(--text-invers);
}

.karte-info__verein {
  margin: 0 0 var(--raum-1);
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-xs);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--akzent);
}

/* Der Vereinsname fuehrt auf die Vereinsseite (zb/23). Er behaelt dabei
   Akzentfarbe und Schriftschnitt - auf dem Verbandsblau kommt er auf 8,70:1
   und ist damit die kraeftigste Kombination, die das Entwurfssystem hat.
   Deshalb NICHT die uebliche Linkfarbe, die hier kaum zu erkennen waere.

   Unterstrichen wird erst beim Ueberfahren: In Grossbuchstaben mit 0,07 em
   Sperrung wirkt eine dauerhafte Linie unruhig, und dass die Zeile anklickbar
   ist, verrät schon der Zeiger. */
.karte-info__verein a {
  color: inherit;
  text-decoration: none;
}

.karte-info__verein a:hover,
.karte-info__verein a:focus-visible {
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

/* Der Bezirk als grobe Ortsangabe direkt unter dem Namen (zb/16, Punkt 2):
   groesser als die Anschriftzeilen darunter, aber kleiner als die
   Hallen-Ueberschrift - und mit eigenem Abstand nach unten, der wie eine
   Leerzeile vor der Anschrift wirkt. Fehlt der Bezirk, erzeugt karte.js
   dieses Element gar nicht erst - dann bleibt auch kein Abstand uebrig. */
.karte-info__bezirk {
  margin: 0 0 var(--raum-4);
  font-size: var(--gr-m);
}

.karte-info__zeile {
  margin: 0 0 var(--raum-1);
  font-size: var(--gr-s);
}

.karte-info__zeiten {
  margin: var(--raum-3) 0 var(--raum-3);
  padding-top: var(--raum-3);
  border-top: 1px solid rgb(255 255 255 / 0.15);
  font-size: var(--gr-s);
  color: var(--weiss);
}

.karte-info__leer {
  margin: 0;
  font-size: var(--gr-s);
}

.karte-info :last-child {
  margin-bottom: 0;
}

/* Ortsliste - die Klasse traegt zweierlei: den button in karte.php (Klick
   waehlt auf der Karte an, keine Navigation) und seit zb/23 zusaetzlich das
   <a> in der Seitenspalte der Vereinsseite (fuehrt auf die Seite Spielorte).
   Deshalb faerbt und unterstreicht sie sich nicht wie ein gewoehnlicher
   Verweis - die Kartenoptik gilt fuer beide gleich, das Hervorheben beim
   Ueberfahren/Fokussieren bleibt unveraendert die alleinige Kennzeichnung. */
.ortsliste {
  margin: var(--raum-5) 0 0;
  padding: 0;
  list-style: none;
}

.ortszeile {
  display: flex;
  gap: var(--raum-4);
  width: 100%;
  padding: var(--raum-4);
  margin-bottom: var(--raum-3);
  background: var(--weiss);
  border: 1px solid var(--linie);
  border-radius: var(--rund-m);
  text-align: left;
  font: inherit;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: border-color var(--uebergang), background var(--uebergang);
}

.ortszeile:hover {
  border-color: var(--blau-400);
  background: var(--blau-50);
}

.ortszeile--gewaehlt {
  border-color: var(--blau-700);
  background: var(--blau-50);
  box-shadow: inset 3px 0 0 var(--akzent);
}

.ortszeile__punkt {
  flex-shrink: 0;
  width: 0.85rem;
  height: 0.85rem;
  margin-top: 0.35rem;
  background: var(--akzent);
  border: 2px solid var(--blau-900);
  border-radius: var(--rund-voll);
}

.ortszeile__halle {
  display: block;
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-s);
  font-weight: 600;
  color: var(--blau-800);
}

.ortszeile__zusatz {
  display: block;
  margin-top: 0.15rem;
  font-size: var(--gr-xs);
  color: var(--text-leise);
}

/* nu/15: Ab mehr als sechs Eintraegen (PHP setzt die Klasse
   "ortsliste--viele", siehe karte.php, $viele) bekommt die Liste am Rechner
   einen eigenen Scrollbereich, damit die Karte daneben nicht aus dem Blick
   geraet, waehrend man durch die Liste blaettert - statt die ganze Seite
   wachsen zu lassen. Nur ab demselben Bruchpunkt wie .kartenfeld oben
   (60rem): darunter bleibt der Aufbau unveraendert, ausdrueckliche Vorgabe
   des Auftraggebers fuer Handy-Aufloesungen.

   34rem ist keine geschaetzte, sondern eine gemessene Groesse: die
   tatsaechliche Hoehe von genau sechs .ortsliste__eintrag (echten
   Theme-Stylesheets, realistischen Testdaten) betrug 544,97px = 34,06rem bei
   16px-Wurzelschriftgroesse. Absichtlich derselbe Wert wie "#pvbb-karte
   max-height" oben: beide Spalten bleiben dadurch etwa gleich hoch, ohne
   dass die Groesse hier von der Karte abgeleitet werden muesste. */
@media (min-width: 60rem) {
  .ortsliste--viele {
    display: flex;
    flex-direction: column;
    max-height: 34rem;
    overflow-x: hidden;
    overflow-y: auto;
    /* Platz fuer den Scrollbalken, damit er nicht ueber dem Text der
       Eintraege liegt. */
    padding-right: var(--raum-2);
    scrollbar-width: thin;
    scrollbar-color: var(--linie-kraeftig) transparent;
  }

  .ortsliste--viele::-webkit-scrollbar {
    width: 0.4rem;
  }

  .ortsliste--viele::-webkit-scrollbar-track {
    background: transparent;
  }

  .ortsliste--viele::-webkit-scrollbar-thumb {
    background: var(--linie-kraeftig);
    border-radius: var(--rund-voll);
  }

  /* NACHBESSERUNG nu/15 (30.08.2026): Hier stand eine Regel, die den
     gewaehlten Eintrag per order:-1 und position:sticky ueber den
     scrollenden Bereich zog. Sie beruhte auf einer falschen Vorgabe -
     gemeint war der dunkelblaue Detailkasten oben, nicht der Listeneintrag.
     Der gewaehlte Eintrag bleibt jetzt normaler Bestandteil der (seit nu/15
     alphabetischen) Liste, nur hervorgehoben ueber .ortszeile--gewaehlt
     weiter unten - wie vor nu/15, und wie es am Handy schon immer war. */
}

.kartenquelle {
  margin-top: var(--raum-4);
  font-size: var(--gr-xs);
  color: var(--text-leise);
}

/* --------------------------------------------------------------------------
   Vorstand

   Portraetfotos liegen noch nicht vor. Statt leerer Rahmen stehen hier
   Initialen in den Verbandsfarben - das wirkt gewollt und laesst sich
   spaeter Bild fuer Bild durch Fotos ersetzen, ohne das Layout zu aendern.
   -------------------------------------------------------------------------- */

.person {
  display: flex;
  gap: var(--raum-4);
  align-items: flex-start;
  padding: var(--raum-5);
  background: var(--weiss);
  border: 1px solid var(--linie);
  border-radius: var(--rund-l);
}

.person__bild {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 3.5rem;
  height: 3.5rem;
  background: var(--blau-800);
  border-radius: var(--rund-voll);
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-m);
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--akzent);
}

.person__name {
  margin: 0 0 0.1rem;
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-m);
  font-weight: 600;
  color: var(--blau-800);
}

.person__amt {
  margin: 0 0 var(--raum-2);
  font-size: var(--gr-xs);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-leise);
}

.person p:last-child {
  margin-bottom: 0;
  font-size: var(--gr-s);
  color: var(--text-leise);
}

/* Seitentitel ohne eigenen Hero */
.seitenkopf {
  padding-block: var(--raum-8) var(--raum-7);
  background: var(--papier);
  border-bottom: 1px solid var(--linie);
}

.brotkrumen {
  margin-bottom: var(--raum-4);
  font-size: var(--gr-xs);
  color: var(--text-leise);
}

.brotkrumen ol {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.brotkrumen li::after {
  content: "›";
  margin-left: 0.4rem;
  color: var(--linie-kraeftig);
}

.brotkrumen li:last-child::after {
  content: none;
}

.brotkrumen a {
  color: var(--text-leise);
}


/* --------------------------------------------------------------------------
   Abstaende im laufenden Text

   Ueberschriften bekommen ihren Abstand nach oben nur dort, wo Text
   tatsaechlich fliesst. Global gesetzt wuerde er in Karten, Seitenspalten
   und Abschnittskoepfen ueberall stoeren.
   -------------------------------------------------------------------------- */

.gespann__inhalt > h2,
.textfluss > h2 {
  margin-top: var(--raum-8);
}

.gespann__inhalt > h3,
.textfluss > h3 {
  margin-top: var(--raum-6);
}

.gespann__inhalt > :first-child,
.textfluss > :first-child {
  margin-top: 0;
}

/* Stufenwahl fuer den Kartenausschnitt */
.ausschnittwahl {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--raum-2);
  margin-bottom: var(--raum-4);
}

.ausschnittwahl__marke {
  display: inline-flex;
  align-items: center;
  gap: var(--raum-2);
  margin-right: var(--raum-2);
  font-family: var(--schrift-ueberschrift);
  font-size: var(--gr-xs);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-leise);
}

.ausschnittwahl__marke svg {
  width: 0.95rem;
  height: 0.95rem;
  fill: currentColor;
}

.schalter--stufe {
  padding: 0.45em 0.9em;
}
