/* Echolux-Theme.
   Farbwelt der Website als Design-Tokens, Lato für Text, Bebas Neue für
   Headlines. Schriften und Logo liegen lokal unter kern/static/kern/.

   Zwei Themen (dunkel/hell) plus Systemvorgabe.
   - Roh-Tokens (`--farbe-*`) sind konstante Werte der Marke.
   - Semantische Tokens (`--fl-*`, `--text-*`, `--linie`, `--akzent-*`,
     `--balken-*`, `--schatten-*`) sind die einzigen Werte, die im
     Stylesheet weiter unten verwendet werden. Sie bekommen im Hellen ein
     eigenes Overlay.
   - Umschaltung: das Attribut `data-thema` am <html> gewinnt vor dem
     System. Fehlt es, folgt das System via `prefers-color-scheme`.
     „Automatisch“ entfernt das Attribut, es setzt keinen dritten Wert –
     sonst friert eine spätere Systemänderung ein. */

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

@font-face {
  font-family: "Lato";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/lato-latin-400-normal.e1b3b5908c9c.woff2") format("woff2");
}

@font-face {
  font-family: "Lato";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/lato-latin-400-italic.efee2d080d7b.woff2") format("woff2");
}

@font-face {
  font-family: "Lato";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/lato-latin-700-normal.de69cf9e514d.woff2") format("woff2");
}

@font-face {
  font-family: "Lato";
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/lato-latin-700-italic.865e46af8163.woff2") format("woff2");
}

@font-face {
  font-family: "Bebas Neue";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/bebas-neue-latin-400-normal.5853435d21b1.woff2") format("woff2");
}

/* --- Design-Tokens -------------------------------------------------------- */

:root {
  /* --- Roh-Tokens (unverändert dunkel-motiviert, konstant je Modus) ---- */
  --farbe-schwarz: #000;
  --farbe-hintergrund: #0b0b0b;
  --farbe-flaeche: #292929;
  --farbe-linie: #3a3a3a;
  --farbe-weiss: #fff;
  --farbe-text: #f2f2f2;
  --farbe-text-leise: #a5a5a5;
  --farbe-text-still: #777;
  --farbe-grau-100: #eaeaea;
  --farbe-grau-200: #d6d6d6;
  --farbe-grau-300: #bdbdbd;
  --farbe-grau-500: #777;
  --farbe-akzent: #303857;
  --farbe-akzent-mittel: #646d93;
  --farbe-akzent-hell: #7784aa;
  --farbe-akzent-heller: #8997c0;
  --farbe-erfolg: #5f8f6a;
  --farbe-warnung: #b8934a;
  --farbe-fehler: #b8554f;
  --farbe-fehler-hell: #e08a85;

  /* --- Semantische Tokens (Vorgabe: dunkles Thema) --------------------- */
  --fl-blatt: var(--farbe-hintergrund);
  --fl-erhaben: var(--farbe-flaeche);
  --fl-kontrast: var(--farbe-schwarz);
  --fl-zebra: rgba(41, 41, 41, 0.5);
  --fl-hover: var(--farbe-flaeche);
  --fl-wochenende: rgba(255, 255, 255, 0.07);
  --fl-wochenende-kalender: rgba(255, 255, 255, 0.04);
  --fl-hover-tag: rgba(255, 255, 255, 0.03);
  --fl-hover-tag-wochenende: rgba(255, 255, 255, 0.1);
  --fl-fehler-leise: rgba(184, 85, 79, 0.15);
  --fl-fehler-schraffur: rgba(184, 85, 79, 0.18);
  --linie: var(--farbe-linie);
  --linie-schwach: rgba(255, 255, 255, 0.08);
  --schraffur-hell: rgba(255, 255, 255, 0.14);

  --text: var(--farbe-text);
  --text-leise: var(--farbe-text-leise);
  --text-still: var(--farbe-text-still);
  --text-invers: var(--farbe-grau-300);
  --text-invers-stark: var(--farbe-weiss);
  --text-akzent: var(--farbe-akzent-hell);

  --akzent: var(--farbe-akzent);
  --akzent-mittel: var(--farbe-akzent-mittel);
  --akzent-hell: var(--farbe-akzent-hell);
  --akzent-heller: var(--farbe-akzent-heller);
  --erfolg: var(--farbe-erfolg);
  --warnung: var(--farbe-warnung);
  --fehler: var(--farbe-fehler);
  --fehler-hell: var(--farbe-fehler-hell);

  /* Balken tragen ihre Farben als eigene Tokens, damit das helle Thema
   * sie ohne Neuformulierung der Klassen übernehmen kann. */
  --balken-bestaetigt-fl: #24432f;
  --balken-bestaetigt-rand: var(--farbe-erfolg);
  --balken-angefragt-fl: #4a3a19;
  --balken-angefragt-rand: var(--farbe-warnung);
  --balken-fremd-fl: var(--farbe-flaeche);
  --balken-fremd-rand: var(--farbe-grau-500);
  --balken-fremd-text: var(--farbe-text-leise);
  /* Nebentitel auf Balken: bewusst leiser als der Haupttitel, aber
   * kräftig genug, um auf --balken-bestaetigt-fl und --balken-angefragt-fl
   * (auch mit Schraffur) AA zu erreichen. */
  --balken-text-leise: #e0e0e0;

  --schrift-text: "Lato", "Helvetica Neue", Arial, sans-serif;
  --schrift-headline: "Bebas Neue", "Arial Narrow", Arial, sans-serif;
  --schrift-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --radius: 3px;
  --abstand-klein: 0.5rem;
  --abstand: 1rem;
  --abstand-gross: 2rem;
  --breite-inhalt: 72rem;
  --schatten-fokus: 0 0 0 3px rgba(119, 132, 170, 0.55);

  /* Boden fuer die Monat-Fit-Spalten (siehe `.timeline-huelle-fit`
   * unten): gemessen als die Spaltenbreite, ab der die zweistellige
   * Tagesnummer (`.timeline-datum`, 13px tabular-nums, im Fit-Modus
   * 0.05rem Innenabstand je Seite) gerade noch ohne Kuerzung passt.
   * 127.0.0.1:8813, Browser-Messung: "31" braucht 15.1px Inhaltsbreite,
   * plus 1.6px Innenabstand macht 16.7px; 1.125rem (18px) rundet mit
   * Sicherheitsabstand auf.
   *
   * Review Runde 11: diese Variable stand vorher auf `.timeline-huelle`
   * (== Monat-Kontext) statt auf `:root`. `.timeline-balken` (siehe dort)
   * liest denselben Wert für seine Mindestbreite, aber `timeline.js`
   * misst diese Mindestbreite über einen Sondenknoten, der nur
   * `.timeline-huelle-fit` selbst ist – nie ein Nachfahre von
   * `.timeline-huelle` – und bekam die Variable darum nie aufgelöst
   * (0px statt 18px, 18% zu kleine Mindestspanne, beide Ueberdeckungs-
   * Fehler aus Runde 9/10 kamen dadurch zurück). `:root` macht die
   * Variable von jedem Knoten aus lesbar, unabhängig davon, wo im Baum
   * er haengt – keine unsichtbare Kontextabhaengigkeit mehr zwischen
   * Sonde und echtem Balken. */
  --monat-mindestspalte: 1.125rem;

  /* Der Kopf ist in beiden Themen dunkel; seine Textfarben stehen deshalb
   * hier fest und werden im Hellen NICHT überschrieben. */
  --kopf-text: #eaeaea;
  --kopf-text-leise: #a5a5a5;
  --kopf-text-stark: #ffffff;
  color-scheme: dark;
}

/* --- Helles Thema: expliziter Wähler und Systemvorgabe -------------------- */

/* Explizite Wahl gewinnt vor dem System. */
:root[data-thema="hell"] {
  --fl-blatt: #f6f4ee;
  --fl-erhaben: #ffffff;
  --fl-kontrast: #1a1a1a;
  --fl-zebra: rgba(0, 0, 0, 0.03);
  --fl-hover: rgba(0, 0, 0, 0.05);
  --fl-wochenende: rgba(0, 0, 0, 0.05);
  --fl-wochenende-kalender: rgba(0, 0, 0, 0.03);
  --fl-hover-tag: rgba(0, 0, 0, 0.03);
  --fl-hover-tag-wochenende: rgba(0, 0, 0, 0.08);
  --fl-fehler-leise: rgba(160, 40, 34, 0.10);
  --fl-fehler-schraffur: rgba(160, 40, 34, 0.16);
  --linie: #d5cfc1;
  --linie-schwach: rgba(0, 0, 0, 0.08);
  --schraffur-hell: rgba(0, 0, 0, 0.18);

  --text: #1a1a1a;
  --text-leise: #4d4d4d;
  --text-still: #737373;
  --text-invers: #eaeaea;
  --text-invers-stark: #ffffff;
  --text-akzent: #3a4880;

  --akzent: #3a4880;
  --akzent-mittel: #4c5a94;
  --akzent-hell: #5a68a2;
  --akzent-heller: #2f3a6b;
  --erfolg: #2f6b3d;
  --warnung: #8a6414;
  --fehler: #a02822;
  --fehler-hell: #8a1f1a;

  --balken-bestaetigt-fl: #d8eadd;
  --balken-bestaetigt-rand: #2f6b3d;
  --balken-angefragt-fl: #f3e6c4;
  --balken-angefragt-rand: #8a6414;
  --balken-fremd-fl: #e8e2d5;
  --balken-fremd-rand: #8a8577;
  --balken-fremd-text: #4d4d4d;
  --balken-text-leise: #3a3a3a;

  --schatten-fokus: 0 0 0 3px rgba(58, 72, 128, 0.55);
  color-scheme: light;
}

/* Systemvorgabe – nur wenn keine explizite Wahl vorliegt. */
@media (prefers-color-scheme: light) {
  :root:not([data-thema]) {
    --fl-blatt: #f6f4ee;
    --fl-erhaben: #ffffff;
    --fl-kontrast: #1a1a1a;
    --fl-zebra: rgba(0, 0, 0, 0.03);
    --fl-hover: rgba(0, 0, 0, 0.05);
    --fl-wochenende: rgba(0, 0, 0, 0.05);
    --fl-wochenende-kalender: rgba(0, 0, 0, 0.03);
    --fl-hover-tag: rgba(0, 0, 0, 0.03);
    --fl-hover-tag-wochenende: rgba(0, 0, 0, 0.08);
    --fl-fehler-leise: rgba(160, 40, 34, 0.10);
    --fl-fehler-schraffur: rgba(160, 40, 34, 0.16);
    --linie: #d5cfc1;
    --linie-schwach: rgba(0, 0, 0, 0.08);
    --schraffur-hell: rgba(0, 0, 0, 0.18);

    --text: #1a1a1a;
    --text-leise: #4d4d4d;
    --text-still: #737373;
    --text-invers: #eaeaea;
    --text-invers-stark: #ffffff;
    --text-akzent: #3a4880;

    --akzent: #3a4880;
    --akzent-mittel: #4c5a94;
    --akzent-hell: #5a68a2;
    --akzent-heller: #2f3a6b;
    --erfolg: #2f6b3d;
    --warnung: #8a6414;
    --fehler: #a02822;
    --fehler-hell: #8a1f1a;

    --balken-bestaetigt-fl: #d8eadd;
    --balken-bestaetigt-rand: #2f6b3d;
    --balken-angefragt-fl: #f3e6c4;
    --balken-angefragt-rand: #8a6414;
    --balken-fremd-fl: #e8e2d5;
    --balken-fremd-rand: #8a8577;
    --balken-fremd-text: #4d4d4d;
    --balken-text-leise: #3a3a3a;

    --schatten-fokus: 0 0 0 3px rgba(58, 72, 128, 0.55);
    color-scheme: light;
  }
}

/* --- Grundgerüst ---------------------------------------------------------- */

* {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background-color: var(--fl-blatt);
  color: var(--text);
  font-family: var(--schrift-text);
  font-size: 1rem;
  line-height: 1.5;
}

h1,
h2,
h3 {
  font-family: var(--schrift-headline);
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.1;
  margin: 0 0 var(--abstand);
}

h1 {
  font-size: 2.75rem;
}

h2 {
  font-size: 2rem;
  margin-top: var(--abstand-gross);
}

h3 {
  font-size: 1.5rem;
  margin-top: var(--abstand);
}

p {
  margin: 0 0 var(--abstand);
}

a {
  color: var(--akzent-hell);
}

a:hover {
  color: var(--akzent-heller);
}

:focus-visible {
  outline: none;
  box-shadow: var(--schatten-fokus);
}

.einleitung {
  font-size: 1.125rem;
  margin: 0 0 1.5rem;
}

.hinweis {
  padding: var(--abstand) 1.25rem;
  background-color: var(--fl-erhaben);
  border-left: 4px solid var(--akzent-hell);
  color: var(--text-leise);
}

.leise {
  color: var(--text-leise);
}

/* --- Kopf und Navigation -------------------------------------------------- */

.kopf {
  background-color: var(--fl-kontrast);
  border-bottom: 1px solid var(--linie);
  color: var(--kopf-text);
}

.kopf-innen {
  width: min(var(--breite-inhalt), 100%);
  margin: 0 auto;
  padding: var(--abstand) 1.5rem;
  display: flex;
  align-items: center;
  gap: var(--abstand-gross);
}

.logo {
  display: block;
  flex: none;
}

.logo img {
  display: block;
  width: 17.5rem;
  max-width: 100%;
  height: auto;
}

.navigation {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: var(--abstand-klein) var(--abstand);
}

.navigation ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--abstand-klein) var(--abstand);
}

.navigation a {
  color: var(--kopf-text);
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.875rem;
  padding: 0.25rem 0;
  border-bottom: 2px solid transparent;
}

.navigation a:hover,
.navigation a[aria-current="page"] {
  border-bottom-color: var(--akzent-hell);
  color: var(--kopf-text-stark);
}

.navigation form {
  margin: 0;
}

.navigation .knopf {
  padding: 0.35rem 0.9rem;
  font-size: 0.8125rem;
}

/* Zaehler am Navigationseintrag (offene Anfragen, Positionen im Korb).
 * Runde Marke im dunklen Akzent, in beiden Themen mit weisser Zahl.
 * `--akzent-hell` erreicht im dunklen Thema (Weiss auf #7784aa) nur
 * 3.7:1 und faellt damit unter AA fuer kleinen Text; dieselbe Fluchtlinie
 * zieht der Themenschalter-Aktivwert schon auf `--akzent`, deshalb hier
 * auch (weiss auf #303857/#3a4880 = 11.32/8.64:1). `[hidden]` bleibt
 * verlaesslich unsichtbar, damit der Zaehler des Korbs auf Seiten ohne
 * Positionen nicht als leerer Kreis steht. */
.navigation .anzahl {
  display: inline-block;
  margin-left: 0.35rem;
  min-width: 1.4rem;
  padding: 0 0.4rem;
  border-radius: 999px;
  background-color: var(--akzent);
  color: var(--kopf-text-stark);
  font-size: 0.75rem;
  font-weight: 700;
  text-align: center;
  line-height: 1.4rem;
}

.navigation .anzahl[hidden] {
  display: none;
}

.nutzer {
  color: var(--kopf-text-leise);
  font-size: 0.875rem;
}

/* Sekundäre Knöpfe im Kopf (Abmelden) folgen dem hellen Kopftext, weil
 * der Kopf in beiden Themen dunkel bleibt. */
.kopf .knopf-sekundaer {
  color: var(--kopf-text);
  border-color: var(--kopf-text-leise);
}

.kopf .knopf-sekundaer:hover {
  color: var(--kopf-text-stark);
  border-color: var(--kopf-text-stark);
  background-color: rgba(255, 255, 255, 0.08);
}

.rolle {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0.1rem 0.5rem;
  border-radius: var(--radius);
  background-color: var(--akzent);
  color: var(--text-invers-stark);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}


/* --- Inhalt und Fuß ------------------------------------------------------- */

.inhalt {
  flex: 1;
  width: min(var(--breite-inhalt), 100%);
  margin: 0 auto;
  padding: 2.5rem 1.5rem;
}

.fuss {
  border-top: 1px solid var(--linie);
  color: var(--text-leise);
  font-size: 0.875rem;
}

.fuss-innen {
  width: min(var(--breite-inhalt), 100%);
  margin: 0 auto;
  padding: var(--abstand) 1.5rem;
}

.fuss p {
  margin: 0;
}

/* --- Meldungen (Django messages) ------------------------------------------ */

.meldungen {
  list-style: none;
  margin: 0 0 1.5rem;
  padding: 0;
}

.meldung {
  padding: 0.75rem 1.25rem;
  margin-bottom: var(--abstand-klein);
  background-color: var(--fl-erhaben);
  border-left: 4px solid var(--akzent-hell);
  border-radius: 0 var(--radius) var(--radius) 0;
}

.meldung-success {
  border-left-color: var(--erfolg);
}

.meldung-warning {
  border-left-color: var(--warnung);
}

.meldung-error {
  border-left-color: var(--fehler);
}

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

form {
  max-width: 32rem;
}

/* Django 5.2 rendert {{ form }} mit einem <div> je Feld; <p> für form.as_p. */
form > div,
form > p {
  margin: 0 0 var(--abstand);
}

fieldset {
  border: 1px solid var(--linie);
  border-radius: var(--radius);
  padding: var(--abstand) 1.25rem;
  margin: 0 0 1.5rem;
}

legend {
  font-family: var(--schrift-headline);
  font-size: 1.25rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0 0.5rem;
}

label {
  display: block;
  margin-bottom: 0.3rem;
  color: var(--text);
  font-weight: 700;
  font-size: 0.9375rem;
}

input,
select,
textarea {
  display: block;
  width: 100%;
  padding: 0.55rem 0.75rem;
  background-color: var(--fl-erhaben);
  color: var(--text);
  border: 1px solid var(--linie);
  border-radius: var(--radius);
  font: inherit;
  line-height: 1.4;
}

input::placeholder,
textarea::placeholder {
  color: var(--text-still);
}

input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--akzent-hell);
  box-shadow: var(--schatten-fokus);
}

input[type="checkbox"],
input[type="radio"] {
  display: inline-block;
  width: auto;
  margin: 0 0.5rem 0 0;
  vertical-align: middle;
  accent-color: var(--akzent-hell);
}

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

select {
  appearance: none;
  padding-right: 2.25rem;
  background-image: linear-gradient(45deg, transparent 50%, var(--text-leise) 50%),
    linear-gradient(135deg, var(--text-leise) 50%, transparent 50%);
  background-position: calc(100% - 1.1rem) 50%, calc(100% - 0.75rem) 50%;
  background-size: 0.35rem 0.35rem;
  background-repeat: no-repeat;
}

.helptext {
  display: block;
  margin-top: 0.3rem;
  color: var(--text-leise);
  font-size: 0.875rem;
}

/* Mehrfachauswahl (Freigaben): Django rendert je Option ein <div> mit Label
   und setzt die Klasse auch an jedes <input> – deshalb nur auf das <div>. */
div.auswahlliste {
  max-height: 16rem;
  overflow-y: auto;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--linie);
  border-radius: var(--radius);
  background-color: var(--fl-erhaben);
}

div.auswahlliste label {
  display: inline;
  margin: 0;
  font-weight: 400;
  color: var(--text);
}

.errorlist {
  list-style: none;
  margin: 0 0 0.5rem;
  padding: 0;
  color: var(--fehler-hell);
  font-size: 0.9375rem;
}

.errorlist li {
  padding: 0.35rem 0.75rem;
  margin-bottom: 0.25rem;
  background-color: var(--fl-fehler-leise);
  border-left: 3px solid var(--fehler);
}

.errorlist.nonfield {
  margin-bottom: var(--abstand);
}

input[aria-invalid="true"],
select[aria-invalid="true"],
textarea[aria-invalid="true"] {
  border-color: var(--fehler);
}

/* --- Buttons -------------------------------------------------------------- */

button,
.knopf {
  display: inline-block;
  padding: 0.6rem 1.4rem;
  background-color: var(--akzent);
  color: var(--text-invers-stark);
  border: 1px solid var(--akzent-mittel);
  border-radius: var(--radius);
  font-family: var(--schrift-text);
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  line-height: 1.3;
  cursor: pointer;
}

button:hover,
.knopf:hover {
  background-color: var(--akzent-mittel);
  border-color: var(--akzent-hell);
  color: var(--text-invers-stark);
}

button:disabled,
.knopf[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
}

.knopf-sekundaer {
  background-color: var(--fl-erhaben);
  border-color: var(--text-still);
  color: var(--text);
}

.knopf-sekundaer:hover {
  background-color: var(--linie);
  border-color: var(--text-invers);
  color: var(--text);
}

/* Gefahr-Rang: gefuellt wie primaer/sekundaer (Ticket #56), Hover dunkelt
 * nur den Hintergrund ab (nicht den Text) – ein Filter auf beide Kanaele
 * haette den weissen Text mitgedaemmt und im dunklen Thema den Kontrast
 * unter 4.5:1 gedrueckt (siehe docs/gestaltung/07-kontrastmessungen.md). */
.knopf-gefahr {
  background-color: var(--fehler);
  border-color: var(--fehler);
  color: var(--text-invers-stark);
}

.knopf-gefahr:hover {
  background-color: color-mix(in srgb, var(--fehler) 82%, black);
  border-color: color-mix(in srgb, var(--fehler) 82%, black);
  color: var(--text-invers-stark);
}

.aktionen {
  display: flex;
  flex-wrap: wrap;
  gap: var(--abstand-klein) var(--abstand);
  align-items: center;
  margin-top: 1.5rem;
}

/* Admin-Endaktion (endgueltiges Loeschen): eigene Zeile, deutlich
 * abgesetzt von den regulaeren Aktionen. Trennlinie oberhalb, damit
 * niemand den Loesch-Knopf auf einer Reihe mit „Stornieren" wahrnimmt
 * (Ticket #34 a2, Punkt 5). */
.aktionen-admin {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px dashed var(--linie);
}

/* --- Tabellen ------------------------------------------------------------- */

.tabelle-huelle {
  overflow-x: auto;
  margin: 0 0 1.5rem;
  border: 1px solid var(--linie);
  border-radius: var(--radius);
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
}

caption {
  text-align: left;
  padding: 0.5rem 0.75rem;
  color: var(--text-leise);
  caption-side: bottom;
}

th,
td {
  padding: 0.6rem 0.75rem;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--linie);
}

thead th {
  background-color: var(--fl-kontrast);
  color: var(--kopf-text);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

tbody tr:nth-child(even) {
  background-color: var(--fl-zebra);
}

tbody tr:hover {
  background-color: var(--fl-erhaben);
}

tbody tr:last-child td {
  border-bottom: none;
}

td.zahl,
th.zahl {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Vorher/Nachher-Vergleich des Aenderungsantrags (Ticket #65): Geaendertes,
 * Neues und Wegfallendes tragen zusaetzlich zum Fettdruck/Text im Inhalt
 * (siehe `buchung.html`) einen linken Rand, damit die Zeile auch beim
 * Ueberfliegen auffaellt – Farbe ist hier nie das einzige Merkmal. Der Rand
 * sitzt an der letzten Zelle (Kopf-Tabelle: Label, Bisher, Gewuenscht;
 * Positions-Tabelle: Bisher, Gewuenscht) – also am „Gewünscht“-Wert, dem
 * geaenderten, nicht am alten (Review rev=3 N4b).
 */
.vergleich-geaendert > :last-child {
  border-left: 3px solid var(--akzent-hell);
}

.vergleich-neu > :last-child {
  border-left: 3px solid var(--erfolg);
}

.vergleich-entfaellt > :last-child {
  border-left: 3px solid var(--fehler);
}

/* Mehrere Aktionen in einer Tabellenzeile stehen nebeneinander; Formulare
   sind Blockelemente und würden sonst umbrechen. */
.zeilen-aktionen {
  display: flex;
  flex-wrap: wrap;
  gap: var(--abstand-klein);
  align-items: center;
}

.zeilen-aktionen form {
  max-width: none;
}

/* --- Timeline ------------------------------------------------------------- */

/* Ein Raster aus Zeilen; jede Zeile ist ihrerseits ein Grid mit derselben
   Spaltenvorlage (Ressource, dann ein Tag je Spalte). Die Hülle scrollt in
   beide Richtungen; Zeitkopf und Ressourcenspalte bleiben darin stehen. */
.timeline-steuerung {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--abstand);
  margin-bottom: var(--abstand);
}

.timeline-navigation,
.timeline-ansichten {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--abstand-klein);
}

.timeline-titel {
  margin: 0 0 0 var(--abstand-klein);
  font-size: 1.75rem;
  min-width: 0;
}

.timeline-ansichten .knopf[aria-pressed="true"] {
  background-color: var(--akzent);
  border-color: var(--akzent-mittel);
  color: var(--text-invers-stark);
}

.timeline-huelle {
  --tage: 7;
  --tagbreite: 2.75rem;
  --ressourcenbreite: 12rem;
  overflow: auto;
  min-height: 12rem;
  margin: 0 0 var(--abstand);
  border: 1px solid var(--linie);
  border-radius: var(--radius);
  background-color: var(--fl-blatt);
}

/* Im Dashboard-Kontext füllt die Timeline-Hülle den Restplatz und scrollt
 * in sich; auf Mobil (dort ist .start-timeline block) greift die
 * Standardhöhe unten. */
.start-timeline .timeline-huelle {
  flex: 1;
  min-height: 0;
  margin-bottom: 0;
}

.timeline-huelle > .hinweis,
.timeline-huelle > .meldung {
  margin: var(--abstand);
}

.timeline-raster {
  min-width: max-content;
  font-size: 0.875rem;
}

.timeline-zeile {
  display: grid;
  grid-template-columns: var(--ressourcenbreite) repeat(var(--tage), minmax(var(--tagbreite), 1fr));
  min-width: 100%;
  border-bottom: 1px solid var(--linie);
}

/* Monat-Ansicht (Owner-Entscheidung nach der Monatsgrenze, Issue-Fund):
 * anders als Woche/Tag soll ein Monatsraster mit 28-31 Spalten in seine
 * Huelle passen, ohne dabei unbegrenzt zu schrumpfen. Review Runde 9 wies
 * nach, dass `minmax(0, 1fr)` (vorige Fassung) keinen Boden hatte: die
 * Spalten wurden beliebig schmal, und ab rund 1050px Huellenbreite
 * (16px Spaltenbreite) wurde die zweistellige Tagesnummer wieder
 * unlesbar – exakt der Fehler, den die Monat-Anpassung beheben sollte.
 * `minmax(var(--monat-mindestspalte), 1fr)` gibt CSS-Grid einen echten
 * Boden: oberhalb der Grenze verteilt `1fr` den Platz gleichmaessig ohne
 * Ueberlauf; sobald die Huelle schmaler wuerde als
 * `Ressourcenspalte + Tage * Mindestspalte`, verhindert dieselbe Summe
 * als `min-width` auf `.timeline-raster`/`.timeline-zeile`, dass die
 * Spalten weiter schrumpfen – die Huelle scrollt stattdessen horizontal,
 * mit lesbaren Spalten am Boden (dieselbe Scroll-Mechanik wie Woche/Tag,
 * nur mit kleinerem Boden). Woche und Tag behalten ihre feste
 * Spaltenbreite unveraendert (kein `.timeline-huelle-fit` dort, siehe
 * timeline.js). Die Balken-Mindestbreite (`.timeline-balken`) ist auf
 * dieselbe Fit-Klasse beschraenkt (siehe dort); ihr Ueberlappungsschutz
 * steckt in `spurenVerteilen()` (timeline.js). */
.timeline-huelle-fit .timeline-raster {
  min-width: calc(var(--ressourcenbreite) + var(--tage) * var(--monat-mindestspalte));
}

.timeline-huelle-fit .timeline-zeile {
  grid-template-columns: var(--ressourcenbreite) repeat(var(--tage), minmax(var(--monat-mindestspalte), 1fr));
  min-width: calc(var(--ressourcenbreite) + var(--tage) * var(--monat-mindestspalte));
}

.timeline-zeile > * {
  grid-row: 1;
}

.timeline-zeile[hidden] {
  display: none;
}

.timeline-ressource {
  grid-column: 1;
  position: sticky;
  left: 0;
  z-index: 2;
  padding: 0.4rem 0.75rem;
  /* Gleiche Zeilenhöhe für Ressourcen mit und ohne Foto: die feste
   * line-height diktiert die Höhe, das Foto sitzt inline darüber. */
  line-height: 1.5rem;
  background-color: var(--fl-blatt);
  border-right: 1px solid var(--linie);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.timeline-ressource-foto {
  display: inline-block;
  width: 1.5rem;
  height: 1.5rem;
  margin-right: 0.4rem;
  vertical-align: middle;
  object-fit: cover;
  border-radius: var(--radius);
  background-color: var(--fl-erhaben);
  /* Dünner Rand grenzt das Bildchen auf hellem wie dunklem Grund ab. */
  border: 1px solid var(--linie);
}

.timeline-ressource-name {
  vertical-align: middle;
}

.timeline-bestand {
  display: block;
  color: var(--text-still);
  font-size: 0.75rem;
}

.timeline-kopf {
  position: sticky;
  top: 0;
  z-index: 3;
  background-color: var(--fl-kontrast);
}

.timeline-kopf .timeline-ressource {
  background-color: var(--fl-kontrast);
  color: var(--kopf-text);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.timeline-ecke {
  z-index: 4;
}

.timeline-tag {
  border-right: 1px solid var(--linie);
  min-width: 0;
}

/* Tag-Ansicht: die Stundenzellen dürfen etwas markanter enden, damit die
 * 15-Minuten-Positionen der Balken zuzuordnen sind. */
.timeline-stunde {
  border-right-color: var(--linie-schwach);
}

.timeline-stunde:nth-child(3n + 2) {
  border-right-color: var(--linie);
}

/* Klick in freie Fläche einer buchbaren Zeile führt in den Buchen-Ablauf;
 * das signalisiert der Zeiger, ohne dass die Balken (Links) ihn verlieren. */
.timeline-buchbar .timeline-tag {
  cursor: pointer;
}

.timeline-tagkopf {
  padding: 0.4rem 0.25rem;
  text-align: center;
  color: var(--kopf-text);
  line-height: 1.2;
  /* Woche/Tag: "TT.MM." kann bei sehr schmalen Spalten trotzdem knapp
   * werden; dieselbe Kürzung wie am Balkentitel
   * (`.timeline-balken-titel`) statt Umbruch oder Überlauf in die
   * Nachbarspalte. Im Monat-Fit-Modus rendert hier nur noch die
   * Tagesnummer (das Wochentagskürzel ist visuell verborgen, siehe
   * `.nur-screenreader`), die Regel bleibt trotzdem als generischer
   * Schutz stehen. */
  overflow: hidden;
}

/* Bei 28-31 Spalten (siehe `.timeline-huelle-fit`/`--monat-mindestspalte`
 * oben) bleiben pro Spalte am Boden rund 18px – die 0.25rem (4px)
 * Innenabstand links/rechts oben ließen selbst der bloßen Tagesnummer
 * (max. "31", zweistellig) keinen Platz mehr (Owner-Fund: Ellipsis
 * zerschnitt "10"-"31" bis zur Unkenntlichkeit, z.B. "10".."19" alle zu
 * "1."). Reduzierter Abstand nur im Fit-Modus schafft genug Raum für die
 * Zahl und haelt damit den Boden (`--monat-mindestspalte`) klein. */
.timeline-huelle-fit .timeline-tagkopf {
  padding-left: 0.05rem;
  padding-right: 0.05rem;
}

.timeline-wochentag {
  display: block;
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Review Runde 9: "MO"/"DO" bei 11px passten selbst mit knappem
 * Innenabstand erst ab rund 22px Spaltenbreite verlustfrei (gemessen,
 * 127.0.0.1:8813) – mehr als die Tagesnummer allein braucht (siehe
 * `--monat-mindestspalte`, 18px). Eine eigene Mini-Schriftgröße (9px,
 * vorige Fassung) blieb trotzdem unterhalb von rund 1100px Huellenbreite
 * hinter dem Boden zurück und war selbst geschrumpft die kleinste
 * Schrift im ganzen Stylesheet. Owner-Entscheidung: im Monat ist die
 * Tagesnummer die Information, das Wochenende ist schon über die
 * Hintergrundfarbe (`.timeline-wochenende`) erkennbar – das Kürzel
 * bleibt darum im Monat nur visuell verborgen (`nur-screenreader`,
 * timeline.js `kopfzeileTage()`), statt eine dritte Mikro-Schriftgröße
 * einzuführen. Woche/Tag zeigen es unveraendert bei 11px.
 *
 * Review Runde 10: die vorige Fassung blendete das Kürzel per
 * `display: none` aus – das entfernt einen Knoten auch aus dem
 * Accessibility-Baum, eine Screenreader-Spalte hätte darum nur noch
 * die blosse Zahl vorgelesen ("17") und das Wochenende wäre allein über
 * Hintergrund-/Textfarbe erkennbar gewesen (WCAG 1.4.1, farbe-only).
 * `.nur-screenreader` ist die allgemeine Klippen-Technik dafür: der
 * Text bleibt im DOM und im Accessibility-Baum, ist aber auf 1x1px ohne
 * sichtbaren Rand reduziert – eine wiederverwendbare Hilfsklasse statt
 * des Tricks nur an dieser einen Stelle. */
.nur-screenreader {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.timeline-datum {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
}

.timeline-wochenende {
  background-color: var(--fl-wochenende);
}

.timeline-kopf .timeline-wochenende {
  /* Fester Blauton, weil die Kopfzeile in beiden Themen dunkel bleibt. */
  color: #a4b0d0;
}

.timeline-heute {
  box-shadow: inset 2px 0 0 var(--akzent-hell);
}

.timeline-kopf .timeline-heute {
  color: var(--kopf-text-stark);
}

/* Kategoriezeilen setzen sich klar von Ressourcenzeilen ab: dieselbe
 * erhabene Fläche, aber der Klapper-Knopf drin ist ein spürbares
 * Bedienelement (siehe unten). */
.timeline-kategorie {
  background-color: var(--fl-erhaben);
  border-top: 1px solid var(--linie);
}

.timeline-kategoriename,
.timeline-kategorie .timeline-ressource {
  background-color: var(--fl-erhaben);
  padding: 0;
}

.timeline-kategorieflaeche {
  min-height: 2.25rem;
}

/* Klapper als eigenständiges Bedienelement: großzügige Trefferfläche,
 * eigener Flächenton, Chevron dreht sich zwischen den Zuständen. Die
 * Fläche macht ihn auf einen Blick als Schalter erkennbar, auch ohne
 * begleitenden Erklärtext. */
.timeline-klapper {
  width: 100%;
  padding: 0.55rem 0.75rem;
  text-align: left;
  background: none;
  border: 1px solid transparent;
  color: var(--text);
  font-family: var(--schrift-headline);
  font-size: 1.125rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
}

.timeline-klapper::before {
  content: "▾";
  display: inline-block;
  width: 1.1em;
  color: var(--akzent-hell);
  font-size: 1.15em;
  line-height: 1;
  transform-origin: center;
  transition: transform 0.15s ease-out, color 0.15s ease-out;
}

.timeline-klapper[aria-expanded="false"]::before {
  transform: rotate(-90deg);
}

.timeline-klapper:hover,
.timeline-klapper:focus-visible {
  background-color: var(--fl-hover);
  color: var(--text);
}

.timeline-klapper:hover::before,
.timeline-klapper:focus-visible::before {
  color: var(--akzent-heller);
}

.timeline-klapper-anzahl {
  margin-left: 0.4rem;
  color: var(--text-leise);
  font-family: var(--schrift-text);
  font-size: 0.875rem;
  letter-spacing: 0;
  text-transform: none;
}

.timeline-ressourcenzeile {
  --spuren: 1;
  min-height: calc(var(--spuren) * 1.5rem + 0.4rem);
}

.timeline-ressourcenzeile:hover .timeline-tag {
  background-color: var(--fl-hover-tag);
}

.timeline-ressourcenzeile:hover .timeline-wochenende {
  background-color: var(--fl-hover-tag-wochenende);
}

.timeline-inaktiv .timeline-ressource {
  color: var(--text-still);
}

.timeline-flaeche {
  grid-column: 2 / -1;
  position: relative;
  min-height: calc(var(--spuren) * 1.5rem + 0.4rem);
  pointer-events: none;
}

.timeline-balken {
  position: absolute;
  box-sizing: border-box;
  height: 1.3rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0 0.4rem;
  overflow: hidden;
  border-radius: var(--radius);
  background-color: var(--akzent);
  border: 1px solid var(--akzent-mittel);
  color: var(--text);
  font-size: 0.75rem;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  pointer-events: auto;
}

/* Ein Restanteil von wenigen Stunden in einem langen Monat-Fenster (28-31
 * Tage) wäre als reiner Prozentanteil eine Haarlinie von 1-2px – nicht
 * mehr anklickbar und praktisch unsichtbar. Diese Mindestbreite hält ihn
 * lesbar; timeline.js entscheidet je Balken die Verankerungsseite
 * (`sichtbarerBereich()`), damit die zusätzliche Breite ins Fenster
 * hinein wächst statt darüber hinaus.
 *
 * Review Runde 9: unskaliert traf die Regel auch Woche/Tag, wo ein
 * Prozentanteil ohnehin genug Pixel hat – dort blies sie kurze Buchungen
 * (z.B. eine 15-Minuten-Reservierung im Tag-Raster) sichtbar auf
 * (gemessen: 12px -> 25.6px). Die Regel gilt darum nur noch in
 * `.timeline-huelle-fit` (== Monat, siehe timeline.js); Woche/Tag bleiben
 * bei ihrer wahren Prozentbreite.
 *
 * Review Runde 10, Owner-Entscheidung: 1.6rem (25.6px) war breiter als
 * eine Spalte selbst am Boden (18px) – eine wiederkehrende 2-Stunden-
 * Buchung pro Tag hätte `spurenVerteilen()` dadurch in eine eigene Spur
 * pro Tag gezwungen (Zeilenhöhe verdoppelt), und eine echte 4-Stunden-
 * Buchung wäre 7.5x ihrer wahren Dauer gezeichnet worden – die Timeline
 * hätte über die Dauer gelogen. Der Wert ist darum an denselben Boden
 * gekoppelt, der schon die Spaltenbreite begrenzt (`--monat-mindestspalte`,
 * `.timeline-huelle` oben) – eine einzige Zahl statt zweier, die
 * auseinanderlaufen können. Der verbleibende Ueberdeckungsfall (zwei
 * kurze, direkt aufeinanderfolgende oder unmittelbar anschliessende
 * Buchungen) steckt nicht im CSS, sondern in `spurenVerteilen()`: die
 * Funktion bekommt die tatsächlich gemessene Mindestbreite als
 * Tagesanteil (`balkenMindestbreitePx()`) und reserviert danach jeder
 * Spur mindestens diese sichtbare Spanne, bevor die naechste Buchung
 * dieselbe Spur wiederverwenden darf. */
.timeline-huelle-fit .timeline-balken {
  min-width: var(--monat-mindestspalte);
}

a.timeline-balken:hover {
  filter: brightness(1.3);
  color: var(--text-invers-stark);
}

.timeline-balken-titel {
  overflow: hidden;
  text-overflow: ellipsis;
  font-weight: 700;
}

.timeline-balken-zusatz {
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--balken-text-leise);
}

/* Kodierung nach Status und Bucher (belegung.js): dieselben Klassen tragen
 * die Balken der Timeline, die Felder der Legende und die Termine im
 * Kalender des Buchen-Ablaufs. Jeder Status ist auch ohne Farbe zu
 * unterscheiden: bestätigt voll, angefragt schraffiert mit gestricheltem
 * Rand, fremde Belegung flach und mager, eigene mit Stern und Kante. */
.timeline-balken.belegung-bestaetigt,
.timeline-legende-balken.belegung-bestaetigt {
  background-color: var(--balken-bestaetigt-fl);
  border-color: var(--erfolg);
}

.timeline-balken.belegung-angefragt,
.timeline-legende-balken.belegung-angefragt {
  background-color: var(--balken-angefragt-fl);
  border-color: var(--warnung);
  border-style: dashed;
  background-image: repeating-linear-gradient(
    135deg,
    transparent 0 5px,
    var(--schraffur-hell) 5px 10px
  );
}

.timeline-balken.belegung-fremd,
.timeline-legende-balken.belegung-fremd {
  background-color: var(--balken-fremd-fl);
  border-color: var(--balken-fremd-rand);
  color: var(--balken-fremd-text);
}

.timeline-balken.belegung-fremd .timeline-balken-titel {
  font-weight: 400;
}

.timeline-balken.belegung-eigene,
.timeline-legende-balken.belegung-eigene {
  border-left: 4px solid var(--akzent-heller);
  box-shadow: 0 0 0 1px var(--akzent-heller);
}

.timeline-balken.belegung-eigene .timeline-balken-titel::before,
.timeline-legende-balken.belegung-eigene::before,
.kalender-belegung.belegung-eigene::before,
.kalender-termin.belegung-eigene .kalender-termin-titel::before {
  content: "★ ";
  color: var(--akzent-heller);
}

.timeline-legende-balken.belegung-eigene::before {
  content: "★";
  display: block;
  font-size: 0.6rem;
  line-height: 0.8rem;
  text-align: center;
}

.timeline-balken-vorher {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  border-left-style: dotted;
}

.timeline-balken-nachher {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  border-right-style: dotted;
}

/* Bei Mindestbreite (siehe .timeline-balken) ist die gepunktete Kante
 * allein kaum zu sehen; ein Pfeil an der offenen Seite macht „geht hier
 * weiter“ unabhängig von der Balkenbreite eindeutig – dieselben Zeichen
 * wie an der Zeitraum-Navigation (`_timeline.html`). `flex: none` hält den
 * Pfeil sichtbar, auch wenn der Titel daneben wegen Platzmangel schrumpft. */
.timeline-balken-vorher::before {
  content: "‹";
  flex: none;
  font-weight: 700;
}

.timeline-balken-nachher::after {
  content: "›";
  flex: none;
  font-weight: 700;
}

.timeline-leer {
  grid-column: 1 / -1;
  margin: var(--abstand);
}

/* Die Legende steht in der Steuerung über dem Raster: eine eigene, rechts
 * ausgerichtete Zeile unter Navigation und Ansicht-Knöpfen, damit sie auch
 * bei vielen Ressourcen ohne Scrollen zu sehen ist. */
.timeline-legende {
  flex-basis: 100%;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: 0.3rem 1rem;
  margin: calc(-1 * var(--abstand) + 0.5rem) 0 0;
  font-size: 0.8125rem;
}

.timeline-legende-eintrag {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  white-space: nowrap;
}
.timeline-legende-balken {
  display: inline-block;
  box-sizing: border-box;
  width: 1.6rem;
  height: 0.9rem;
  border-radius: var(--radius);
  background-color: var(--akzent);
  border: 1px solid var(--akzent-mittel);
}

.timeline-legende-balken.belegung-angefragt {
  background-image: repeating-linear-gradient(
    135deg,
    transparent 0 3px,
    var(--schraffur-hell) 3px 6px
  );
}

/* --- Buchen: Startseite, Karten, Korb, Kalender --------------------------- */

/* Startseite als Dashboard: zwei feste Bereiche im Sichtfenster, kein
 * Seitenscrollen. Karten- und Timelinebereich scrollen in sich. Auf
 * schmalem Bildschirm (siehe Mobil-Regeln am Ende) fällt das auf den
 * normalen Fluss zurück; dort scrollt wieder die Seite selbst. */
body.startseite {
  height: 100vh;
  min-height: 0;
  overflow: hidden;
}

body.startseite .inhalt {
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding-top: 1.25rem;
  padding-bottom: 1.25rem;
}

/* Owner-Vorgabe (Runde 4): auf sehr breiten Bildschirmen bleibt bei
 * `--breite-inhalt` (72rem) viel Platz links/rechts ungenutzt – spürbar in
 * der Monatsansicht der Timeline. Nur die Startseite (Dashboard mit
 * Timeline) wird breiter; `--breite-inhalt` selbst bleibt unverändert, damit
 * Formulare/Textseiten nicht unangenehm breit werden. Unter der Grenze und
 * auf Mobil/Tablet bleibt es beim normalen `.inhalt`. */
@media (min-width: 90rem) {
  body.startseite .inhalt {
    width: min(96rem, 96%);
  }
}

.start-raster {
  display: grid;
  grid-template-columns: 17rem minmax(0, 1fr);
  gap: var(--abstand-gross);
  align-items: stretch;
  min-height: 0;
  flex: 1;
}

.start-karten {
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--abstand-gross);
}

/* Die Buchen-Karte behaelt die bisherige Innenaufteilung des linken
 * Bereichs: Kopf fest, Inhalt scrollt in sich. Sie waechst in den
 * verbleibenden Platz, waehrend die Vorgaenge-Karte darueber ihre
 * eigene Hoehe behaelt (Ticket #63). */
.start-buchen-karte {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--abstand-klein);
}

/* Offene Vorgaenge (Ticket #63): dieselbe Flaechen-/Randsprache wie
 * `.karte`, aber ohne deren Grid-Fixierung (`height: 100%`), die hier
 * nichts zu stretchen hat. Feste Groesse, eigener Scroll erst ab vielen
 * Eintraegen, damit ein voller Vorrat die Buchen-Karte nicht verdraengt. */
.start-vorgaenge-karte {
  flex: none;
  max-height: 45%;
  overflow-y: auto;
  padding: var(--abstand) 1.25rem;
  background-color: var(--fl-erhaben);
  border: 1px solid var(--linie);
  border-left: 4px solid var(--akzent);
  border-radius: var(--radius);
  color: var(--text);
}

.start-vorgaenge-karte h2 {
  margin: 0 0 0.5rem;
}

.start-vorgaenge-liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.start-vorgaenge-liste li {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.start-timeline {
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* Der Kartenbereich scrollt in sich, wenn die Kategorien höher werden als
 * das Sichtfenster. Der iCal-Abo-Fuß bleibt darunter fest sichtbar. */
.start-karten-inhalt {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding-right: var(--abstand-klein);
}

/* Meine Buchung: Formular links, Kategorie-Karten rechts.
 *
 * Ticket #52, Korrekturrunde 3: bis hierher war die Seite wie das
 * Dashboard fixiert (100vh, `overflow: hidden`) und Positionsliste samt
 * Karten scrollten in einer eigenen Box in sich. Solange dort nur wenige
 * Zeilen standen, fiel das nicht auf – seit die Karten "Weitere Position
 * hinzufügen" ebenfalls in dieser Spalte stehen, ist der Inhalt oft länger
 * als die Box, und `autofocus` auf dem Titelfeld (`buchungen/forms.py`)
 * scrollte genau diese innere Box beim Laden weit genug herunter, dass
 * Positionsliste und die neuen Karten unsichtbar waren – exakt das, was
 * #52 zeigen sollte. Die Seite scrollt jetzt als Ganzes wie jede andere
 * Seite auch; nichts beginnt vorgescrollt. */

/* Hinweis auf eine laufende Aenderung, deren Korb noch im sessionStorage
 * liegt (Ticket #40): Text und die beiden Aktionen nebeneinander, solange
 * Platz ist, sonst untereinander. */
.aenderung-hinweis {
  margin: 0 0 1.25rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--abstand);
}

.aenderung-hinweis p {
  margin: 0;
  flex: 1 1 16rem;
}

.aenderung-hinweis-aktionen {
  display: flex;
  flex-wrap: wrap;
  gap: var(--abstand-klein);
}

.aenderung-hinweis[hidden] {
  display: none;
}

.meine-buchung-raster {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 17rem;
  gap: var(--abstand-gross);
  align-items: start;
}

.meine-buchung-formular {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--abstand-klein);
}

.meine-buchung-formular form {
  max-width: none;
}

.meine-buchung-formular[hidden] {
  display: none;
}

/* Titelzeile der Angaben: Ueberschrift links, Aktionen rechts. Sie bleibt
 * beim Scrollen der Formularspalte oben stehen, damit Abschicken und
 * Verwerfen auch bei langem Korb erreichbar sind, ohne zu scrollen. */
.angaben-kopf {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--abstand-klein);
  padding: var(--abstand-klein) 0;
  background-color: var(--fl-blatt);
  border-bottom: 1px solid var(--linie-schwach);
}

.angaben-kopf h2 {
  margin: 0;
}

.angaben-kopf .aktionen {
  margin: 0;
}


/* Kartenspalte rechts: oben die Liste der bestehenden Buchungen des
 * Nutzers (Ticket #34), darunter die Kategorie-Karten.
 *
 * Ticket #52, Korrekturrunde 3: die Spalte scrollte vorher in sich, weil
 * das Grid sie auf die Höhe der (damals kürzeren) Formularspalte
 * gestreckt hat. Jetzt, wo die Seite als Ganzes scrollt, gibt es diese
 * Höhe nicht mehr – `position: sticky` hält die Spalte stattdessen im
 * sichtbaren Bereich, solange die Formularspalte länger ist; die Höhe
 * kommt jetzt vom Sichtfenster (`calc(100vh - …)`), nicht mehr vom
 * Grid-Stretch. Die Aufteilung darunter (Liste gedeckelt auf 60 %,
 * Kategorien füllen den Rest, beide scrollen bei Bedarf in sich) bleibt
 * unverändert (Ticket #34 a2, Punkt 7). */
.meine-buchung-seite {
  position: sticky;
  top: 1.5rem;
  align-self: start;
  height: calc(100vh - 3rem);
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--abstand);
}

.meine-buchung-liste {
  min-height: 0;
  max-height: 60%;
  display: flex;
  flex-direction: column;
  gap: var(--abstand-klein);
  flex: 0 1 auto;
}

.meine-buchung-karten {
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--abstand-klein);
  flex: 1 1 auto;
}

.meine-buchung-liste > h2,
.meine-buchung-karten > h2 {
  margin: 0;
  flex: none;
}

.meine-buchung-liste-inhalt,
.meine-buchung-karten-inhalt {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding-right: var(--abstand-klein);
}

.meine-buchung-karten[hidden] {
  display: none;
}

/* Ticket #52: die Kategorie-Karten im laufenden Vorgang stehen in der
 * Mittelspalte (`.meine-buchung-formular`), die schon selbst in sich
 * scrollt – anders als in der rechten Spalte sollen die Karten dort nicht
 * noch einmal eine feste Resthoehe fuellen oder eigenstaendig scrollen,
 * sondern normal mit der Positionsliste und den Angaben mitfliessen. */
.meine-buchung-karten-vorgang {
  flex: none;
}

.meine-buchung-karten-vorgang .meine-buchung-karten-inhalt {
  flex: none;
  overflow-y: visible;
  padding-right: 0;
}

/* Ueberschrift ueber der Positionsliste (Ticket #55): sie steht nur,
 * solange ein Vorgang laeuft (die ganze `.meine-buchung-formular`-Spalte
 * ist dann sichtbar), kein eigenes Sichtbarkeits-Handling noetig. */
.korb-positionen-titel {
  margin: 0;
}

/* Bestehende Buchungen: kompakte Liste, Titel oben, Zeitraum darunter,
 * Status leise am Fuss. Die Kanten schwaechen sich bei vergangenen
 * Buchungen, ein Storno-Vermerk hebt sich mit Warnfarbe ab. */
.eigene-buchungen {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--abstand-klein);
}

.eigene-buchung {
  border: 1px solid var(--linie);
  border-left: 3px solid var(--akzent-hell);
  border-radius: var(--radius);
  background: var(--fl-erhaben);
}

.eigene-buchung-storno {
  border-left-color: var(--warnung);
}

.eigene-buchung-storniert,
.eigene-buchung-abgelehnt {
  border-left-color: var(--fehler);
}

.eigene-buchung-vergangen {
  opacity: 0.78;
}

.eigene-buchung-link {
  display: block;
  padding: 0.5rem 0.75rem;
  color: var(--text);
  text-decoration: none;
}

.eigene-buchung-link:hover,
.eigene-buchung-link:focus-visible {
  color: var(--text);
  background: var(--fl-hover);
}

.eigene-buchung-titel {
  display: block;
  font-weight: 700;
}

.eigene-buchung-zeitraum {
  display: block;
  font-size: 0.875rem;
  color: var(--text-leise);
}

.eigene-buchung-status {
  display: block;
  font-size: 0.8125rem;
  color: var(--text-leise);
}

.nur-lesegeraet {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}


.pfad {
  color: var(--text-leise);
  font-size: 0.9375rem;
  margin-bottom: var(--abstand-klein);
}

.karten {
  list-style: none;
  margin: 0 0 var(--abstand);
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
  gap: var(--abstand);
}

.karten-schmal {
  grid-template-columns: 1fr;
}

/* Eine Karte ist ein <li>: der Inhalt als Link (.karte-link), darunter für
   den Admin die Aktionen – ein Formular im <a> wäre kein gültiges HTML. */
.karte {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: var(--abstand) 1.25rem;
  background-color: var(--fl-erhaben);
  border: 1px solid var(--linie);
  border-left: 4px solid var(--akzent);
  border-radius: var(--radius);
  color: var(--text);
}

.karte:hover,
.karte:focus-within {
  border-color: var(--akzent-hell);
}

.karte-inaktiv {
  border-left-color: var(--linie);
}

.karte-link {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  gap: 0.35rem;
  color: inherit;
  text-decoration: none;
}

a.karte-link:hover,
a.karte-link:focus-visible {
  color: var(--text-invers-stark);
}

/* Bis zu drei Aktionen in einer Zeile; kompakt gefuellte Knoepfe statt der
   frueheren schlichten Textknoepfe (Ticket #56) – Umbruch erlaubt, weil
   gefuellte Knoepfe bei schmalen Karten sonst ueberlaufen wuerden. */
.karte-aktionen {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--linie);
}

.karte-aktionen form {
  max-width: none;
}

.karte-aktionen .knopf {
  padding: 0.35rem 0.9rem;
  font-size: 0.8125rem;
}

.karte-titel {
  font-family: var(--schrift-headline);
  font-size: 1.5rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.1;
}

.karte-text,
.karte-liste {
  color: var(--text-leise);
  font-size: 0.9375rem;
}

/* Feste Höhe, beschnitten statt gestaucht: alle Karten einer Reihe zeigen
   das Foto gleich groß, unabhängig vom Seitenverhältnis. */
.karte-bild {
  flex: none;
  width: 100%;
  height: 10rem;
  border-radius: var(--radius);
  margin-bottom: 0.25rem;
  object-fit: cover;
}

.karte-fakten {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  margin-top: auto;
  padding-top: 0.5rem;
  font-size: 0.875rem;
  color: var(--text-leise);
}

.korb-leiste {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--abstand-klein) var(--abstand);
  margin-bottom: 1.5rem;
  padding: 0.75rem var(--abstand);
  background-color: var(--akzent);
  color: var(--text-invers-stark);
  border-radius: var(--radius);
}

.korb-leiste[hidden] {
  display: none;
}

.korb-leiste-text {
  flex: 1 1 auto;
  font-weight: 700;
}

.korb-leiste .knopf {
  background-color: var(--fl-blatt);
  border-color: var(--akzent-hell);
  color: var(--text);
}

.korb-leiste .knopf:hover,
.korb-leiste .knopf:focus-visible {
  color: var(--text-invers-stark);
}

.korb-positionen {
  list-style: none;
  margin: 0 0 var(--abstand);
  padding: 0;
  display: grid;
  gap: var(--abstand-klein);
}

.korb-position {
  padding: var(--abstand) 1.25rem;
  background-color: var(--fl-erhaben);
  border: 1px solid var(--linie);
  border-left: 4px solid var(--akzent);
  border-radius: var(--radius);
}

.korb-position p {
  margin: 0 0 0.25rem;
}

.korb-position-konflikt {
  border-left-color: var(--fehler);
}

.korb-position-kopf {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 0.75rem;
  margin-bottom: 0.35rem;
}

.korb-position-name {
  font-family: var(--schrift-headline);
  font-size: 1.375rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.korb-position-preis {
  color: var(--text-leise);
  font-size: 0.9375rem;
}

.korb-position-aktionen {
  display: flex;
  flex-wrap: wrap;
  gap: var(--abstand-klein);
  margin-top: 0.5rem;
}

.korb-position .errorlist {
  margin-top: 0.5rem;
}

.korb-summe {
  font-size: 1.125rem;
}

/* Positionsseite: Kalender links, Formular rechts. */
.position-raster {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(18rem, 24rem);
  gap: var(--abstand-gross);
  align-items: start;
}

.positionsformular {
  max-width: none;
}

.position-foto {
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  margin-bottom: var(--abstand);
}

.zeitraum-zeile {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--abstand);
}

.zeitraum-tag {
  margin: 0 0 0.35rem;
  font-family: var(--schrift-headline);
  font-size: 1.375rem;
  letter-spacing: 0.04em;
}

.kalender-kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--abstand);
  margin-bottom: var(--abstand-klein);
}

.kalender-titel {
  margin: 0;
  font-size: 1.5rem;
}

.kalender-raster {
  border: 1px solid var(--linie);
  border-radius: var(--radius);
  overflow: hidden;
}

.kalender-zeile {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
}

.kalender-wochentage {
  background-color: var(--fl-erhaben);
}

.kalender-wochentag {
  padding: 0.4rem 0.5rem;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-leise);
  text-align: center;
}

.kalender-zelle {
  border-top: 1px solid var(--linie);
  border-right: 1px solid var(--linie);
  min-width: 0;
}

.kalender-zelle:last-child {
  border-right: none;
}

.kalender-tag {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
  width: 100%;
  min-height: 4.25rem;
  padding: 0.4rem 0.5rem;
  background: none;
  border: none;
  border-radius: 0;
  color: var(--text);
  font-family: var(--schrift-text);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  text-align: left;
  cursor: pointer;
}

.kalender-tag:not(:disabled):hover {
  background-color: var(--fl-erhaben);
  border: none;
}

.kalender-tag:disabled {
  cursor: not-allowed;
}

.kalender-gesperrt .kalender-tagzahl {
  text-decoration: line-through;
}

.kalender-tagzahl {
  font-weight: 700;
}

.kalender-fremd {
  color: var(--text-still);
}

.kalender-wochenende {
  background-color: var(--fl-wochenende-kalender);
}

.kalender-heute .kalender-tagzahl {
  color: var(--akzent-heller);
  text-decoration: underline;
}

.kalender-belegung,
.kalender-bucher {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.75rem;
  line-height: 1.2;
  color: var(--fehler-hell);
}

.kalender-bucher {
  color: var(--text-leise);
}

.kalender-belegt {
  background-image: repeating-linear-gradient(
    135deg,
    var(--fl-fehler-schraffur) 0,
    var(--fl-fehler-schraffur) 4px,
    transparent 4px,
    transparent 10px
  );
}

.kalender-teilweise .kalender-belegung {
  color: var(--warnung);
}

/* Termine im Kalender tragen dieselbe Kodierung wie die Timeline-Balken,
 * als farbige Kante: bestätigt voll grün, angefragt gestrichelt gelb,
 * fremde Belegung grau und mager, eigene mit Stern (siehe oben). */
.kalender-belegung.belegung-bestaetigt,
.kalender-belegung.belegung-angefragt,
.kalender-belegung.belegung-fremd,
.kalender-termin.belegung-bestaetigt,
.kalender-termin.belegung-angefragt,
.kalender-termin.belegung-fremd {
  padding-left: 0.4rem;
  border-left: 3px solid var(--text-still);
  color: var(--text);
}

.kalender-belegung.belegung-bestaetigt,
.kalender-termin.belegung-bestaetigt {
  border-left-color: var(--erfolg);
}

.kalender-belegung.belegung-angefragt,
.kalender-termin.belegung-angefragt {
  border-left-style: dashed;
  border-left-color: var(--warnung);
}

.kalender-belegung.belegung-fremd,
.kalender-termin.belegung-fremd {
  color: var(--text-leise);
}

.kalender-termin.belegung-fremd .kalender-termin-titel {
  font-weight: 400;
}

.kalender-gewaehlt {
  background-color: var(--akzent);
  color: var(--text-invers-stark);
}

.kalender-gewaehlt:hover {
  background-color: var(--akzent-mittel);
}

.kalender-beginn {
  box-shadow: inset 3px 0 0 var(--akzent-heller);
}

.kalender-ende {
  box-shadow: inset -3px 0 0 var(--akzent-heller);
}

.kalender-beginn.kalender-ende {
  box-shadow: inset 3px 0 0 var(--akzent-heller), inset -3px 0 0 var(--akzent-heller);
}

.kalender-hinweis {
  margin-top: var(--abstand-klein);
  min-height: 1.5rem;
}

/* Die Termine des Monats unter dem Raster – dieselben Balken wie im Raster. */
.kalender-termine-titel {
  margin: var(--abstand-klein) 0 0.5rem;
  font-size: 1.125rem;
}

.kalender-terminliste {
  list-style: none;
  margin: 0;
  padding: 0;
}

.kalender-termin {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  padding: 0.4rem 0;
  border-top: 1px solid var(--linie);
}

.kalender-termin-zeit {
  font-variant-numeric: tabular-nums;
  color: var(--text-leise);
}

.kalender-termin-titel {
  font-weight: 700;
}

/* --- Kalender abonnieren (iCal, Fuß der Buchen-Seitenleiste) -------------- */

/* Kompakter Abo-Abschnitt als <details> am Fuß der Seitenleiste.
 * Vorgabe zu, ein Klick klappt Adresse und Erneuern-Knopf aus. Sitzt
 * bewusst dort, weil die Seitenleiste ohnehin Admin/Intern-Blickfeld
 * ist (der Feed wird nur ihnen ausgeliefert) und die Timeline dadurch
 * vertikal ungestört bleibt. */
.kalender-abo {
  flex: none;
  margin-top: var(--abstand-klein);
  padding: 0.25rem 0;
  border-top: 1px solid var(--linie);
  color: var(--text-leise);
}

.kalender-abo > summary {
  padding: 0.4rem 0.25rem;
  cursor: pointer;
  color: var(--text);
  font-family: var(--schrift-headline);
  font-size: 1rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  list-style: none;
}

.kalender-abo > summary::-webkit-details-marker {
  display: none;
}

.kalender-abo > summary::before {
  content: "▸ ";
  color: var(--akzent-hell);
  display: inline-block;
  transition: transform 0.15s ease-out;
}

.kalender-abo[open] > summary::before {
  content: "▾ ";
}

.kalender-abo > summary:hover,
.kalender-abo > summary:focus-visible {
  background-color: var(--fl-hover);
  border-radius: var(--radius);
}

.kalender-abo-hinweis {
  margin: 0.25rem 0 var(--abstand-klein);
  font-size: 0.875rem;
  color: var(--text-leise);
}

.kalender-abo-url {
  width: 100%;
  font-family: var(--schrift-mono);
  font-size: 0.8125rem;
  background-color: var(--fl-erhaben);
  color: var(--text);
}

.kalender-abo-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--abstand-klein);
  max-width: none;
  margin: 0;
}

/* --- Themenschalter (Automatisch / Hell / Dunkel) ------------------------- */

.themenschalter {
  display: inline-flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0;
  border: 1px solid var(--akzent-mittel);
  border-radius: var(--radius);
  overflow: hidden;
}

.themenschalter .knopf {
  padding: 0.3rem 0.7rem;
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  border-radius: 0;
  border: 0;
  border-right: 1px solid var(--akzent-mittel);
  background-color: transparent;
  color: var(--text);
}

.themenschalter .knopf:last-child {
  border-right: 0;
}

.themenschalter .knopf[aria-pressed="true"] {
  background-color: var(--akzent);
  color: var(--text-invers-stark);
}

.themenschalter .knopf:hover {
  background-color: var(--fl-hover);
  color: var(--text);
}

.themenschalter .knopf[aria-pressed="true"]:hover {
  background-color: var(--akzent-mittel);
  color: var(--text-invers-stark);
}

/* --- Einstellungen-Abschnitte --------------------------------------------- */

.einstellung {
  padding: 1rem 0;
  border-bottom: 1px solid var(--linie-schwach);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
}

.einstellung:last-of-type {
  border-bottom: 0;
}

.einstellung h2 {
  margin: 0;
  font-size: 1rem;
  letter-spacing: 0.04em;
}

/* --- Bewegungsempfinden --------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
    animation: none !important;
  }

  a.timeline-balken:hover {
    filter: none;
  }
}

/* --- Mobil: lesbar, nicht optimiert --------------------------------------- */

@media (max-width: 48rem) {
  .kopf-innen {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--abstand);
    padding: var(--abstand);
  }

  .logo img {
    width: 14rem;
  }

  .navigation {
    justify-content: flex-start;
    width: 100%;
  }

  .inhalt {
    padding: 1.5rem var(--abstand);
  }

  /* Schmal: normaler Fluss. Die Dashboard-Fixierung des Startseite wird
   * aufgehoben, die Seite scrollt wieder als Ganzes; Karten stehen oben,
   * Timeline darunter. Kalender-Ansicht: Raster über dem Formular.
   * `body.meine-buchung` scrollt seit Ticket #52/Korrekturrunde 3 auf
   * jeder Breite normal – hier bleibt nur noch die schmalere Randbreite
   * wie bei jeder anderen Seite. */
  body.startseite {
    overflow: visible;
  }

  body.startseite .inhalt {
    display: block;
    padding: 1.5rem var(--abstand);
  }

  .start-raster,
  .position-raster,
  .meine-buchung-raster {
    display: block;
  }

  .start-karten,
  .start-karten-inhalt,
  .start-buchen-karte,
  .start-vorgaenge-karte,
  .meine-buchung-seite,
  .meine-buchung-liste,
  .meine-buchung-liste-inhalt,
  .meine-buchung-karten,
  .meine-buchung-karten-inhalt {
    display: block;
    min-height: 0;
    max-height: none;
    overflow-y: visible;
    padding-right: 0;
  }

  .meine-buchung-seite {
    position: static;
    height: auto;
  }

  .start-timeline {
    display: block;
  }

  .kalender-tag {
    min-height: 3.25rem;
    padding: 0.3rem;
  }

  .fuss-innen {
    padding: var(--abstand);
  }

  h1 {
    font-size: 2.25rem;
  }

  h2 {
    font-size: 1.625rem;
  }

  form {
    max-width: none;
  }

  .aktionen .knopf,
  .aktionen button {
    width: 100%;
    text-align: center;
  }
}
