/*
 * public/assets/css/ski-design.css
 *
 * Ski-Design (FORM-17): Dunkelblau/Gold, Bebas Neue (Headings) + DM Sans
 * (Fließtext), Berg-Silhouetten, Kachel-Pattern (.teilnahme-grid/.tn-btn).
 * Übernimmt die visuelle Basis der 07.06.2026-Legacy-Version (Karten-Layout
 * mit Schritt-Nummerierung), responsive für Desktop + Mobile.
 *
 * Kein Build-Prozess, kein CSS-Framework (Projekt-Constraint: Shared
 * Hosting ohne Composer/Bundler) — reines Vanilla-CSS.
 *
 * Font-Hinweis (DSGVO): Bebas Neue/DM Sans werden bewusst NICHT von einer
 * externen CDN (z.B. Google Fonts) nachgeladen, da dies die IP-Adresse
 * jedes Besuchers an einen Drittanbieter überträgt (Projekt-Kernwert:
 * "keine externen Cloud-Dienste", DSGVO-sauber auf dem eigenen Server).
 * Stattdessen @font-face mit local()-Fallback (nutzt die Schrift nur, wenn
 * sie bereits auf dem Gerät installiert ist) + eine optisch nahe
 * System-Font-Stack-Kaskade als Fallback. TODO (späterer Task/Phase, falls
 * Pixel-genaue Bebas-Neue-Optik gewünscht ist): echte .woff2-Dateien der
 * SIL-Open-Font-License-Schriften selbst hosten unter assets/fonts/ und
 * hier per @font-face src:url(...) einbinden.
 */

:root {
  /* Dunkelblau/Blau-Akzent (Rückbau von D-08-07/FORM-23 via Quick-Task
     260725-vc5) / two-blue palette (variable NAMES unchanged, ~30 call
     sites keep referencing these same names). --gold is for fills/
     backgrounds/borders; --gold-hell is the WCAG-safe darker value for
     anything rendered as TEXT or a thin outline (legends, focus rings,
     hover) — see the two-blue rule at each call site below. */
  --dunkelblau: #F8FAFC;
  --dunkelblau-hell: #DBEAFE;
  --dunkelblau-karte: #FFFFFF;
  --gold: #2577c8;
  --gold-hell: #1a4a7a;
  --text-hell: #111827;
  --text-dunkel: #111827;
  --fehler-rot: #DC2626;
  --fehler-bg: rgba(220, 38, 38, 0.08);
  --grau-vergangen: #6B7280;
  --rand: #DBEAFE;
  --schrift-headline: 'Bebas Neue', 'Oswald', 'Arial Narrow', sans-serif;
  --schrift-text: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

  /* Phase 15 (D-07/D-22/D-23, 15-RESEARCH.md Pitfall #4): drei neue,
     zweckgebundene Pillen-Farben. NICHT --gold/--gold-hell verwenden — die
     beiden Namen rendern seit dem 2026-Rebrand BLAU (#2577c8), eine Pille
     mit var(--gold) waere optisch nicht von der bestehenden Kachel-
     Auswahlfarbe zu unterscheiden. Werte 1:1 aus admin.css's bereits
     etabliertem --color-success/--color-accent-Paar sowie dem hier schon
     vorhandenen --grau-vergangen-Grau uebernommen, unter neuen,
     bedeutungsspezifischen Namen (ein spaeterer Leser soll nicht denken,
     das sei derselbe Token wie das blaue --gold). */
  --kurstag-gruen: #16A34A;
  --kurstag-gruen-tint: rgba(22, 163, 74, 0.12);
  /* Phase 16 (D-09, 16-UI-SPEC.md §Color): identischer Hex wie
     --kurstag-gruen (Projekt-Konvention: keine zweite Grün-Nuance
     erfinden), aber ein eigener Name — 15-UI-SPEC.md hat --kurstag-gruen
     ausdrücklich auf die eine Bedeutung "dieser Tag ist Teil eines
     Fix-Könnensstufen-Pakets" reserviert und vor jeder Zweitverwendung
     gewarnt. --kapazitaet-frei-gruen transportiert eine andere Bedeutung:
     "für diesen Termin ist im gewünschten Bus noch für die ganze Gruppe
     Platz". */
  --kapazitaet-frei-gruen: #16A34A;
  --kapazitaet-frei-gruen-tint: rgba(22, 163, 74, 0.12);
  --rabatt-gold: #D97706;
  --rabatt-gold-tint: rgba(217, 119, 6, 0.12);
  --warteliste-grau: #6B7280;
  --warteliste-grau-tint: rgba(107, 114, 128, 0.12);
  /* Plan 19-18 (E-1): echtes Gelb für die Mitfahren-Info-Box — der Verein hat
     bei der 19-12-Abnahme ausdrücklich "gelb" gewünscht, nicht die blaue
     --gold-Familie (informative Hinweise, .bus-hinweis/.warteliste-hinweis-
     banner) und NICHT --rabatt-gold (bereits für Rabatt-Pillen reserviert,
     siehe Kommentar oben). Eigener, neu benannter Token statt Wiederverwendung
     — Projekt-Konvention (siehe --kurstag-gruen-Warnung oben). */
  --info-gelb: #B45309;
  --info-gelb-tint: rgba(245, 158, 11, 0.16);
  --info-gelb-rand: #F59E0B;
}

@font-face {
  font-family: 'Bebas Neue';
  src: local('Bebas Neue'), local('BebasNeue-Regular'), local('BebasNeue');
  font-weight: 400;
  font-display: swap;
}

@font-face {
  font-family: 'DM Sans';
  src: local('DM Sans'), local('DMSans-Regular');
  font-weight: 400;
  font-display: swap;
}

* {
  box-sizing: border-box;
}

[hidden] {
  display: none !important;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: var(--schrift-text);
  /* Quick-Task 260726-0p8: durchgehender fixed Verlauf — ersetzt den
     bisherigen separaten .kopf-Header-Gradient, verankert am Viewport
     statt am Dokument. */
  background: linear-gradient(180deg, #0B2341 0%, #6BAADF 100%);
  background-attachment: fixed;
  background-repeat: no-repeat;
  color: var(--text-hell);
  line-height: 1.5;
}

h1, h2, h3, legend {
  font-family: var(--schrift-headline);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--gold-hell);
  margin: 0 0 0.5em;
}

/* ---------------------------------------------------------------------
   Kopfbereich mit Berg-Silhouetten (FORM-17)
   --------------------------------------------------------------------- */

.kopf {
  position: relative;
  overflow: hidden;
  padding: 2.5rem 1.25rem 2.75rem;
  text-align: center;
}

.kopf-inhalt {
  position: relative;
  z-index: 2;
}

.verein-name {
  margin: 0 0 0.25rem;
  color: #dbeafe;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 0.9rem;
}

.kopf h1 {
  font-size: clamp(1.8rem, 6vw, 3rem);
  margin: 0;
  color: #f4f7fb;
}

/* Quick-Task 260726-0p8: volldeckend, D5E8FD vorne / EEF5FD hinten */
.berge {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 140px;
  z-index: -1;
  opacity: 1;
  pointer-events: none;
  background-repeat: no-repeat;
  background-position: bottom center;
  background-size: cover;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 200' preserveAspectRatio='none'%3E%3Cpolygon points='0,200 150,40 300,140 450,20 600,120 750,60 900,160 1050,50 1200,130 1200,200' fill='%23EEF5FD'/%3E%3Cpolygon points='0,200 200,90 380,170 560,70 760,150 950,90 1200,170 1200,200' fill='%23D5E8FD'/%3E%3C/svg%3E");
}

/* ---------------------------------------------------------------------
   Formular-Layout & Karten-Schritte
   --------------------------------------------------------------------- */

main {
  max-width: 760px;
  margin: 0 auto;
  padding: 1.25rem 1rem 3rem;
}

#anmeldeformular {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.formular-schritt {
  background: var(--dunkelblau-karte);
  border: 1px solid var(--rand);
  border-radius: 10px;
  padding: 1.5rem 1.25rem;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.25);
}

.formular-schritt h2 {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 1.4rem;
}

.schritt-nummer {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background: var(--gold);
  color: #FFFFFF;
  font-family: var(--schrift-headline);
  font-size: 1.1rem;
}

label {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.9rem;
  color: var(--text-hell);
  margin-bottom: 0.9rem;
}

input[type="text"],
input[type="email"],
input[type="tel"],
input[type="date"],
input[type="number"],
textarea {
  font-family: var(--schrift-text);
  font-size: 1rem;
  padding: 0.55rem 0.7rem;
  border-radius: 6px;
  border: 1px solid var(--rand);
  background: var(--dunkelblau);
  color: var(--text-hell);
}

textarea {
  resize: vertical;
  min-height: 4.5rem;
}

input::placeholder,
textarea::placeholder {
  color: rgba(17, 24, 39, 0.5);
}

input:focus,
textarea:focus {
  outline: 2px solid var(--gold-hell);
  outline-offset: 1px;
}

fieldset {
  border: 1px solid var(--rand);
  border-radius: 8px;
  padding: 0.9rem;
  margin: 0 0 1rem;
}

legend {
  padding: 0 0.4rem;
  font-size: 1rem;
}

/* Schritt 1: Personenzahl */

.personenzahl-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.75rem;
  margin-bottom: 1rem;
}

/* D-08-09: Stepper — replaces native number-spinner arrows with explicit
   +/- buttons; the readonly <input type="number"> stays the real
   submitted field and doubles as the live count display (index.php/
   formular.js, 08-06). */
.stepper {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.stepper-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  border-radius: 8px;
  border: 1px solid transparent;
  background: var(--gold);
  color: #FFFFFF;
  font-family: var(--schrift-text);
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 1;
  padding: 0;
  cursor: pointer;
  transition: background 0.15s ease, transform 0.1s ease;
}

.stepper-btn:hover {
  background: var(--gold-hell);
}

/* D-19 (16-UI-SPEC.md Komponente 5): das Minus-Symbol bleibt bei 0
   sichtbar, statt wie bisher server-seitig hidden zu werden — hier nur
   der Dimming-Look; das hidden-Attribut entfernt Plan 16-05 (Markup).
   Die volle 44px-Fläche bleibt erhalten, kein Layout-Sprung. */
.stepper-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  background: var(--grau-vergangen);
}

.stepper-btn:disabled:hover {
  background: var(--grau-vergangen);
}

.stepper-btn:focus-visible {
  outline: 2px solid var(--gold-hell);
  outline-offset: 2px;
}

.stepper input[type="number"] {
  border: none;
  background: transparent;
  padding: 0;
  margin: 0;
  width: auto;
  min-width: 2ch;
  text-align: center;
  font-family: var(--schrift-headline);
  font-size: 20px;
  font-weight: 700;
  color: var(--text-hell);
  -moz-appearance: textfield;
}

.stepper input[type="number"]::-webkit-inner-spin-button,
.stepper input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.warnhinweis {
  border: 1px solid var(--fehler-rot);
  background: rgba(220, 38, 38, 0.12);
  border-radius: 8px;
  padding: 0.9rem 1rem;
  margin-bottom: 1rem;
}

.warnhinweis p {
  margin-top: 0;
  color: var(--fehler-rot);
}

/* K6/D-03/D-09 (Phase 11, 11-07): Mobile-Validierungskasten — reiner
   UX-Spiegel der bereits vorhandenen Weiter-/Absenden-Gates, siehe
   11-UI-SPEC.md §Component Pattern Nr. 5. Nutzt exakt dieselbe
   --fehler-rot-Rotfamilie wie .warnhinweis/.age-err-msg — keine neue Farbe,
   keine neue Custom Property. */
.weiter-fehlerliste {
  border: 1px solid var(--fehler-rot);
  background: rgba(220, 38, 38, 0.08);
  border-radius: 8px;
  padding: 16px;
  margin: 0 0 1rem;
}

.weiter-fehlerliste-titel {
  margin: 0 0 8px;
  font-weight: 700;
  font-size: 0.9rem;
  line-height: 1.4;
  color: var(--fehler-rot);
}

.weiter-fehlerliste-liste {
  margin: 0;
  padding-left: 16px;
  font-size: 0.9rem;
  font-weight: 400;
  line-height: 1.4;
  color: var(--fehler-rot);
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* Personendaten (Schritt 2) */

.feld-gruppe {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.75rem;
}

/* D-08-10: person-block card encapsulation — full border/radius/shadow
   instead of the old dashed top-border. #F1F5F9 (not pure white) so a
   person-block reads as its own card nested inside the white
   .formular-schritt surface rather than two stacked identical whites. */
.person-block {
  border: 1px solid var(--rand);
  border-radius: 8px;
  background: #F1F5F9;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
  padding: 16px;
  margin-top: 24px;
}

.person-block:first-child {
  margin-top: 0;
}

/* buildPersonBloecke() (formular.js) appends every .person-block into a
   single flat #personen-container in a fixed erwachsener -> jugendlicher
   -> kind order with no per-category wrapper element, so the "32px
   between category sections" gap (vs. 24px within a category) is
   expressed as a boundary-crossing sibling rule via each block's own
   data-erwartete-kategorie attribute (index.php renderPersonBlock()) —
   the 3rd selector covers the case where a category has 0 people and its
   neighbors become directly adjacent. */
.person-block[data-erwartete-kategorie="erwachsener"] + .person-block[data-erwartete-kategorie="jugendlicher"],
.person-block[data-erwartete-kategorie="jugendlicher"] + .person-block[data-erwartete-kategorie="kind"],
.person-block[data-erwartete-kategorie="erwachsener"] + .person-block[data-erwartete-kategorie="kind"] {
  margin-top: 32px;
}

/* Quick-Task 260725-qwe: farbiger Kategorie-Header ("Erwachsene" /
   "Jugendliche" / "Kinder") über der ersten Kachel jeder nicht-leeren
   Personen-Kategorie, genau einmal. buildPersonBloecke() (formular.js)
   klont Person-Blöcke flach und in fester erwachsener -> jugendlicher ->
   kind Reihenfolge in #personen-container (kein JS/Markup-Wrapper nötig).
   "Erster Block einer Kategorie" = entweder :first-child (Kategorie hat
   keinen Vorgänger überhaupt) ODER der direkte Vorgänger-Sibling gehört
   NICHT zur selben Kategorie (deckt auch den Fall ab, dass eine
   vorangehende Kategorie 0 Personen hat und die Blöcke direkt
   aneinandergrenzen — identisches Muster wie die 32px-Grenzübergangs-
   Regel oben). */
.person-block[data-erwartete-kategorie="erwachsener"]:first-child::before,
.person-block:not([data-erwartete-kategorie="jugendlicher"]) + .person-block[data-erwartete-kategorie="jugendlicher"]::before,
.person-block[data-erwartete-kategorie="jugendlicher"]:first-child::before,
.person-block:not([data-erwartete-kategorie="kind"]) + .person-block[data-erwartete-kategorie="kind"]::before,
.person-block[data-erwartete-kategorie="kind"]:first-child::before {
  display: block;
  font-family: var(--schrift-headline);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--gold-hell);
  font-size: 1rem;
  margin: 0 0 0.75rem;
}

.person-block[data-erwartete-kategorie="erwachsener"]:first-child::before {
  content: "Erwachsene";
}

.person-block:not([data-erwartete-kategorie="jugendlicher"]) + .person-block[data-erwartete-kategorie="jugendlicher"]::before,
.person-block[data-erwartete-kategorie="jugendlicher"]:first-child::before {
  content: "Jugendliche";
}

.person-block:not([data-erwartete-kategorie="kind"]) + .person-block[data-erwartete-kategorie="kind"]::before,
.person-block[data-erwartete-kategorie="kind"]:first-child::before {
  content: "Kinder";
}

.skifahrkoennen-option {
  flex-direction: row;
  align-items: flex-start;
  gap: 0.5rem;
}

.skifahrkoennen-option input {
  margin-top: 0.2rem;
}

/* Plan 19-18 (E-2): "Kursauswahl"-Kacheln (Koennensstufen-Auswahl,
   Phase 17) — der Radio-"Icon" steht per geerbtem .skifahrkoennen-option
   (align-items: flex-start) oben an der ersten Textzeile, sobald
   Name+Beschreibung+Pille auf mehrere Zeilen umbrechen. Gewuenscht:
   Radio am Zeilenanfang, aber vertikal mittig neben dem Text
   (19-18-PLAN.md Task 2). Bewusst auf .koennensstufe-option statt der
   geteilten Basisklasse .skifahrkoennen-option skaliert — jene wird auch
   von den einfachen Skifahrkoennen-Fragen weiter unten genutzt (ohne
   Kursauswahl-Bedeutung), die unveraendert bleiben sollen. Der
   input-margin-top-Ausgleich der Basisklasse (fuer den flex-start-Fall
   gedacht) wird hier auf 0 zurueckgesetzt, da er bei align-items:center
   die Zentrierung wieder verschieben wuerde. */
.koennensstufe-option {
  align-items: center;
}

.koennensstufe-option input {
  margin-top: 0;
}

/* Phase 15 (15-UI-SPEC.md New Component Patterns 1): geteilte Basiskomponente
   fuer alle drei neuen Pillen, portiert aus admin.css's .bezahlt-pille-Form
   (dieselben Padding-/Radius-/Schriftwerte) — die oeffentliche Formularseite
   laedt admin.css nicht, daher hier als eigene Basisklasse. */
.pille {
  display: inline-block;
  border-radius: 999px;
  padding: 0.15rem 0.65rem;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}

.pille--kurstag {
  background: var(--kurstag-gruen-tint);
  color: var(--kurstag-gruen);
}

.pille--rabatt {
  background: var(--rabatt-gold-tint);
  color: var(--rabatt-gold);
}

/* Quick-Task 260920-jhv (G12): auffaelligeres Orange statt gedaempftem Grau
   fuer die Warteliste-Pille an der Koennensstufen-Option — bewusste
   Wiederverwendung des bereits vorhandenen Rabatt-Tokens statt eines neuen
   Hex-Werts. Betrifft NUR diese Pille, nicht .skikurs-warteliste-hinweis
   (Tagestext bleibt bewusst grau/gedaempft, siehe Kommentar dort). */
.pille--warteliste {
  background: var(--rabatt-gold-tint);
  color: var(--rabatt-gold);
}

/* Phase 15 (D-07): eigene Flex-Reihe fuer die Kurstag-Pille links vom
   Kachel-Label. Bewusst NICHT .tn-label-group wiederverwenden — jene ist
   eine Flex-SPALTE fuer den zweizeiligen Skikurs-/Snowboard-Kachel-Hinweis
   (Name + Erklaerungstext untereinander), waehrend .tn-label-row Pille und
   Label in einer Zeile nebeneinander anordnet. */
.tn-label-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Phase 15 (D-09, 15-UI-SPEC.md New Component Patterns 3): dritte Kachel im
   Januar-Teilnahme-Grid. Ausgewaehlter Zustand bewusst GRUEN statt des
   blauen .tn-btn:has(:checked)-Akzents — diese Kachel bedeutet "Skikurs
   findet an diesem Tag statt", nicht "ausgewaehlt". */
.tn-btn--skikurs-optional:has(.tn-btn-input:checked) {
  border-color: var(--kurstag-gruen);
  background: var(--kurstag-gruen-tint);
}

.tn-btn--skikurs-optional:has(.tn-btn-input:checked) .tn-label {
  color: var(--kurstag-gruen);
}

/* G7/WART-03 (Phase 15, 15-21): Hinweis neben der Skikurs-Kachel je
   Januar-Zeile, wenn die gewaehlte Koennensstufe voll ist. Sichtbarkeit
   ausschliesslich clientseitig per updateKoennensstufenEffekte()
   (formular.js) gesteuert, serverseitig immer hidden gerendert. Bewusst
   eigenes, gedaempftes Farbtoken (Quick-Task 260920-jhv, G12: die
   Warteliste-PILLE an der Stufen-Option ist seitdem orange/auffaellig,
   dieser reine Fliesstext bleibt bewusst grau — kein gemeinsames Token
   mehr, keine neue Custom Property).
   Quick-Task 260920-jhv (G13): `grid-column: 1 / -1` nimmt den Hinweis
   aus der einzelnen `max-content`-Spalte von
   .teilnahme-grid.januar-tn-grid.januar-tn-grid--kompakt heraus (siehe
   @media (min-width: 600px) weiter unten) — eine max-content-Spalte sizt
   sich sonst auf die volle EINZEILIGE Breite ihres Inhalts, unabhaengig
   von overflow-wrap auf dem Element selbst, und zog dadurch die gesamte
   Zeile (und das Formular) auf Desktop-Breite auseinander. `width: 0;
   min-width: 100%;` verhindert zusaetzlich, dass der Fliesstext bei der
   intrinsischen Groessenermittlung des Grids als Breiten-Vorschlag
   einfliesst; overflow-wrap/word-wrap sichern einzelne lange Woerter ab. */
.skikurs-warteliste-hinweis {
  font-size: 0.9rem;
  font-weight: 400;
  line-height: 1.3;
  color: var(--warteliste-grau);
  align-self: center;
  margin: 0;
  grid-column: 1 / -1;
  width: 0;
  min-width: 100%;
  box-sizing: border-box;
  overflow-wrap: break-word;
  word-wrap: break-word;
}

/* Phase 15: kleiner, gedaempfter Hinweistext unterhalb der Koennensstufen-
   Radioliste (Fix-/Optional-Copy wird clientseitig in 15-10 gesetzt) — Stil
   identisch zum bestehenden .tn-hint, keine neue Farbe. */
.koennensstufen-hinweis {
  font-size: 0.9rem;
  font-weight: 400;
  line-height: 1.3;
  color: var(--grau-vergangen);
}

/* D-08: Altersklassen-Widerspruch — rote Fehlerblockierung */

.age-err-msg {
  color: var(--fehler-rot);
  background: rgba(220, 38, 38, 0.18);
  border: 1px solid var(--fehler-rot);
  border-radius: 6px;
  padding: 0.6rem 0.8rem;
  font-size: 0.85rem;
  margin: -0.3rem 0 0.9rem;
}

.person-block.age-blocked {
  border: 1px solid var(--fehler-rot);
  border-radius: 8px;
  padding: 1rem;
  background: rgba(220, 38, 38, 0.06);
}

/* ---------------------------------------------------------------------
   Kachel-Pattern (.teilnahme-grid/.tn-btn) — Teilnahme-Art, Buswunsch,
   teilnahme_art_sonder
   --------------------------------------------------------------------- */

.teilnahme-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.6rem;
}

/* D-08-04: 2x2 Kinder-Grid — forces exactly 2 columns at ALL breakpoints
   for the jugendlicher/kind Teilnahme-Art tiles (Mitfahrer nur Bus /
   Mitfahrer inkl. Lift / Kinder-Snowboard / Kinder-Skikurs), overriding
   the 1/2/3-col responsive escalation used for the erwachsener (3-tile)
   and buswunsch (3-tile) grids below. .teilnahme-grid--2x2 is the named
   modifier the design contract specifies; the attribute-selector pair
   scopes it to the two person categories via the existing
   data-erwartete-kategorie attribute already on .person-block
   (index.php renderPersonBlock()) — both person templates render an
   unmodified <div class="teilnahme-grid"> for Teilnahme-Art (no markup
   change needed/in-scope here, ski-design.css-only plan). */
.teilnahme-grid.teilnahme-grid--2x2,
.person-block[data-erwartete-kategorie="jugendlicher"] .teilnahme-art-gruppe .teilnahme-grid,
.person-block[data-erwartete-kategorie="kind"] .teilnahme-art-gruppe .teilnahme-grid {
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
}

/* WR-03 (08-REVIEW.md): januar-tn-grid always has exactly 2 tiles
   (dabei/nicht_dabei) — force 2 columns at ALL breakpoints instead of
   inheriting the generic 1/2/3-col escalation below, which leaves an
   uneven column at ≥900px. sonder-tn-grid is a single tile and should
   span the full row rather than sit in a narrow 1-of-3 column. */
.teilnahme-grid.januar-tn-grid {
  grid-template-columns: repeat(2, 1fr);
}

/* K3 (11-05, 11-UI-SPEC.md §New/Modified Component Patterns Nr. 2): kompakte
   Kopfzeile fuer die Erwachsenen-Januar-Zeile — spaltet den Buttonpaar
   inhaltsbreit statt in zwei erzwungene 1fr-Spalten auf, analog zum bereits
   kompakten .sonder-tn-grid. Drei-Klassen-Spezifitaet (0,3,0) schlaegt sowohl
   .teilnahme-grid.januar-tn-grid (0,2,0) als auch die .teilnahme-grid-Regeln
   in beiden @media-Bloecken (0,1,0) — ohne Important-Deklaration. Mobile-First
   (Backlog 999.3 / Quick-Task 260802-ps2, gemeldet im Live-Test nach
   Phase-11-Deploy): Basisregel ist einspaltig gestapelt, damit die beiden
   Auswahlboxen auch auf Smartphone-Breite nicht erzwungen nebeneinander
   stehen. Ab 600px wird das Zwei-Spalten-Verhalten per Duplikat-Regel im
   bestehenden min-width:600px-Block wiederhergestellt — dort entscheidet
   zwischen den beiden gleich spezifischen Dreiklassen-Regeln die
   Quellreihenfolge (die spaetere gewinnt). gap:8px entspricht bewusst dem
   Design-Contract (11-UI-SPEC.md §Spacing Scale), nicht dem
   0.6rem-Basisabstand von .teilnahme-grid, und gilt unveraendert fuer alle
   Breiten (daher hier und nicht im 600px-Duplikat). */
.teilnahme-grid.januar-tn-grid.januar-tn-grid--kompakt {
  grid-template-columns: 1fr;
  gap: 8px;
}

.januar-tn-grid--kompakt .tn-btn {
  white-space: nowrap;
}

.teilnahme-grid.sonder-tn-grid {
  grid-template-columns: 1fr;
}

.tn-btn {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  border: 1px solid var(--rand);
  border-radius: 8px;
  padding: 0.7rem 0.9rem;
  background: var(--dunkelblau);
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
  margin-bottom: 0;
  font-size: 0.9rem;
}

.tn-btn:hover {
  border-color: var(--gold);
}

/* Nativer Radio-Kreis a11y-sicher versteckt: NICHT display:none/visibility:hidden,
   da diese den Input aus Tab-Reihenfolge und Accessibility-Tree entfernen können.
   opacity:0 + 1px-Größe hält ihn fokussierbar und im a11y-Tree; das umschließende
   <label> (.tn-btn) hält die Kachel klickbar, :has(.tn-btn-input:checked) treibt
   weiter die visuelle Auswahl. pointer-events:none verhindert, dass die 1px-Box
   Klicks abfängt. Fokus bleibt via .tn-btn:focus-within-Outline auf der Kachel sichtbar. */
.tn-btn-input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  pointer-events: none;
}

.tn-icon {
  font-size: 1.2rem;
  line-height: 1;
  flex-shrink: 0;
  filter: grayscale(1);
  opacity: 0.5;
  transition: filter 0.15s ease, opacity 0.15s ease;
}

.teilnahme-art-gruppe .tn-btn .tn-label {
  color: var(--grau-vergangen);
  font-weight: 500;
  transition: color 0.15s ease;
}

.tn-label {
  color: var(--text-hell);
  font-weight: 500;
}

/* K2 (Phase 11, 11-04, 11-UI-SPEC.md Component Pattern 1): zweizeiliger
   Kachel-Hinweistext (nur auf den drei Skikurs-/Snowboard-Kacheln). Beide
   .teilnahme-art-gruppe .tn-btn .tn-label (color: --grau-vergangen) und der
   Checked-Zustand .tn-btn:has(.tn-btn-input:checked) .tn-label (color:
   --gold-hell) selektieren nur .tn-label, nicht .tn-hint — der Hinweistext
   bleibt daher bewusst immer gedaempft, auch bei ausgewaehlter Kachel. */
.tn-label-group {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.tn-hint {
  font-size: 0.9rem;
  font-weight: 400;
  line-height: 1.3;
  color: var(--grau-vergangen);
}

/* Ausgewählter Zustand: modernes :has() (Chrome/Firefox/Safari 15.4+). */
.tn-btn:has(.tn-btn-input:checked) {
  border-color: var(--gold);
  background: rgba(37, 119, 200, 0.16);
}

.tn-btn:has(.tn-btn-input:checked) .tn-icon {
  filter: none;
  opacity: 1;
}

.tn-btn:has(.tn-btn-input:checked) .tn-label {
  color: var(--gold-hell);
  font-weight: 700;
}

.tn-btn:focus-within {
  outline: 2px solid var(--gold-hell);
  outline-offset: 2px;
}

/* Quick-Task 260727-rgb (Punkt 4): erbt die .tn-btn-Kacheloptik (Auswahl-
   Zustand/Fokus-Ring bereits über .tn-btn:has()/.tn-btn:focus-within oben
   abgedeckt) — nur Blockbreite/Abstand innerhalb der Aufsichtsperson-Warnung
   nachjustiert, keine neuen Farben. */
.nur-jugendwochenende-btn {
  width: 100%;
  margin-bottom: 0.6rem;
}

.nur-jugendwochenende-hinweis {
  font-size: 0.85rem;
  font-weight: 400;
  color: var(--text-hell);
  margin: 0 0 0.9rem;
}

.teilnahme-art-sonder-row {
  margin-top: 0.9rem;
  padding-top: 0.9rem;
  border-top: 1px dashed var(--rand);
}

.teilnahme-art-sonder-row p {
  margin: 0 0 0.5rem;
  font-size: 0.85rem;
  color: var(--gold-hell);
}

/* Vertretung-Kachel (10-04-PLAN.md, D-10-02/D-10-04/D-10-06): natives
   <details>/<summary> (kein JS nötig), portiert aus admin.css
   .einstellungen-bereich-Akkordeon (admin.css:298-326), aber mit den
   öffentlichen Blau-Tokens statt Admin-Amber. Zugeklappt als Default —
   kein open-Attribut. */
/* Phase 16 (D-06, 16-UI-SPEC.md Komponente 3b), Gap-Closure G3/G4 (16-12,
   2026-09-25): die Teil-Engpass-Auswahl teilt sich mit der Vertretung-
   Kachel nur noch den Kartenrahmen (Border/Radius/Background/Padding) —
   ihre Akkordeon-Mechanik ist NICHT geteilt. Die Vertretung-Kachel bleibt
   ein natives Akkordeon-Element; die Teil-Engpass-Auswahl ist ein reines,
   JS-gesteuertes Element mit genau einem Sichtbarkeitszustand (hidden),
   siehe die neue Titelregel weiter unten. */
/* Phase 19 (19-06, 19-UI-SPEC.md Komponente 1): die neue Mitfahren-Tag-
   Karte erweitert dieselbe Selektorliste, statt eine eigene Kartenrahmen-
   Regel zu duplizieren (Projekt-Konvention: Liste erweitern, nicht
   verdoppeln). */
.vertretung-kachel,
.termin-engpass-auswahl,
.mitfahren-tag-karte {
  border: 1px solid var(--rand);
  border-radius: 8px;
  background: var(--dunkelblau-karte);
  padding: 16px;
}

.vertretung-kachel > summary {
  cursor: pointer;
  font-weight: 700;
  color: var(--gold-hell);
  list-style: none;
}

.vertretung-kachel > summary::-webkit-details-marker {
  display: none;
}

.vertretung-kachel > summary::before {
  content: "▸ ";
}

.vertretung-kachel[open] > summary::before {
  content: "▾ ";
}

/* Phase 16 Gap-Closure G3/G4 (16-12, 2026-09-25): Ersatz für die frühere
   <summary>-Typografie der Engpass-Auswahl — übernimmt deren Werte 1:1,
   ohne die ▸/▾-Marker-Glyphen (der Bereich klappt nicht mehr per Klick auf
   die Überschrift, sondern folgt dem Modus-Radio). */
.termin-engpass-auswahl-titel {
  margin: 0 0 0.6rem;
  font-weight: 700;
  color: var(--gold-hell);
}

/* Ausfahrten / Sonderausfahrten Zeilen */

.ausfahrt-zeile,
.sonderausfahrt-zeile {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--rand);
}

.ausfahrt-zeile:last-child,
.sonderausfahrt-zeile:last-child {
  border-bottom: none;
}

.ausfahrt-name,
.sonderausfahrt-name {
  font-weight: 600;
  flex: 1 1 auto;
}

/* FORM-10: vergangene Ausfahrten ausgegraut/nicht wählbar */

.ausfahrt-zeile.past,
.sonderausfahrt-zeile.past {
  opacity: 0.5;
  color: var(--grau-vergangen);
  text-decoration: line-through;
}

.ausfahrt-zeile.past .ausfahrt-name,
.sonderausfahrt-zeile.past .sonderausfahrt-name {
  color: var(--grau-vergangen);
}

/* K10/D-08 (Phase 11, 11-06): dritter, klar abgegrenzter Januar-Zeilen-
   Zustand — vorübergehend nicht verfügbar (Personendaten/Teilnahme-Art
   fehlen noch), NICHT dasselbe wie .past (dauerhaft vergangen,
   durchgestrichen) und NICHT dasselbe wie .warteliste-modus (Akzent-Blau,
   Kachel bleibt aktiv). Nutzt bewusst ausschließlich das bereits
   vorhandene, gedämpfte --grau-vergangen-Grau plus eine gestrichelte
   --rand-Umrandung — keine neue Farbe, keine neue Custom Property, kein
   Rot (kein Fehlerzustand).
   Seit Phase 999.5 (R1/R3/R4) deckt dieselbe Regel zusätzlich die
   Personenanzahl-Auswahl ab, die vor erteilter Zustimmung zum
   Zustimmungsgate ebenfalls gesperrt ist — derselbe Sperr-Ton, kein
   zweiter Opacity-Wert. */
.ausfahrt-zeile.gesperrt,
.personenzahl-grid.gesperrt {
  opacity: 0.6;
}

.gesperrt-hinweis {
  flex-basis: 100%;
  margin: 4px 0 0;
  font-size: 0.9rem;
  font-weight: 400;
  line-height: 1.3;
  color: var(--grau-vergangen);
  background: var(--dunkelblau);
  border: 1px dashed var(--rand);
  border-radius: 6px;
  padding: 8px;
}

/* WART-01/D-24: voller Termin -> "Auf Warteliste"-Zustand, optisch klar von
   der normalen Ja/Nein-Checkbox UND vom .past-Zustand abgesetzt (kein
   bloßer Hinweistext). Server entscheidet allein (D-12), Checkbox bleibt
   aktiv (NICHT disabled) — der Nutzer soll sich bewusst auf die Warteliste
   setzen können. */

.ausfahrt-zeile.warteliste-modus,
.sonderausfahrt-zeile.warteliste-modus {
  background: rgba(37, 119, 200, 0.16);
  border: 1px solid var(--gold);
  border-radius: 8px;
  padding: 0.6rem 0.8rem;
}

.ausfahrt-zeile.warteliste-modus .ausfahrt-name,
.sonderausfahrt-zeile.warteliste-modus .sonderausfahrt-name {
  color: var(--gold-hell);
}

/* D-08-05/D-08-06 retargeted this rule from the pre-Phase-8
   .ja-nein-toggle/.dabei-toggle checkbox spans (removed above, replaced by
   the .tn-btn Kachel pattern) to the current "Auf Warteliste"-Kachel label
   — scoped to :first-child so only the dabei-tile is bolded, not the
   nicht_dabei tile or (for Sonderausfahrten) the nested Mitfahrt-Art
   sub-tiles living in their own unmodified .teilnahme-grid. */
.ausfahrt-zeile.warteliste-modus .teilnahme-grid.januar-tn-grid .tn-btn:first-child .tn-label,
.sonderausfahrt-zeile.warteliste-modus .teilnahme-grid.sonder-tn-grid .tn-btn:first-child .tn-label {
  font-weight: 700;
  color: var(--gold-hell);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.nachricht-skilehrer-feld {
  margin-top: 0.5rem;
}

/* Kommentar / Wortzähler */

.wortzaehler {
  font-size: 0.8rem;
  color: rgba(17, 24, 39, 0.7);
  margin: -0.5rem 0 0.5rem;
}

/* ---------------------------------------------------------------------
   Kostenübersicht (FORM-16)
   --------------------------------------------------------------------- */

.kostenuebersicht {
  margin: 1rem 0;
  border: 1px solid var(--rand);
  border-radius: 8px;
  padding: 0.9rem 1rem;
  background: var(--dunkelblau);
}

.kostenuebersicht table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

.kostenuebersicht th,
.kostenuebersicht td {
  text-align: left;
  padding: 0.4rem 0.3rem;
  border-bottom: 1px solid var(--rand);
}

.kostenuebersicht tfoot td {
  font-weight: 700;
  /* Gold-Akzent (Kostenbetrag), vertiefte WCAG-sichere Variante von Referenz-#e8b84b */
  color: #8F6D0D;
  border-bottom: none;
}

.kostenuebersicht .warteliste-zeile td:last-child {
  color: rgba(17, 24, 39, 0.6);
  font-style: italic;
}

.kostenuebersicht .rabatt-zeile td {
  color: var(--gold-hell);
}

/* D-21: Bestätigungs-Banner nach dem Absenden — benennt explizit, welche
   Termine per Race-Condition auf die Warteliste umgebucht wurden. Gold statt
   Rot (kein Validierungsfehler, siehe .warnhinweis), analog zum bestehenden
   .warteliste-modus-Ton. Ergänzt die .warteliste-zeile-Darstellung, ersetzt
   sie nicht. */

.warteliste-hinweis-banner {
  margin: 1rem 0;
  border: 1px solid var(--gold);
  background: rgba(37, 119, 200, 0.16);
  border-radius: 8px;
  padding: 0.9rem 1rem;
}

.warteliste-hinweis-banner p {
  margin-top: 0;
  font-weight: 700;
  color: var(--gold-hell);
}

.warteliste-hinweis-banner ul {
  margin: 0.4rem 0 0;
  padding-left: 1.2rem;
}

.warteliste-hinweis-banner li {
  color: rgba(17, 24, 39, 0.9);
}

/* Backlog-Punkt 999.4-7 / D-12 / D-13: Hinweis, dass die Bus/Lift-Wahl
   ("nur Busfahrt" / "Busfahrt (zzgl. Liftticket)") nur der Planungssicherheit
   des Vereins dient und am Ausfahrtstag im Bus noch änderbar ist. Bewusst die
   Gold-/Blau-Familie (--gold, rgba(37, 119, 200, 0.16)) analog
   .warteliste-hinweis-banner statt --fehler-rot/.warnhinweis, weil dies ein
   informativer Hinweis und kein Validierungsfehler ist. Die in
   999.4-UI-SPEC.md genannten --color-accent*-Tokens werden hier bewusst NICHT
   verwendet, da sie nur in admin.css definiert sind — public/index.php lädt
   admin.css gar nicht, nur dieses ski-design.css. */

.bus-hinweis {
  border: 1px solid var(--gold);
  background: rgba(37, 119, 200, 0.16);
  border-radius: 8px;
  padding: 0.9rem 1rem;
  margin: 0.6rem 0 0;
  font-size: 0.85rem;
  line-height: 1.4;
  color: var(--text-hell);
}

/* Plan 19-18 (E-1): gelbe Info-Box am Anfang des Mitfahren-Schritts, siehe
   MITFAHREN_INFO_HINWEIS-Docblock in public/index.php. Layout analog
   .warteliste-hinweis-banner (Rahmen + getönter Hintergrund), aber mit dem
   neuen --info-gelb-Farbtripel statt der blauen --gold-Familie. */
.mitfahren-info-box {
  margin: 0.75rem 0 1.1rem;
  border: 1px solid var(--info-gelb-rand);
  background: var(--info-gelb-tint);
  border-radius: 8px;
  padding: 0.9rem 1rem;
}

.mitfahren-info-box p {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--info-gelb);
}

/* ---------------------------------------------------------------------
   Erfolgs-Ansicht (Quick-Task 260725-s6s, Task 4) — ersetzt nach dem
   Absenden das gesamte Formular. Karten-Look analog zu .kostenuebersicht.
   --------------------------------------------------------------------- */

.erfolg-ansicht {
  margin: 1.5rem 0;
  border: 1px solid var(--rand);
  border-radius: 8px;
  padding: 1.25rem 1.4rem;
  background: var(--dunkelblau);
}

.erfolg-ansicht h2 {
  margin-top: 0;
}

.erfolg-code {
  font-size: 1.1rem;
}

.erfolg-code strong {
  font-size: 1.4rem;
  color: var(--gold-hell);
  letter-spacing: 0.05em;
}

/* ---------------------------------------------------------------------
   Navigation & Buttons
   --------------------------------------------------------------------- */

.schritt-nav {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 1.25rem;
}

button {
  font-family: var(--schrift-text);
  font-size: 0.95rem;
  font-weight: 700;
  padding: 0.65rem 1.4rem;
  border-radius: 999px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.1s ease, background 0.15s ease;
}

button:active {
  transform: scale(0.97);
}

.btn-weiter,
.btn-absenden {
  background: var(--gold);
  color: #FFFFFF;
  margin-left: auto;
}

/* D-19/D-20/D-21 (16-UI-SPEC.md Layout Notes Punkt 1): Stepper-Minus
   bleibt bei 0 sichtbar (Dimming-Regel oben), Schritt 1 bekommt einen
   vollbreiten Weiter-Button, Schritt 2-4 teilen Zurück/Weiter exakt
   50/50. Der Screenshot aus 16-CONTEXT.md <specifics> bestätigt die
   Symmetrie mit .zustimmungsgate-download (bereits width: 100%) als
   Referenz. */

/* D-20: Schritt 1 ist die einzige .schritt-nav ohne Zurück-Button —
   die einzig-Kind-Pseudoklasse trifft damit exakt diesen Fall. */
.schritt-nav .btn-weiter:only-child {
  width: 100%;
  margin-left: 0;
}

/* D-21: sobald ein Zurück-Button vorhanden ist (Schritt 2-4), teilen
   sich Zurück und Weiter/Absenden die Zeile 50/50. justify-content:
   space-between bleibt als :has()-Fallback bewusst stehen. */
.schritt-nav:has(.btn-zurueck) {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.schritt-nav:has(.btn-zurueck) .btn-zurueck {
  width: 100%;
}

.schritt-nav:has(.btn-zurueck) .btn-weiter,
.schritt-nav:has(.btn-zurueck) .btn-absenden {
  width: 100%;
  margin-left: 0;
}

.btn-weiter:hover,
.btn-absenden:hover {
  background: var(--gold-hell);
}

/* Q4/D-08 (Phase 999.6): "Weiteren Teilnehmer anmelden"-Button auf der
   Erfolgsseite — visuell identisch zu .btn-weiter/.btn-absenden, da er die
   einzige verbleibende primäre Aktion auf dem Erfolgsbildschirm ist. */
.btn-neue-anmeldung {
  background: var(--gold);
  color: #FFFFFF;
  display: block;
  width: 100%;
}

.btn-neue-anmeldung:hover {
  background: var(--gold-hell);
}

/* Quick-Task 260725-s6s (Task 3): Weiter-Button-Gating — bewusst NICHT über
   das native disabled-Attribut (kein Hover-Tooltip dort), sondern über
   aria-disabled + diese Klasse (siehe formular.js setWeiterGate()). */
.btn-weiter-gesperrt {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn-weiter-gesperrt:hover {
  background: var(--gold);
}

.btn-zurueck {
  background: transparent;
  color: var(--text-hell);
  border-color: var(--rand);
}

.btn-zurueck:hover {
  border-color: var(--gold);
}

/* ---------------------------------------------------------------------
   Fußbereich
   --------------------------------------------------------------------- */

.fuss {
  text-align: center;
  padding: 1.5rem 1rem 2.5rem;
  color: rgba(17, 24, 39, 0.6);
  font-size: 0.8rem;
}

/* ---------------------------------------------------------------------
   Phase 9 (09-06, JW-01..03): Jugendwochenende-Fragebogen — Fieldset-
   Oberfläche, Personendaten-Echo (UI-SPEC New Component Pattern 2) und
   die Legal-Consent-Blöcke (Patterns 3+4). Reine Erweiterung der
   bestehenden Custom Properties oben — keine neue Farbe, kein neues
   Schriftgewicht, keine Schriftgröße unter 13px (09-UI-SPEC.md).
   --------------------------------------------------------------------- */

/* K4/D-01 (Phase 11, 11-04, 11-UI-SPEC.md Component Pattern 3): Panel
   schmaeler als sein .person-block-Elterncontainer statt das Formular
   insgesamt zu verbreitern — erzeugt symmetrische Raender links/rechts.
   main/.person-block selbst bleiben unangetastet. */
.jugendwochenende-block {
  background: var(--dunkelblau-karte);
  border: 1px solid var(--rand);
  padding: 16px;
  max-width: calc(100% - 16px);
  margin: 0 auto;
}

/* 12px (md) Abstand zwischen den 5 direkten Unter-Fieldsets (Adresse,
   Notfallkontakt, Medizin/Verpflegung, Allergien, Ernährungsform) —
   enger als der 16px-Fieldset-Standard, da dies Unter-Abschnitte EINER
   bereits gescopten Person sind, keine eigenständigen Wizard-Schritte
   (UI-SPEC Spacing-Ausnahme). ">"-Kindselektor lässt die verschachtelten
   .skifahrkoennen-gruppe-Fieldsets darin unangetastet. */
.jugendwochenende-block > fieldset {
  margin-bottom: 12px;
}

.jugendwochenende-block > fieldset:last-of-type {
  margin-bottom: 0;
}

.jugendwochenende-person-echo {
  font-size: 14px;
  font-weight: 400;
  line-height: 1.4;
  color: var(--text-hell);
  margin: 0 0 12px;
}

/* Markenkonforme native Steuerelemente (Tetanus/Medikamente/
   Wundversorgung/Schwimmer/Allergien/Ernährung/Einwilligungen) —
   deckt auch die verschachtelten .consent-checkbox-Inputs unten ab,
   analog zur bestehenden .skifahrkoennen-option-Behandlung. */
.jugendwochenende-block input[type="radio"],
.jugendwochenende-block input[type="checkbox"] {
  accent-color: var(--gold);
}

.jugendwochenende-einwilligungen {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* Pattern 3 — sechs Pflicht-Einwilligungen als Einzel-Checkbox-Block +
   Pattern 4 — Foto-Einwilligung als zweizeiliges Radio-Paar, gleiche
   Optik. align-items: flex-start, da der Text auf 3-6 Zeilen umbricht
   (Checkbox bleibt an der ersten Zeile ausgerichtet, nicht vertikal
   zentriert). min-height 44px wird über padding erreicht, nicht über
   Schriftverkleinerung (Touch-Target-Konvention wie .stepper-btn). */
.consent-checkbox {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px;
  border: 1px solid var(--rand);
  border-radius: 8px;
  background: var(--dunkelblau-karte);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5;
  min-height: 44px;
  margin-bottom: 0;
  cursor: pointer;
}

.consent-checkbox input {
  margin: 0.15rem 0 0;
  flex-shrink: 0;
}

/* Foto-Einwilligung (Pattern 4): die beiden Radio-Zeilen sitzen enger
   beieinander (8px) als die 12px-Standardlücke zwischen den übrigen
   Einwilligungsblöcken — negative margin-top auf der zweiten Zeile
   reduziert die geerbte Flex-gap von 12px auf 8px. */
.jugendwochenende-einwilligungen .consent-checkbox:has(input[name*="[einwilligung_fotos]"]) + .consent-checkbox:has(input[name*="[einwilligung_fotos]"]) {
  margin-top: -4px;
}

/* Invalid-Zustand (Pflicht-Einwilligung beim Absenden nicht angehakt) —
   swap auf --fehler-rot, exakt der bestehende Farbwert aus .warnhinweis/
   .age-err-msg. Explizit KEINE neue Warnfarbe (UI-SPEC "Explicit
   non-goal"). */
.consent-checkbox:has(input:invalid) {
  border-color: var(--fehler-rot);
}

/* Quick-Task 260727-rgb (Punkt 3): kurze Überschrift über jeder der 6
   Pflicht-Einwilligungen + eigene Foto-Kachel. 4px Abstand zwischen Titel
   und Label — der 12px-gap von .jugendwochenende-einwilligungen trennt die
   Blöcke weiterhin voneinander. */
.consent-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.consent-titel {
  font-family: var(--schrift-headline);
  font-size: 16px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--gold-hell);
  margin: 0;
}

/* Gleiche Kartenoptik wie .consent-checkbox (1px --rand, 8px Radius,
   --dunkelblau-karte, 12px Padding) — die beiden Radio-Zeilen darin
   behalten .consent-checkbox (inkl. der bestehenden 8px-Abstand-Regel
   oben). */
.consent-foto-box {
  border: 1px solid var(--rand);
  border-radius: 8px;
  background: var(--dunkelblau-karte);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.consent-foto-box legend {
  font-family: var(--schrift-headline);
  font-size: 16px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--gold-hell);
  margin: 0 0 4px;
  padding: 0;
}

/* ---------------------------------------------------------------------
   Phase 999.5 (R1/R3/R4, 999.5-UI-SPEC.md §Component Specification):
   Zustimmungsgate am Anfang von Schritt 1 — Überschrift/Untertitel,
   Checkbox links + PDF-Download-Button rechts. Reine Erweiterung
   bestehender Bausteine (.consent-checkbox, Button-Basisregel,
   .stepper-btn:focus-visible), keine neue Farbe/Custom Property.
   --------------------------------------------------------------------- */

.zustimmungsgate {
  margin-bottom: 1.5rem;
}

.zustimmungsgate h2 {
  margin-top: 0;
}

.zustimmungsgate-untertitel {
  margin: 0 0 12px;
  font-size: 1rem;
  line-height: 1.5;
  color: var(--text-hell);
}

.zustimmungsgate-zeile {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
}

.zustimmungsgate input[type="checkbox"] {
  accent-color: var(--gold);
}

.zustimmungsgate-download {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0.65rem 1.4rem;
  border-radius: 999px;
  border: 1px solid transparent;
  background: var(--gold);
  color: #FFFFFF;
  font-family: var(--schrift-text);
  font-size: 0.95rem;
  font-weight: 700;
  line-height: 1.3;
  text-align: center;
  text-decoration: none;
}

.zustimmungsgate-download:hover {
  background: var(--gold-hell);
}

.zustimmungsgate-download:focus-visible {
  outline: 2px solid var(--gold-hell);
  outline-offset: 2px;
}

/* Die Checkbox ist ab dem ersten Rendern :invalid (unangehakt + required) —
   ohne diese Neutralisierung wäre der Block schon beim Seitenaufruf rot,
   obwohl der Nutzer noch nichts falsch gemacht hat (999.5-UI-SPEC.md §2:
   der Invalid-Zustand gehört an den Weiter-Versuch, nicht an den
   Seitenaufruf). */
.zustimmungsgate .consent-checkbox:has(input:invalid) {
  border-color: var(--rand);
}

/* Fehlerzustand, den Plan 999.5-03 per Klasse .zustimmung-fehler auf dem
   Container einschaltet, sobald der Nutzer trotz fehlender Zustimmung auf
   „Weiter" klickt. */
.zustimmungsgate.zustimmung-fehler .consent-checkbox:has(input:invalid) {
  border-color: var(--fehler-rot);
}

/* ---------------------------------------------------------------------
   Responsive (Success Criterion 5): Mobile-First-Basis oben, ab Tablet/
   Desktop mehrspaltige Grids.
   --------------------------------------------------------------------- */

@media (min-width: 600px) {
  .personenzahl-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .feld-gruppe {
    grid-template-columns: repeat(3, 1fr);
  }

  /* K5/D-10 (Phase 11, 11-04, 11-UI-SPEC.md Component Pattern 4): explizite,
     feldanzahl-unabhaengige 2-Spalten-Paarung fuer die Jugendwochenende-
     Feldgruppen — MUSS nach der .feld-gruppe-Dreispalten-Regel stehen. Unter
     600px bleibt .feld-gruppe (D-10) unveraendert einspaltig gestapelt. */
  .feld-gruppe.feld-gruppe--paar {
    grid-template-columns: repeat(2, 1fr);
  }

  .teilnahme-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Backlog 999.3 / 260802-ps2 — Gegenstueck zur einspaltigen Basisregel
     oben: ab 600px stehen die beiden Januar-Auswahlboxen wieder inhaltsbreit
     nebeneinander (K3-Verhalten aus 11-05), unveraendert gegenueber vor
     diesem Fix. */
  .teilnahme-grid.januar-tn-grid.januar-tn-grid--kompakt {
    grid-template-columns: max-content max-content;
  }

  .buswunsch-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  /* K4/D-01 (Phase 11, 11-04, 11-UI-SPEC.md Component Pattern 3): ab 600px
     16px/Seite statt 8px/Seite Mobile-Rand. */
  .jugendwochenende-block {
    max-width: calc(100% - 32px);
  }
}

@media (min-width: 900px) {
  main {
    padding-top: 2rem;
  }

  .teilnahme-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* ---------------------------------------------------------------------
   Phase 16 — Bus-Kapazität, Termin-Status, Vertretung
   Reines CSS für den in 16-UI-SPEC.md festgelegten visuellen Vertrag;
   Markup/JS folgen erst in 16-05/16-07. Additiv — die einzige Ausnahme
   ist die .vertretung-kachel-Selektor-Erweiterung weiter oben (siehe
   Kommentar dort), sonst wird keine bestehende Regel verändert.
   --------------------------------------------------------------------- */

/* D-03: Bus-Wunsch-Kachel "Bereits ausgebucht" — derselbe Opacity-Wert
   wie die bestehende .ausfahrt-zeile.gesperrt-Regel, kein zweiter
   Dimming-Wert. */
.tn-btn:has(.tn-btn-input:disabled) {
  cursor: not-allowed;
  opacity: 0.6;
}

/* D-03: Rot-Variante von .tn-hint für den Text "Bereits ausgebucht". */
.tn-hint--fehler {
  color: var(--fehler-rot);
  font-weight: 500;
}

/* D-09: Stapel-Container für die Termin-Status-Zeilen in Schritt 3. */
.termin-status-liste {
  display: block;
  margin: 0.6rem 0 0;
}

.termin-status {
  border-radius: 8px;
  padding: 0.6rem 0.8rem;
  margin: 0 0 1rem;
  font-size: 0.9rem;
  line-height: 1.4;
}

/* D-09, Fall "ausreichend" — neues Kapazitäts-Grün, siehe :root-Token. */
.termin-status--frei {
  border: 1px solid var(--kapazitaet-frei-gruen);
  background: var(--kapazitaet-frei-gruen-tint);
  color: var(--text-hell);
}

.termin-status--frei strong {
  color: var(--kapazitaet-frei-gruen);
}

/* D-07: visuell identisch zur bestehenden .warteliste-hinweis-banner-
   Familie — "identischer Mechanismus, kein neuer Warteliste-Typ". */
.termin-status--warteliste {
  border: 1px solid var(--gold);
  background: rgba(37, 119, 200, 0.16);
  font-weight: 700;
  color: var(--gold-hell);
}

/* D-06: erwarteter Entscheidungsfall (Teil-Engpass) — bewusst NICHT rot,
   dieselbe Gold-/Blau-Familie wie .bus-hinweis/.warteliste-hinweis-banner. */
.termin-engpass-kachel {
  border: 1px solid var(--gold);
  background: rgba(37, 119, 200, 0.16);
  border-radius: 8px;
  padding: 16px;
  margin: 0 0 1rem;
}

.termin-engpass-titel {
  margin: 0 0 0.6rem;
  font-weight: 700;
  color: var(--gold-hell);
}

.termin-engpass-titel strong {
  color: var(--gold-hell);
}

.termin-engpass-personen {
  display: grid;
  gap: 0.5rem;
}

/* Phase 16 Gap-Closure (G1), 16-09-PLAN.md: gedimmter, nicht anklickbarer
   Zustand für eine Engpass-Personen-Auswahl, deren Restplatzzahl erreicht
   ist. Kein neuer Farbwert, kein neues Token. */
.termin-engpass-personen label.gesperrt {
  opacity: 0.5;
  cursor: not-allowed;
}

/* D-14…D-17: dritte Vertretungs-Option "Bereits separat angemeldet" —
   überschreibt für diese eine Gruppe die Mehrspaltigkeit von
   .sonder-tn-grid; alle drei Kacheln stehen untereinander in voller
   Breite (User-Entscheidung aus dem interaktiven Layout-Review,
   16-UI-SPEC.md Komponente 4). Bewusst NACH .sonder-tn-grid platziert
   und als .teilnahme-grid.vertretung-art-grid geschrieben, damit die
   Spezifität die bestehende .teilnahme-grid.sonder-tn-grid-Regel
   schlägt. */
.teilnahme-grid.vertretung-art-grid {
  grid-template-columns: 1fr;
}

/* ---------------------------------------------------------------------
   Phase 17 (Skikurs-Organisation), Plan 17-12: Landing-Page des
   Bestätigungsmail-Flows (public/nachruecken-bestaetigen.php,
   17-UI-SPEC.md Komponente 1). Rein additiv — keine bestehende Regel
   dieser Datei wird verändert.
   --------------------------------------------------------------------- */

/* landing-ablehnen ist NICHT --fehler-rot gefüllt (kein Fehlerzustand) —
   Outline-Button, sekundäre Aktion, dieselbe Rot-Familie wie die
   destruktiven Admin-Aktionen, aber deutlich zurückhaltender als die
   primäre Annehmen-Aktion (.btn-weiter). Padding ist grid-aligned
   (16px/24px — lg/xl aus dem 17-UI-SPEC.md-Spacing-Scale), nicht das
   sitewide 0.65rem/1.4rem der Basis-Button-Regel, da dieser Button neu
   für Phase 17 ist. */
.btn-ablehnen {
  font-family: var(--schrift-text);
  font-size: 1rem;
  padding: 1rem 1.5rem;
  min-height: 44px;
  border-radius: 8px;
  border: 1px solid var(--fehler-rot);
  background: transparent;
  color: var(--fehler-rot);
  cursor: pointer;
}

.btn-ablehnen:hover {
  background: var(--fehler-bg);
}

.landing-kosten-zeile {
  font-size: 1rem;
  margin: 0.75rem 0;
}

.landing-frist-hinweis {
  font-size: 0.9rem;
  color: var(--text-hell);
}

/* Informativer Blauton der bestehenden .bus-hinweis-Familie — Zustand
   "entschieden" (D-28): die Entscheidung ist bereits gespeichert, das
   ist keine Warnung. */
.landing-status-banner {
  border: 1px solid var(--gold);
  background: rgba(37, 119, 200, 0.16);
  border-radius: 8px;
  padding: 1rem 1.5rem;
  margin: 0.75rem 0 0;
  color: var(--text-hell);
}

/* Gedämpfter Grauton — Zustände "abgelaufen" (D-27) und "zurueckgezogen"
   (D-32): beide sind nicht mehr aktionsfähig, dieselbe visuelle Sprache
   wie bereits ausgegraute, vergangene Ausfahrten im Formular. */
.landing-status-banner--abgelaufen {
  border-color: var(--warteliste-grau);
  background: var(--warteliste-grau-tint);
  color: var(--grau-vergangen);
}

/* ---------------------------------------------------------------------
   Phase 19 (Kurs-Warteliste-Sicherheitsfix und Mitfahren-Entscheidung),
   Plan 19-06: statische Hälfte des neuen fünften Formularschritts
   (19-UI-SPEC.md Komponente 1/2). Der Kartenrahmen der neuen Tag-Karte
   selbst ist KEINE eigene Regel hier — er erweitert die bestehende
   Vertretung-/Engpass-Kartenrahmen-Selektorliste weiter oben in dieser
   Datei (Projekt-Konvention: Liste erweitern, nicht duplizieren). Alle
   Werte unten sind wörtliche Wiederverwendungen aus der genehmigten
   UI-SPEC — kein neuer Farb- oder Spacing-Wert.
   --------------------------------------------------------------------- */

/* Checker-Fix (19-UI-SPEC.md Spacing Scale): Achtel-rem-Wert entspricht
   8px = sm-Token, bewusst kleiner als das ältere .termin-engpass-titel-
   Vorbild — die Abweichung zum älteren Vorbild ist beabsichtigt, kein
   Versehen. */
.mitfahren-tag-titel {
  margin: 0 0 0.5rem;
  font-weight: 700;
  color: var(--gold-hell);
}

/* Gestapelt, analog .teilnahme-grid.vertretung-art-grid (Phase 16): jede
   der drei Optionen trägt eine zweite Hinweiszeile, ein Mehrspalten-Grid
   würde ungleiche Kachelhöhen erzeugen. Spezifität schlägt die generische
   .teilnahme-grid-Regel, deshalb als zusammengesetzter Selektor
   geschrieben und nach den bestehenden .teilnahme-grid-Varianten
   platziert. */
.teilnahme-grid.mitfahren-optionen-grid {
  grid-template-columns: 1fr;
}

/* D-03: Race-Condition-Recovery-Banner. Die rote Optik kommt vollständig
   aus der bereits vorhandenen .age-err-msg-Regel (im Markup mitgesetzt) —
   hier nur der zusätzliche Abstand, keine Farb-/Border-Deklaration
   dupliziert. */
.mitfahren-race-hinweis {
  margin: 0 0 1rem;
}

/* Phase 23 D-01: Honeypot-Feld. Bewusst NICHT mit display:none versteckt,
   damit Bots es wie ein normales Feld sehen; stattdessen weit ausserhalb
   des Viewports platziert (fuer Menschen und Screenreader unsichtbar,
   Container traegt aria-hidden, Feld tabindex=-1). */
.hp-feld {
  position: absolute;
  left: -10000px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Phase 26 (D-20): Testzugang-Banner oberhalb des Formulars. */
.testzugang-banner {
  max-width: 760px;
  margin: 0 auto 16px;
  background: #FEF3C7;
  border: 1px solid #F59E0B;
  border-radius: 8px;
  padding: 10px 14px;
  font-size: .9rem;
  color: #111827;
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}

.testzugang-banner strong {
  font-family: var(--schrift-headline);
  letter-spacing: .05em;
  font-size: 1.1rem;
  font-weight: 400;
  text-transform: uppercase;
  color: #92400E;
}

.testzugang-banner span {
  flex: 1 1 260px;
}
