/* ======================================================================
   Puls — die gemeinsame Bauteilschicht (24.09.2026)

   Renés Auftrag: „Ich habe eine Website gefunden, die mir aus der Seele spricht — gerade
   was Einheitlichkeit und Genauigkeit bei Eingaben und Angaben angeht … Ich finde, dies
   sollte nun ein fester Bestandteil unseres Layouts sein im gesamten Puls.“ Dazu drei
   Artikel der UI-Components-Serie (Textfelder, Auswahlelemente, Knöpfe) und der
   Dashboard-Leitfaden von Formwandler Interactive.

   **Diese Datei ist die unterste Schicht und wird von allen Oberflächen geladen** —
   Admin-Tool (`puls.css`), die Module (`dienstplan.css`), myPuls (`mypuls.css`), die
   Bereichsansicht und die Stempeluhr. Darüber liegt nur noch, was eine Oberfläche
   wirklich eigen hat. Vorher gab es dieselbe Feldregel viermal mit vier verschiedenen
   Maßen; das ist genau die Uneinheitlichkeit, die René meint.

   **Was hier steht, ist eine Entscheidung, keine Vorliebe.** Jede Regel nennt ihren
   Grund — und wo ein Maß aus einer Norm kommt (WCAG 2.2, § 3.3 Eingabehilfen), steht die
   Norm dabei. Die Musterseite unter `/gestaltung` zeigt jedes Bauteil in jedem Zustand;
   wer etwas ändert, ändert es dort sichtbar mit.

   Reihenfolge: Marken · Flächen · Schrift · Knöpfe · Felder · Auswahl · Karten ·
   Tabellen · Meldungen · Raster.
   ====================================================================== */

/* ============================================================ 1. Die Marken

   **Ein Wert steht an einer Stelle.** Wer eine Farbe oder einen Abstand braucht, nimmt
   eine Marke von hier — eine fest eingetippte Zahl in einer Moduldatei ist der Anfang
   von vier verschiedenen Grautönen für dieselbe Linie. */
:root {
  /* --- Fläche und Schrift ------------------------------------------------
     Puls hat **keine eigene Primärfarbe**: Die Fläche bleibt neutral, die Farbe kommt
     vom Mandanten und bedeutet immer dasselbe — in wessen Unternehmen man arbeitet. */
  --grund: #FFFFFF;          /* Karten, Felder, alles, was vorn liegt */
  --flaeche: #F2F5F9;        /* der Seitengrund hinter den Karten */
  --flaeche-tief: #E8ECF2;   /* Hervorhebung auf der Fläche, Tabellenköpfe */
  --linie: #DDE2E8;          /* Ränder, Trenner */
  --linie-stark: #C3CAD3;    /* Feldränder: sie müssen 3:1 erreichen, siehe unten */
  --text: #1A1D21;
  /* **Schrift auf einer Markenfläche, die Weiß nicht trägt** (25.10.2026). Renés
     Hotelorange `#E6511E` kommt mit Weiß auf **3,78:1** — gerechnet wird die Schriftfarbe
     deshalb (`util.schrift_auf`). Und `--text` genügt dort **nicht**: Es erreicht auf
     derselben Fläche nur **4,48:1**, also eine Hundertstel unter den 4,5 von WCAG 1.4.3.
     Dieses Dunkel kommt auf **4,67**. *Eine Nuance, die man nicht sieht und nachrechnen
     muss* — und deshalb steht sie als Token da und nicht als Zahl in Python. */
  --text-auf-farbe: #16191D;
  --gedaempft: #5F6771;      /* 4.6:1 auf Weiß — noch Fließtext-tauglich */
  /* **Gerechnet, nicht geschätzt** (10.10.2026, Renés Idee 22 — die Regel, die
     mews.design ausspricht und Puls nachprüfbar macht): Jede Farbe, die **Text** trägt,
     hält 4,5:1 (WCAG 1.4.3), und weiße Schrift auf einer Markenfläche ebenso.
     `tests/test_gestaltung.py` rechnet es nach.

     Drei Werte sind dafür an diesem Tag nachjustiert worden, jeder um eine Nuance:
     `--leise` (3,18 → 4,52 auf Weiß; sie trägt an **103** Stellen Text), `--gut`
     (4,33 → 4,50 unter weißer Schrift) und `--warnung` (4,23 → 4,52).

     **`--leise` bleibt die leiseste Stimme und nicht mehr:** Auf der getönten Fläche
     erreicht sie 4,13:1 — wer dort einen Satz zeigen will, der gelesen werden muss,
     nimmt `--gedaempft` (5,24:1). */
  --leise: #71777F;          /* nur für Nicht-Text: Striche, abgeschaltete Zeichen */

  /* --- Der Mandant ist der Akzent --------------------------------------- */
  --mandant: #4A5568;
  --mandant-fein: color-mix(in srgb, var(--mandant) 10%, white);
  --mandant-rand: color-mix(in srgb, var(--mandant) 45%, white);

  /* --- Bedeutungsfarben --------------------------------------------------
     **Nie mehr als vier Farben gleichzeitig** und **niemals eine reine Rot/Grün-
     Codierung** (Formwandler-Leitfaden). Jede Bedeutung tritt als Dreiklang auf:
     kräftig für Flächen, fein als Hintergrund, dunkel für Text auf Weiß — denn ein
     kräftiges Grün trägt weißen Text, aber keinen schwarzen. */
  --gut: #1E8759;      --gut-fein: #E8F5EE;      --gut-text: #14653F;
  --warnung: #AD650D;  --warnung-fein: #FDF3E4;  --warnung-text: #8A4F06;
  --fehler: #C0392B;   --fehler-fein: #FDECEA;   --fehler-text: #97271B;
  --info: #2E6FB8;     --info-fein: #EAF2FB;     --info-text: #1F4F86;

  /* --- Abstände: ein Raster von 4 ---------------------------------------
     Alles, was Abstand hat, nimmt eine dieser Stufen. Ein 13-Pixel-Abstand neben einem
     14er sieht nicht nach Absicht aus, sondern nach Zufall — und genau daraus entsteht
     der Eindruck von Unordnung, den man nicht benennen kann. */
  --a1: 4px;  --a2: 8px;  --a3: 12px; --a4: 16px; --a5: 20px;
  --a6: 24px; --a7: 32px; --a8: 40px; --a9: 48px; --a10: 64px;

  /* --- Rundungen und Schatten ------------------------------------------- */
  --r-klein: 6px; --r: 10px; --r-karte: 14px; --r-pille: 999px;
  --schatten-1: 0 1px 2px rgba(16, 24, 40, .06);
  --schatten-2: 0 2px 8px rgba(16, 24, 40, .08);
  --schatten-3: 0 8px 24px rgba(16, 24, 40, .12);

  /* --- Höhen der Bedienelemente -----------------------------------------
     **44 Pixel ist die Untergrenze für alles, was ein Finger trifft** (WCAG 2.2,
     Erfolgskriterium 2.5.8 „Zielgröße“, und die Grenze, unter der die Fehltippquote auf
     Tablets deutlich steigt). `--hoehe` ist der Regelfall, `--hoehe-gross` für Geräte im
     Betrieb — Küche, Bunker, Objekt —, `--hoehe-klein` nur für Werkzeugleisten am
     Schreibtisch, nie für ein Formularfeld.

     **`--hoehe-app` ist die vierte, und sie stand bis zum 01.10.2026 als rohe Zahl an
     acht Stellen in `mypuls.css`** (Renés Idee 8: „Oft sind die Buttons auf
     unterschiedlichen Höhen"). Die App bedient man im Gehen, mit einem Daumen, oft
     einhändig — großzügiger als am Schreibtisch, kleiner als ein Gerät an der Wand.
     Benannt ist sie, damit die Frage „sollen es 48 oder 52 sein?" **an einer Stelle**
     entschieden wird statt an acht; *eine vierte Zahl ohne Namen ist keine Entscheidung,
     sondern ein Zufall.* Sie gilt ausschließlich in myPuls.

     **`--hoehe-werkzeug` ist die fünfte und die einzige, die unter 44 liegt**
     (24.10.2026, Renés Notiz an Idee 8). Ein Zeichenknopf in einer Tabellenzeile ist
     ein Quadrat von 32 Pixeln: Drei davon brauchen 110 Pixel, drei Knöpfe mit Text
     über 220 und drängen die Inhaltsspalten zusammen. **Erfolgskriterium 2.5.8 ist
     trotzdem erfüllt** — es verlangt 24 × 24 *oder* genug Abstand, und beides steht:
     32 Pixel Kante, 6 Pixel Lücke, also 38 Pixel zwischen den Mittelpunkten.
     *Eine unsichtbare Trefferfläche von 44 Pixeln wäre hier die schlechtere Lösung:
     Bei 6 Pixeln Lücke überlappte sie den Nachbarn und stähle ihm den Klick.* */
  --hoehe-klein: 36px; --hoehe: 44px; --hoehe-gross: 52px; --hoehe-app: 48px;
  --hoehe-werkzeug: 32px;

  --schrift: "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --schrift-zahl: "Open Sans", ui-monospace, "SF Mono", Menlo, monospace;

  /* --- Übergänge --------------------------------------------------------
     Kurz und nur auf Farbe/Schatten. Eine Oberfläche, die sich bewegt, während jemand
     arbeitet, wirkt langsamer, als sie ist. */
  --zeit: .12s;
}

/* **Wer weniger Bewegung eingestellt hat, hat einen Grund dafür.** */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
}

/* ========================================================= 2. Grundflächen */

* { box-sizing: border-box; }
/* **Kein Bild ist breiter als sein Platz** (15.09.2026, nach dem zu großen Logo). */
img, svg, video { max-width: 100%; }

body {
  margin: 0; font-family: var(--schrift); color: var(--text);
  background: var(--flaeche); font-size: 15px; line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

/* **16 Pixel auf dem Telefon** (Formwandler-Leitfaden, und ein iPhone zoomt bei jedem
   Feld unter 16px beim Antippen ungefragt hinein — der Grund, warum kleine Schrift auf
   Mobilgeräten nicht nur schlecht lesbar, sondern schlicht kaputt ist). */
@media (max-width: 720px) {
  body { font-size: 16px; }
}

/* **Fokus ist keine Zierde, sondern der einzige Weg für die Tastatur.** Ein Ring von
   2 Pixeln mit Abstand, überall gleich, nie abgeschaltet. `:focus-visible` statt
   `:focus`, damit ein Mausklick keinen Ring hinterlässt. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--mandant); outline-offset: 2px; border-radius: var(--r-klein);
}

/* ============================================================== 3. Schrift

   Eine Skala mit wenigen Stufen. Wer eine Zwischengröße braucht, braucht in Wahrheit
   eine andere Stufe. */
h1 { font-size: 1.65rem; line-height: 1.25; margin: 0 0 var(--a3); font-weight: 700; }
h2 { font-size: 1.25rem; line-height: 1.3; margin: var(--a7) 0 var(--a3); font-weight: 700; }
h3 { font-size: 1.05rem; line-height: 1.35; margin: var(--a5) 0 var(--a2); font-weight: 700; }
h1:first-child, h2:first-child, h3:first-child { margin-top: 0; }

.gedaempft { color: var(--gedaempft); }
.klein { font-size: .86rem; }
/* **Zahlen stehen untereinander.** Tabellenziffern haben alle dieselbe Breite; ohne sie
   springt eine Spalte mit Beträgen bei jedem Wert, und man liest sie nicht mehr. */
/* **Am Ende der Spalte, nicht rechts.** In einer Tabelle sollen die Einer untereinander
   stehen — in einer von rechts nach links gelesenen Tabelle ist das die linke Kante. */
.zahl, td.zahl, th.zahl {
  font-variant-numeric: tabular-nums; text-align: end;
}

/* ============================================================== 4. Knöpfe

   Aus dem Knopf-Artikel der Serie, und jede Regel hat einen Grund, den man im Betrieb
   sieht:

   * **Eine primäre Handlung je Bildschirmabschnitt.** Zwei gleich starke Knöpfe
     nebeneinander sind keine Hierarchie, sondern eine Frage.
   * **Die Beschriftung ist ein Verb mit seinem Gegenstand** — „Schicht speichern“, nicht
     „OK“. Wer „OK“ liest, muss die Überschrift noch einmal lesen.
   * **Abgeschaltete Knöpfe sind die schlechtere Lösung.** Ein grauer Knopf sagt nicht,
     *warum* er grau ist. Wo es geht, bleibt der Knopf aktiv und die Absage nennt den
     Grund; `:disabled` bleibt für die Fälle, in denen wirklich nichts zu erklären ist
     (ein laufender Vorgang).
   * **Die zerstörende Handlung ist rot und steht nicht neben der primären.** */

button, .knopf, input[type="submit"] {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--a2);
  min-height: var(--hoehe); padding: 0 var(--a5);
  font: inherit; font-weight: 600; line-height: 1;
  border: 1px solid transparent; border-radius: var(--r-klein);
  background: var(--mandant); color: #fff; text-decoration: none; cursor: pointer;
  transition: background var(--zeit) ease, border-color var(--zeit) ease,
              box-shadow var(--zeit) ease, filter var(--zeit) ease;
}
button:hover, .knopf:hover { filter: brightness(1.08); }
button:active, .knopf:active { filter: brightness(.94); }

/* Zweite Stufe: gleiche Form, weniger Gewicht — für alles neben der Haupthandlung. */
button.zweit, .knopf.zweit, button.stumm, .knopf.stumm {
  background: var(--grund); color: var(--text); border-color: var(--linie-stark);
}
button.zweit:hover, .knopf.zweit:hover { background: var(--flaeche); filter: none; }

/* **Der gewählte Filter sieht gewählt aus** (11.10.2026). `.knopf … an` stand seit dem
   20.09.2026 in zwei Vorlagen (Gemeldete Fehler) und **in keiner Stildatei**: Die
   Filterzeile zeigte nicht, welcher Filter greift. Dieselbe Klasse wie `--radius-klein`
   am 10.10.2026 — *eine Klasse, die nichts bewirkt, fällt nicht auf.* Die Auswahl steht
   hinter `.zweit`, damit sie dessen Grund sticht. */
button.zweit.an, .knopf.zweit.an, button.an, .knopf.an {
  background: var(--flaeche); border-color: var(--text); color: var(--text);
  font-weight: 600;
}

/* Dritte Stufe: nur Schrift. Für das, was man selten braucht und nie sucht. */
button.leer, .knopf.leer {
  background: none; border-color: transparent; color: var(--gedaempft);
  font-weight: 600; padding: 0 var(--a3);
}
button.leer:hover, .knopf.leer:hover { background: var(--flaeche-tief); filter: none; }

/* **Zerstörend**: rot, und die Beschriftung nennt die Tat („Löschen“, nie „Ja“). */
button.rot, .knopf.rot { background: var(--fehler); border-color: var(--fehler); }

button.gross, .knopf.gross { min-height: var(--hoehe-gross); padding: 0 var(--a6);
  font-size: 1.05rem; }
button.schmal, .knopf.schmal { min-height: var(--hoehe-klein); padding: 0 var(--a3);
  font-size: .88rem; }
/* Auf dem Telefon nimmt die Haupthandlung die ganze Breite — ein 120 Pixel breiter Knopf
   am Rand eines 380-Pixel-Bildschirms ist verschenkter Platz und ein kleineres Ziel. */
button.breit, .knopf.breit { width: 100%; }
@media (max-width: 560px) { .knopfzeile > button, .knopfzeile > .knopf { flex: 1 1 auto; } }

button:disabled, .knopf[aria-disabled="true"] {
  opacity: .55; cursor: not-allowed; filter: none;
}
/* **Der Ladezustand** ist ein eigener Zustand, kein abgeschalteter Knopf: Er sagt „es
   läuft“, nicht „geht nicht“. */
button[data-laeuft]::before {
  content: ""; width: 1em; height: 1em; border-radius: 50%; flex: 0 0 auto;
  border: 2px solid currentColor; border-top-color: transparent;
  animation: puls-dreht .7s linear infinite;
}
@keyframes puls-dreht { to { transform: rotate(360deg); } }

.knopfzeile { display: flex; gap: var(--a3); align-items: center; flex-wrap: wrap;
  margin-top: var(--a5); }
/* Ein Abstand, der die zerstörende Handlung von der primären trennt — damit der Daumen
   nicht danebentrifft. */
.knopfzeile .rot { margin-inline-start: auto; }

/* ============================================================== 5. Felder

   Aus dem Textfeld-Artikel. Die vier Regeln, die den Unterschied machen:

   1. **Das Etikett steht über dem Feld und bleibt stehen.** Nicht daneben (bricht auf
      schmalen Bildschirmen und bei langen Wörtern), nicht schwebend (schlechter Kontrast,
      und beim Ausfüllen sitzt es im Weg), nicht im Feld.
   2. **Ein Platzhalter ist kein Etikett.** Er verschwindet beim ersten Zeichen, und dann
      weiß niemand mehr, was hier hingehört — im Formular des Personalfragebogens ist das
      der Unterschied zwischen einer Steuer-ID und einer Sozialversicherungsnummer. Er
      dient nur als **Beispiel** für das Format („z. B. 12.03.1980“).
   3. **Die Breite des Feldes sagt, wie lang die Antwort ist.** Eine Postleitzahl bekommt
      110 Pixel, eine Straße die ganze Zeile. Ein Formular aus lauter gleich breiten
      Feldern ist schwerer auszufüllen, weil jedes Feld erst gelesen werden muss.
   4. **Der Fehler steht am Feld, nicht am Seitenkopf** — mit Text *und* Zeichen, nie mit
      Farbe allein, und **geprüft wird beim Verlassen des Feldes**, nicht bei jedem
      Tastendruck: Wer beim dritten Zeichen einer E-Mail-Adresse „ungültig“ liest, wird
      beim echten Fehler nicht mehr hinsehen. */

label { display: block; font-weight: 600; margin: 0 0 var(--a1); }
/* **Gekennzeichnet wird das Seltenere.** In Puls sind die meisten Felder freiwillig, also
   steht „Pflicht“ dran — und wo fast alles Pflicht ist, steht „(optional)“ an den
   anderen. Eine Seite voller Sternchen sagt nichts. */
label .pflicht { color: var(--fehler-text); font-weight: 700; margin-inline-start: 2px; }
label .freiwillig { color: var(--gedaempft); font-weight: 400; }

/* **Kästchen, Punkte und Schalter sind ausgenommen** — sie sind keine Textfelder.
   `input` trifft sonst auch sie, und aus einem 22-Pixel-Kästchen würde eine Fläche über
   die ganze Zeilenbreite. Dieselbe Falle steckte schon in der alten `dienstplan.css`;
   mit einer Mindesthöhe von 44 Pixeln wäre sie unübersehbar geworden.
   Ebenso ausgenommen: Datei-, Farb- und Schiebefelder — sie bringen ihre eigene
   Darstellung mit, und ein Rahmen darum sieht aus wie ein zweites Feld. */
input:not([type="checkbox"], [type="radio"], [type="file"], [type="color"],
          [type="range"], [type="image"], [type="submit"], [type="button"]),
select, textarea {
  width: 100%; min-height: var(--hoehe); font: inherit; color: var(--text);
  padding: 0 var(--a3); background: var(--grund);
  border: 1px solid var(--linie-stark); border-radius: var(--r-klein);
  transition: border-color var(--zeit) ease, box-shadow var(--zeit) ease;
}
/* Ein Kästchen oder Punkt **außerhalb** einer `.wahl`-Zeile bekommt wenigstens eine
   brauchbare Größe und die Farbe des Unternehmens. */
input[type="checkbox"], input[type="radio"] {
  width: 20px; height: 20px; accent-color: var(--mandant); cursor: pointer;
}
textarea { padding: var(--a3); min-height: 96px; line-height: 1.5; resize: vertical; }
select { appearance: none; padding-inline-end: var(--a7);
  /* Das Zeichen ist eingebettet, nicht geladen: ein Bild aus dem Netz wäre ein Weg nach
     draußen, der in keiner Integrationstabelle steht. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%235F6771' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right var(--a3) center;
}
/* **Von rechts nach links wandert das Zeichen mit** (Arabisch, seit 23.09.2026):
   `background-position` kennt keine logische Schreibweise, also wird es hier gedreht.
   Eine einzige seitenabhängige Zeile reicht, damit die Oberfläche schief steht — und es
   fällt nur dem auf, der sie benutzt. */
[dir="rtl"] select { background-position: left var(--a3) center;
  padding-inline-end: var(--a3); padding-inline-start: var(--a7); }
input:not([type="checkbox"], [type="radio"]):hover, select:hover, textarea:hover {
  border-color: var(--gedaempft);
}
input:not([type="checkbox"], [type="radio"]):focus, select:focus, textarea:focus {
  outline: none; border-color: var(--mandant);
  box-shadow: 0 0 0 3px var(--mandant-fein);
}
input::placeholder, textarea::placeholder { color: var(--leise); }

/* **Nicht änderbar heißt nicht kaputt.** `readonly` bleibt lesbar (der Text steht auf
   voller Deckkraft), `disabled` ist sichtbar außer Betrieb. Zwei verschiedene Aussagen,
   die überall gleich aussahen. */
input[readonly], textarea[readonly] { background: var(--flaeche); border-style: dashed; }
input:not([type="checkbox"], [type="radio"]):disabled, select:disabled,
textarea:disabled {
  background: var(--flaeche-tief); color: var(--gedaempft); cursor: not-allowed;
}
input[type="checkbox"]:disabled, input[type="radio"]:disabled {
  opacity: .5; cursor: not-allowed;
}

/* Zustände am Feld. `aria-invalid` ist die Quelle — so liest es auch ein Screenreader,
   und die Farbe ist nur die Zugabe. */
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"],
.feld.fehlerhaft input, .feld.fehlerhaft select, .feld.fehlerhaft textarea {
  border-color: var(--fehler); box-shadow: 0 0 0 3px var(--fehler-fein);
}
.feld.geprueft input { border-color: var(--gut); }

/* Der Feldblock: Etikett, Feld, Hilfe, Fehler — immer in dieser Reihenfolge. */
.feld { margin-bottom: var(--a4); min-width: 0; }
.feldhilfe { display: block; margin-top: var(--a1); font-size: .84rem;
  color: var(--gedaempft); }
/* **Der Fehler trägt ein Zeichen**, damit er ohne Farbunterscheidung ankommt. */
.feldfehler { display: flex; align-items: flex-start; gap: var(--a1);
  margin-top: var(--a1); font-size: .86rem; font-weight: 600; color: var(--fehler-text); }
.feldfehler::before { content: "⚠"; flex: 0 0 auto; }

/* **Breiten, die der Antwort entsprechen.** Ein Feld, das dreimal so breit ist wie sein
   Inhalt, lässt den Ausfüllenden zweifeln, ob er alles eingegeben hat. */
.feld.w-klein { max-width: 110px; }   /* PLZ, Hausnummer, Anzahl */
.feld.w-mittel { max-width: 200px; }  /* Datum, Betrag, Telefon */
.feld.w-gross { max-width: 380px; }   /* Name, Ort */
.feld.w-voll { max-width: none; }     /* Straße, Betreff, Text */

/* Felder nebeneinander nur, wenn sie zusammengehören (PLZ und Ort). Sonst untereinander:
   Ein Formular in einer Spalte wird nachweislich schneller und fehlerärmer ausgefüllt. */
.feldpaar { display: flex; gap: var(--a4); flex-wrap: wrap; align-items: flex-start; }
.feldpaar > .feld { flex: 1 1 200px; }

/* Ein Bund gehört zusammen und trägt seine Überschrift — für die Tastatur und den
   Screenreader ist das `<fieldset>` die Gruppe, nicht die Überschrift daneben. */
fieldset.bund { border: 1px solid var(--linie); border-radius: var(--r);
  padding: var(--a4); margin: 0 0 var(--a5); min-width: 0; }
fieldset.bund > legend { padding: 0 var(--a2); font-weight: 700; }

/* ======================================================= 6. Auswahlelemente

   Aus dem Artikel über Auswahlelemente. **Die Wahl des Bauteils ist eine fachliche
   Aussage**, keine Geschmacksfrage:

   | Bauteil | Wofür | Wirkt |
   |---|---|---|
   | **Kästchen** | mehrere aus einer Menge, unabhängig voneinander | erst beim Absenden |
   | **Punkt** | genau eines aus zwei bis fünf | erst beim Absenden |
   | **Schalter** | ein Zustand an oder aus | **sofort** |
   | **Liste** | eines aus vielen (ab etwa sechs) | erst beim Absenden |

   Der häufigste Fehler ist der Schalter, der erst beim Speichern wirkt: Wer ihn umlegt,
   hat den Eindruck, es sei erledigt — und geht. */

.wahl { display: flex; align-items: flex-start; gap: var(--a3);
  /* **Die ganze Zeile ist das Ziel**, nicht das 20-Pixel-Kästchen. */
  min-height: var(--hoehe); padding-block: var(--a2);
  padding-inline: 0 var(--a2);
  cursor: pointer; font-weight: 400; margin: 0; }
.wahl:hover { color: var(--text); }
.wahl input[type="checkbox"], .wahl input[type="radio"] {
  width: 22px; height: 22px; min-height: 0; flex: 0 0 auto; margin: 1px 0 0;
  accent-color: var(--mandant); cursor: pointer;
}
.wahl > span { display: block; }
.wahl .wahlname { font-weight: 600; }
.wahl .wahlhilfe { display: block; font-size: .84rem; color: var(--gedaempft); }
/* Untereinander, nicht nebeneinander: eine senkrechte Liste liest man in einem Zug. */
.wahlgruppe { display: flex; flex-direction: column; }
.wahlgruppe.nebeneinander { flex-direction: row; flex-wrap: wrap; gap: var(--a4); }

/* **Der Schalter** — und er wirkt sofort. Deshalb steht er in einem eigenen kleinen
   Formular und braucht keinen Speichern-Knopf daneben. */
.schalter { display: flex; align-items: center; gap: var(--a3);
  min-height: var(--hoehe); cursor: pointer; font-weight: 600; margin: 0; }
.schalter input { position: absolute; opacity: 0; width: 0; height: 0; }
.schalter .gleis {
  position: relative; flex: 0 0 auto; width: 46px; height: 26px; border-radius: var(--r-pille);
  background: var(--linie-stark); transition: background var(--zeit) ease;
}
.schalter .gleis::after {
  content: ""; position: absolute; top: 3px; inset-inline-start: 3px;
  width: 20px; height: 20px; border-radius: 50%; background: #fff;
  box-shadow: var(--schatten-1); transition: transform var(--zeit) ease;
}
.schalter input:checked + .gleis { background: var(--gut); }
.schalter input:checked + .gleis::after { transform: translateX(20px); }
[dir="rtl"] .schalter input:checked + .gleis::after { transform: translateX(-20px); }
.schalter input:focus-visible + .gleis { outline: 2px solid var(--mandant);
  outline-offset: 2px; }
.schalter input:disabled + .gleis { opacity: .5; }
/* **Das Wort neben dem Schalter benennt die Sache, nicht den Zustand** — „Push-Nachrichten“
   und nicht „Push aus“: Sonst liest man beim Umlegen das Gegenteil dessen, was gilt. */

/* ============================================================== 7. Karten

   Aus dem Dashboard-Leitfaden: **weiße Karten auf getöntem Grund**, gestapelt statt
   nebeneinandergedrängt, eine Kennzahl groß. */
.karte { background: var(--grund); border-radius: var(--r-karte); padding: var(--a5);
  box-shadow: var(--schatten-1); }
.karte > h2:first-child, .karte > h3:first-child { margin-top: 0; }
.kartenkopf { display: flex; align-items: center; justify-content: space-between;
  gap: var(--a4); margin-bottom: var(--a4); }

/* **Vier Grundformen, die keiner Moduldatei gehören** (26.10.2026, Renés „Räum auf —
   was gemacht werden muss").

   **Gemessen waren es 36 Klassen**, die in mindestens einer Vorlage **nicht wirkten**:
   Sie stehen in einer Stildatei, die die Seite nicht lädt. *Eine Kanonklasse in der
   falschen Datei wirkt nicht und fällt nicht auf.*

   ***Und 32 davon lassen sich nicht hierher verschieben.*** Der Hausstandard sagt: **Ein
   Name gehört einer Schicht** (`test_die_bauteilschicht_belegt_keinen_fremden_namen_neu`),
   und `.hinweis` ist in vier Moduldateien, `.marke` in drei, `.abschnitt` in zwei — mit
   verschiedenen Bedeutungen. Eine Grundform hier würde ihnen eine fremde Bauart
   aufzwingen. *Die Lösung liegt deshalb in den Vorlagen und nicht in dieser Datei* —
   siehe die Frage dazu in `docs/plan.md`.

   Hier stehen nur die vier, die **keine** Moduldatei beansprucht. */
.still { opacity: .6; }
/* **Eine Liste von Befunden, jeder ein Satz mit Weg** (Renés Abschnitt 9 zu Idee 36,
   26.10.2026). Kein Aufzählungszeichen, sondern Luft zwischen den Sätzen: *Ein Befund
   ist ein Satz, den man liest, und kein Punkt in einer Liste, die man überfliegt.* */
.befundliste { list-style: none; padding: 0; margin: 0 0 var(--a5); }
.befundliste li { border-inline-start: 3px solid var(--mandant);
  padding: var(--a2) var(--a4); margin-bottom: var(--a2);
  background: var(--flaeche); border-radius: var(--r-klein); }
.befundliste a { color: var(--text); text-decoration: none; display: block; }
.befundliste a:hover { text-decoration: underline; }
.gewaehlt { outline: 2px solid var(--mandant); outline-offset: 1px; }
.stark { font-weight: 700; }

/* **Die Reihe, in der Kennzahlen stehen.** Sie gehört in den Kanon und nicht in eine
   Moduldatei — *eine Kennzahl ohne ihre Reihe ist ein halbes Bauteil*, und `.kennzahl`
   steht hier.

   **Gefunden am 26.10.2026:** Die Klasse stand nur in `kantine.css`. Damit war sie für
   **sieben Seiten des Admin-Tools wirkungslos** — `/lumi/statistik`, `/lumi/wissen`,
   `/lumi/archiv`, `/systeme` und die drei Einkaufsseiten laden `kantine.css` nicht, und
   ihre Kennzahlen standen untereinander statt nebeneinander. *Eine Kanonklasse in der
   falschen Datei wirkt nicht und fällt nicht auf.* */
.kopfzahlen { display: flex; flex-wrap: wrap; gap: var(--a4); }

/* Die große Zahl mit ihrer Beschriftung **darüber** — man liest erst, was es ist. */
.kennzahl { display: flex; flex-direction: column; gap: 2px; }
.kennzahl .kzname { font-size: .78rem; color: var(--gedaempft);
  text-transform: uppercase; letter-spacing: .04em; }
.kennzahl .kzwert { font-size: 2rem; font-weight: 700; line-height: 1.05;
  font-variant-numeric: tabular-nums; }
/* **Eine Zahl ohne Vergleich ist keine Kennzahl** (Dashboard-Leitfaden und die Regel des
   Admin-Dashboards seit dem 13.09.2026). Der Pfeil trägt die Richtung, die Farbe ist
   Zugabe — nie Rot/Grün allein. */
.kennzahl .kztrend { font-size: .84rem; font-weight: 600; }
.kztrend.hoch { color: var(--gut-text); }
.kztrend.runter { color: var(--fehler-text); }

/* =========================================================== 8. Tabellen */
table.liste { width: 100%; border-collapse: collapse; background: var(--grund);
  border-radius: var(--r); overflow: hidden; }
table.liste th { text-align: start; font-size: .8rem; text-transform: uppercase;
  letter-spacing: .04em; color: var(--gedaempft); background: var(--flaeche-tief);
  padding: var(--a3) var(--a4); white-space: nowrap; }
table.liste td { padding: var(--a3) var(--a4); border-top: 1px solid var(--linie); }
table.liste tbody tr:hover { background: var(--flaeche); }

/* ======================================= 8a. Sortierbare Spaltenköpfe

   Seit dem 26.10.2026 (Renés Auftrag zum Einkaufscontrolling: „Tabellen
   Übersichtlichkeit und Funktion nicht vergessen").

   **Der Kopf bleibt ein Kopf.** Er sieht nicht wie ein Knopf aus — er trägt nur ein
   Zeichen, das sagt, dass man ihn anklicken kann: `⇅` ruhend, `▾`/`▴` an der Spalte, nach
   der gerade geordnet ist. *Zehn Knöpfe in einer Kopfzeile sehen aus wie zehn
   Handlungen, und keine davon ist die Tabelle.*

   **Das Ziel ist die ganze Zelle**, nicht das Wort darin: `display: block` plus die
   negativen Abstände des `th` — ein 14 Pixel hohes Klickziel in einer Kopfzeile trifft
   niemand mit dem Finger (WCAG 2.5.8, dieselbe Lehre wie bei `.ansichtswahl` am
   09.10.2026). */
table.liste th:has(> .sortkopf) { padding: 0; }
.sortkopf { display: block; padding: var(--a3) var(--a4); color: inherit;
  text-decoration: none; }
.sortkopf:hover { background: var(--linie); color: var(--text); }
.sortkopf.an { color: var(--text); }
/* **Das ruhende Zeichen ist leise und wird beim Überfahren deutlich** — sonst stehen in
   jeder Kopfzeile neun gleich laute Zeichen, und keines sagt etwas. */
.sortpfeil { margin-inline-start: var(--a2); opacity: .35; }
.sortkopf:hover .sortpfeil, .sortkopf.an .sortpfeil { opacity: 1; }

/* =============================== 8b. Werkzeuge in einer Tabellenzeile

   Seit dem 24.10.2026 im Kanon statt in `dienstplan.css` (Renés Notiz an Idee 8:
   „Prüfe bitte die Buttons und Schaltflächen im Bereich Dienstplan/Mitarbeiter/Dokumente
   — dort stehen die Button in der Abfrage nach den Nachweisen nicht ordnungsgemäß aus.")

   **Die Form gab es seit dem 26.09.2026 und sie lag in der falschen Datei.** Das
   Admin-Tool lädt `dienstplan.css` nicht, also war sie auf `/berichte` **wirkungslos** —
   dieselbe Klasse wie `--radius-klein` am 10.10.2026: *eine Klasse, die nichts bewirkt,
   fällt nicht auf.*

   **`min-height: 0` ist hier wieder die halbe Regel** (die Lehre vom 01.10.2026, zum
   zweiten Mal): Der Kanon gibt **jedem** `button` 44 Pixel Mindesthöhe. `height: 32px`
   setzt die Höhe und hebt das Mindestmaß **nicht** auf — aus 32 × 32 wurden 32 × 44.
   Ein `<a class="werkzeugknopf">` bekommt es nicht, ein `<button>` schon: **In sechs
   Vorlagen stand der Stift 32 Pixel hoch neben einem Mülleimer von 44.** Das ist Renés
   Satz „oft sind die Buttons auf unterschiedlichen Höhen" wörtlich und zählbar.

   Drei Knöpfe mit Text brauchen in einer Tabellenspalte über 220 Pixel, drei Zeichen
   110 — und ein Schieberegler sagt seinen Zustand, statt ihn zu benennen. */
.zeilenwerkzeuge { display: flex; gap: var(--a2); justify-content: flex-end;
  align-items: center; white-space: nowrap; }
/* **Ein Formular ist hier kein Block.** Ohne diese Zeile bricht jedes `<form>` in der
   Zelle auf eine eigene Zeile — genau der Grund, warum das Dokumentenblatt „nicht
   ordnungsgemäß" aussah. */
.zeilenwerkzeuge form { display: flex; margin: 0; }

/* **Eine Tabellenzelle bleibt eine Tabellenzelle** (24.10.2026, Renés zweiter Befund
   am selben Abend: „allerdings sind die Trennlinien an dieser Stelle nach oben
   gerutscht").

   `display: flex` an einem `<td>` nimmt es aus dem Tabellenlayout: Der Browser legt
   eine anonyme Zelle darum, die Zelle wird **nicht mehr auf Zeilenhöhe gestreckt**, und
   ihr `border-top` — die Trennlinie der Liste — sitzt an ihrer eigenen Unterkante statt
   an der der Zeile. Auf seinem Bildschirm lief die Linie der Schalterspalte quer durch
   die Zeile. *Dieselbe Fehlerklasse wie `.raster` am 26.09.2026, nur eine Ebene tiefer:
   Was eine Tabelle zerstört, zerstört auch eine Zelle.*

   **Nebeneinander stehen die Werkzeuge auch ohne Flex.** Was umbricht, ist das
   **Formular** — und das wird hier inline. Die senkrechte Ausrichtung kommt damit
   wieder von der Zeile, wie bei jeder anderen Spalte. */
td.zeilenwerkzeuge, th.zeilenwerkzeuge { display: table-cell; text-align: end; }
td.schalterspalte, th.schalterspalte { display: table-cell; text-align: start; }
td.zeilenwerkzeuge > *, td.schalterspalte > * { vertical-align: middle; }
td.zeilenwerkzeuge > form, td.schalterspalte > form { display: inline-flex; }
td.zeilenwerkzeuge > * + *, td.schalterspalte > * + * {
  margin-inline-start: var(--a1); }
.werkzeugknopf { display: inline-flex; align-items: center; justify-content: center;
  width: var(--hoehe-werkzeug); height: var(--hoehe-werkzeug); min-height: 0;
  flex: 0 0 auto; border-radius: var(--r-klein); border: 1px solid var(--linie);
  background: var(--grund); color: var(--gedaempft); cursor: pointer;
  text-decoration: none; padding: 0; font-size: 13px; font-weight: 400; }
.werkzeugknopf svg { width: 17px; height: 17px; fill: none; stroke: currentColor;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.werkzeugknopf:hover { background: var(--flaeche); color: var(--text);
  border-color: var(--gedaempft); filter: none; }
.werkzeugknopf:focus-visible { outline: 2px solid var(--mandant); outline-offset: 2px; }
/* **Gestrichelt heißt: geht nicht, und daneben steht warum.** Ein abgeschalteter Knopf
   sagt nicht, *warum* er grau ist (Abschnitt 4) — dieser trägt seinen Grund im
   Mouse-over und ist gar kein Knopf, sondern ein `<span>`. */
.werkzeugknopf.leer { border-style: dashed; cursor: default; }

/* **`.werkzeug` ist dieselbe Form in 44 Pixeln** — der Knopf in der **Leiste über** einer
   Liste (Suche, Drucken, Ausgabe als Datei, Kacheln gegen Liste), nicht in der Zeile.
   Zwei Größen, zwei Orte, **eine Stelle**: Er lag bis zum 24.10.2026 in `dienstplan.css`
   und trug seine Zeichen als Schriftzeichen und Emoji (✎ ⎙ ↓ ✉ 🗑). *Ein Emoji ist keine
   Strichzeichnung* — und ein `<svg>` ohne Maß wäre 300 × 150 groß, deshalb steht die
   Größe hier und nicht in der Vorlage. */
.werkzeug { display: inline-flex; align-items: center; justify-content: center;
  width: var(--hoehe); height: var(--hoehe); min-height: 0; flex: 0 0 auto;
  padding: 0; border: 1px solid var(--linie); border-radius: var(--r-klein);
  background: var(--grund); color: var(--gedaempft); text-decoration: none;
  font-size: 17px; font-weight: 400; }
.werkzeug:hover { background: var(--flaeche); color: var(--text);
  border-color: var(--gedaempft); filter: none; }
.werkzeug:focus-visible { outline: 2px solid var(--mandant); outline-offset: 2px; }
.werkzeug svg { width: 19px; height: 19px; fill: none; stroke: currentColor;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

/* **Die Ansichtswahl** — zwei bis drei Werkzeuge, die zusammengehören und von denen
   genau eines gilt (Kacheln gegen Liste). Sie ist ein Schalter in Knopfgestalt: Die
   Wahl steht an `.an`, und sie wirkt sofort.

   **Sie stand in `dienstplan.css` *und* `puls.css`** — zwei Fassungen mit zwei Rundungen
   (`6px` gegen `var(--radius)`), und die Oberflächen, die beide laden, bekamen die
   zufällig letzte (24.10.2026). *Genau die Uneinheitlichkeit, gegen die der Kanon
   angetreten ist, und sie fällt nie auf, weil man die beiden Leisten nie nebeneinander
   sieht.* */
.ansichtswahl { display: flex; }
.ansichtswahl form { display: flex; margin: 0; }
.ansichtswahl a, .ansichtswahl button {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--hoehe); height: var(--hoehe); min-height: 0; flex: 0 0 auto;
  padding: 0; font-size: 16px; font-weight: 400; border-radius: 0;
  border: 1px solid var(--linie); background: var(--grund); color: var(--gedaempft);
  text-decoration: none; }
.ansichtswahl > *:first-child, .ansichtswahl form:first-child > * {
  border-start-start-radius: var(--r-klein); border-end-start-radius: var(--r-klein); }
.ansichtswahl > *:last-child, .ansichtswahl form:last-child > * {
  border-start-end-radius: var(--r-klein); border-end-end-radius: var(--r-klein);
  border-inline-start: none; }
.ansichtswahl a.an, .ansichtswahl button.an {
  background: var(--flaeche); color: var(--text); font-weight: 400; }
.ansichtswahl a:hover, .ansichtswahl button:hover { color: var(--text); filter: none; }
.ansichtswahl a:focus-visible, .ansichtswahl button:focus-visible {
  outline: 2px solid var(--mandant); outline-offset: 2px; }
.ansichtswahl svg { width: 19px; height: 19px; fill: none; stroke: currentColor;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

/* **Das Unternehmen als Zeichen** (25.10.2026, Renés Anmerkung zum Modul Dienstplan:
   „Die Auswahl der Unternehmen läuft ins Menü — es ist viel zu lang. Es würde mir
   reichen, das Unternehmen in Abkürzung zu sehen, rund, Hintergrund die
   Unternehmensfarbe.")

   **Die Farbe trägt die Wiedererkennung, die zwei Buchstaben die Aussage** — Farbe
   allein ist keine Information (WCAG 1.4.1). Die **Schriftfarbe wird gerechnet**
   (`util.schrift_auf`, als Jinja-Filter `|schrift`): Renés Hotelorange `#E6511E` trägt
   Weiß nur mit 3,78:1, die übrigen fünf Häuser zwischen 5,0 und 8,3. *Eine
   Schriftfarbe, die für fünf von sechs stimmt, ist keine Regel, sondern ein Zufall.*

   34 Pixel plus das Polster des Schalters ergeben die 44 des Fingerziels. */
/* **Kein `min-height: 0`** — die Form sitzt auf einem `<span>` und einem `<a>`, nie auf
   einem Knopf; das Mindestmaß des Kanons gilt dort nicht, und *ein Feld, das nichts
   bewirkt, ist schlimmer als ein fehlendes.* Wer sie an einen `<button>` schreibt, wird
   von `test_jede_feste_hoehe_hebt_das_mindestmass_auf` daran erinnert. */
.firmazeichen { display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex: 0 0 auto; border-radius: 50%;
  font-size: 12.5px; font-weight: 700; letter-spacing: .3px; line-height: 1;
  text-decoration: none; }
/* In der Klappe steht der ganze Name daneben — dort genügt das halbe Zeichen. */
.firmazeichen.klein { width: 24px; height: 24px; font-size: 10.5px; }
/* Kein Unternehmen gewählt: ein Zeichen, das nichts behauptet. */
.firmazeichen.ohne { background: var(--linie-stark); color: var(--text); }

/* **Die Codenummer** — eine Zahl, die jemand **vorliest oder abtippt**, nicht eine, die
   man summiert (07.11.2026, Plan 2.106 Nr. 717): die vier Ziffern des Aufklebers am
   Objekt, und künftig jede Nummer derselben Art.

   Darum eine Festbreitenschrift mit Sperrung: Eine 1 neben einer 7 verschwimmt sonst zur
   17, und dann steht jemand vor der falschen Wand. **Dieselbe Entscheidung wie auf dem
   gedruckten Blatt** — dort in 14 mm, hier in Lesegröße. */
.codenummer { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-weight: 700;
  letter-spacing: 1.5px; white-space: nowrap; }

/* **Die Hakenliste** — mehrere Zeilen zum Abhaken untereinander, jede ein `<label>` mit
   seinem Kästchen (`.hakenzeile`): die Liste „was ist gemacht worden?" (07.11.2026,
   Plan 2.106 Nr. 724).

   **Warum nicht `.haken`**, die es seit dem 15.09.2026 gibt: Dieser Name steht in
   **drei** Dateien für **drei** Dinge — in `dienstplan.css` für diese Zeile, in
   `bereich.css` für das 30-Pixel-Kästchen eines Checklistenpunktes, in `kantine.css` für
   einen antippbaren Haken aus einem Schriftzeichen. Er steht deshalb in
   `BEKANNTE_STILLUECKEN` (`tests/test_gestaltung.py`), *und sein Aufräumen ist eine
   Entscheidung Renés, weil es das Aussehen von Dutzenden Seiten ändert* — keine
   Nebenarbeit an einem Fenster. **Eine neue Form mit eindeutigem Namen nimmt diese
   Entscheidung nicht vorweg.** */
.hakenliste { border: 0; padding: 0; margin: var(--a3) 0 0; }
.hakenliste legend { padding: 0; font-weight: 600; }
.hakenzeile { display: flex; align-items: flex-start; gap: 9px; margin: 7px 0;
  font-size: 14px; color: var(--text); }
.hakenzeile input { width: auto; margin: 3px 0 0; flex: 0 0 auto; }

/* **Die Wahlreihe** — eine Reihe aus Filterknöpfen **mit Wort** über einer Liste
   („Offen · Alle", „Zu tun · In Arbeit · Erledigt"). Sie hieß bis zum 24.10.2026
   `.schalter` wie die Schaltfläche aus Abschnitt 6 und stand in `dienstplan.css`
   **und** `puls.css`; die Form ist dieselbe, **die Farbe des gewählten Knopfes nicht**
   — im Admin-Tool trägt sie die Mandantenfarbe, in den Modulen Blau. *Die Form gehört
   hierher, die Zustandsfarbe bleibt beim Modul: sie benennt einen Gebrauch.* */
.wahlreihe { display: flex; flex-wrap: wrap; gap: var(--a2); align-items: center;
  margin-bottom: var(--a2); }
.wahlreihe form { display: flex; margin: 0; }
/* **Die Höhe bleibt die des Kanons** (44 px): Diese Knöpfe tragen ein Wort und werden
   mit dem Finger getroffen — `--hoehe-klein` wäre hier eine stille Verkleinerung von
   etwas, das vorher richtig war. Nur Schrift und Polster sind knapper, damit eine Reihe
   aus vier Filtern nicht die halbe Breite nimmt. */
.wahlreihe button, .wahlreihe .knopf {
  font-size: 13px; font-weight: 600; padding: 6px 12px; }

/* **Der Rundschalter** — ein Zustand je Zeile, der sofort wirkt, wo für einen
   Schieberegler kein Platz ist: drei nebeneinander in einer Tabellenspalte. Er trug
   **denselben Fehler** und war damit 30 × 44, also ein Oval statt eines Kreises — auf
   genau dem Blatt, das Renés Notiz nennt. Jetzt ist er so groß wie der Werkzeugknopf
   daneben: *zwei Spalten in derselben Zeile, zwei verschiedene Höhen, und beides fällt
   nur zusammen auf.* */
.schalterspalte { display: flex; gap: var(--a2); align-items: center;
  white-space: nowrap; }
.schalterspalte form { display: flex; margin: 0; }
.rundschalter { width: var(--hoehe-werkzeug); height: var(--hoehe-werkzeug);
  min-height: 0; flex: 0 0 auto; padding: 0; border-radius: 50%; font-size: 13px;
  font-weight: 400; background: var(--flaeche); border: 1px solid var(--linie);
  color: var(--gedaempft); }
.rundschalter:hover { background: var(--flaeche-tief); filter: none; }
.rundschalter.an { background: var(--info-fein); border-color: var(--info);
  color: var(--info); }
.rundschalter.gut { background: var(--gut); border-color: var(--gut); color: #fff; }
.rundschalter:focus-visible { outline: 2px solid var(--mandant); outline-offset: 2px; }
/* Ein Kreis von 32 Pixeln trägt ein Zeichen von 15 — mehr sprengt den Rand. */
.rundschalter svg { width: 15px; height: 15px; fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* **Der Schieberegler** ist der Schalter aus Abschnitt 6 als abgeschickter Knopf — die
   Form, die der Kanon für „wirkt sofort" vorsieht, **ohne Skript**: Was allein an einem
   Skript hängt, ist eine Falle (13.09.2026). Dasselbe Aussehen, zwei Mechaniken; die
   Maße stehen deshalb hier und nicht zweimal.

   **Die Trefferfläche ist 44 Pixel hoch** und liegt unsichtbar um ihn herum, statt ihn
   aufzublasen — ihn selbst zu vergrößern machte aus ihm ein Quadrat (01.10.2026, Renés
   Idee 8: „Schaltflächen für an/Ausschalten sind sehr quadratisch und
   überproportional"). */
.schieber { position: relative; width: 46px; height: 26px; min-height: 0; flex: 0 0 auto;
  padding: 0; line-height: 1; border-radius: var(--r-pille);
  border: 1px solid transparent; background: var(--linie-stark);
  cursor: pointer; transition: background var(--zeit) ease; }
.schieber::after { content: ""; position: absolute; inset: -9px -4px; }
.schieber .knauf { position: absolute; top: 3px; inset-inline-start: 3px; width: 20px;
  height: 20px; border-radius: 50%; background: #fff; box-shadow: var(--schatten-1);
  transition: inset-inline-start var(--zeit) ease; }
.schieber.an { background: var(--gut); border-color: var(--gut); }
.schieber.an .knauf { inset-inline-start: 23px; }
.schieber:hover { filter: none; }
.schieber:focus-visible { outline: 2px solid var(--mandant); outline-offset: 2px; }

/* ========================================================== 9. Meldungen

   **Farbe, Zeichen und Text** — jede Meldung sagt dasselbe dreifach, damit sie ankommt,
   wenn eine der drei Ebenen ausfällt. */
.meldung { display: flex; align-items: flex-start; gap: var(--a3);
  padding: var(--a3) var(--a4); border-radius: var(--r-klein);
  border-inline-start: 4px solid var(--info); background: var(--info-fein);
  color: var(--info-text); margin: 0 0 var(--a4); }
.meldung::before { content: "i"; flex: 0 0 auto; font-weight: 700; }
.meldung.gut { border-color: var(--gut); background: var(--gut-fein); color: var(--gut-text); }
.meldung.gut::before { content: "✓"; }
.meldung.warnung { border-color: var(--warnung); background: var(--warnung-fein);
  color: var(--warnung-text); }
.meldung.warnung::before { content: "!"; }
.meldung.fehler { border-color: var(--fehler); background: var(--fehler-fein);
  color: var(--fehler-text); }
.meldung.fehler::before { content: "⚠"; }

/* Die Marke an einer Zeile: kurz, rund, mit Bedeutung. */
.merkmal { display: inline-block; padding: 2px var(--a2); border-radius: var(--r-pille);
  font-size: .76rem; font-weight: 600; background: var(--flaeche-tief);
  color: var(--gedaempft); }
.merkmal.gut { background: var(--gut-fein); color: var(--gut-text); }
.merkmal.warnung { background: var(--warnung-fein); color: var(--warnung-text); }
.merkmal.fehler { background: var(--fehler-fein); color: var(--fehler-text); }

/* ================================================ 9b. Der Weg in Schritten

   **Ein Ablauf, der mehr als einen Schritt hat, zeigt, wo man steht.** Die Abrechnung
   läuft seit dem 19.09.2026 so (vier Schritte, Vorbild E2N), der Wachbericht seit dem
   17.10.2026 in zwei — Renés Ablauf: „Danach klickt der Schichtleiter auf weiter, um den
   Wachbericht weiter zu führen."

   **Der Schritt steht in der Adresse, nicht in einem Skript** — so arbeitet der
   Zurück-Knopf des Browsers, und ohne Skript geht es genauso. Hier liegt nur das
   Aussehen; die Reihenfolge ist Sache der Seite.

   Die Marke trägt die Hervorhebung: `--mandant` statt des Blaus, das in `dienstplan.css`
   stand — *eine Bauform, die alle Oberflächen laden, darf keine Farbe nennen, die nur
   eine davon kennt.* */
.schritte { display: flex; gap: 0; background: var(--grund); border: 1px solid var(--linie);
  border-radius: var(--r-klein); padding: 6px; margin-bottom: 18px; overflow-x: auto; }
.schritt { flex: 1; display: flex; align-items: center; gap: 10px; padding: 12px 16px;
  text-decoration: none; color: var(--gedaempft); border-radius: var(--r-klein);
  white-space: nowrap; position: relative; }
.schritt + .schritt::before { content: ""; position: absolute; left: -1px; top: 18px;
  bottom: 18px; width: 1px; background: var(--linie); }
.schritt .nummer { width: 26px; height: 26px; border-radius: 50%; background: var(--flaeche);
  color: var(--gedaempft); display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 13px; flex: 0 0 auto; }
.schritt .name { font-weight: 600; }
.schritt:hover { background: var(--flaeche); color: var(--text); }
.schritt.hier { background: var(--mandant-fein); color: var(--mandant); }
.schritt.hier .nummer { background: var(--mandant); color: #fff; }

/* ============================================================== 10. Raster

   **Ein bis zwei Spalten, nie vier** (Dashboard-Leitfaden: vier Spalten überfordern).
   Die Karten stapeln sich auf schmalen Geräten von selbst — `auto-fit` mit einer
   Mindestbreite, damit **niemals waagerecht gescrollt** werden muss. */
/* **Die Klasse heißt `kartenraster` und nicht `raster`** (berichtigt am 26.09.2026,
   Renés Fund: „wenn ich in den Wochenplan reingehe, ist die Seite rechts verrutscht —
   ist seit der Änderung der CSS"). `.raster` gibt es in `dienstplan.css` seit Wochen, und
   dort ist es die **Tabelle** des Wochenplans und der Bedarfsplanung. Diese Datei lädt
   zuerst, `dienstplan.css` überschreibt Rahmen und Breiten — aber **`display: grid`
   stand nur hier und blieb deshalb stehen**: Aus zwei Tabellen wurden Grids, und ihre
   Spalten liefen aus dem Bildschirm.

   **Ein Klassenname mit zwei Bedeutungen ist der Fehler**, nicht die Reihenfolge der
   Dateien. Eine Datei, die für alle neun Oberflächen gilt, darf keinen Namen belegen, den
   eine von ihnen schon anders benutzt. `tests/test_gestaltung.py` prüft das jetzt. */
/* **Höchstens zwei Karten nebeneinander** (09.10.2026, Renés Idee 21: „Keine 3 Karten
   nebeneinander").

   Der Kanon sagt seit dem 24.09.2026 „ein bis zwei Spalten, nie vier" — der **Code** sagte
   etwas anderes: `minmax(260px, 1fr)` ergibt auf den 1.080 Pixeln der Inhaltsspalte
   **vier** Karten. *Eine Regel, die im Text steht und im Code nicht, ist keine.* Jetzt
   stehen zwei, und unter 760 Pixeln eine.

   **Karten sind nicht Kacheln.** Eine Karte trägt Überschrift und Inhalt (Einstellungen,
   Abschnitte, Berichte) — davon liest niemand drei nebeneinander. Eine **Kachel** ist ein
   quadratisches Ziel mit Zeichen und Wort (Module, Mahlzeiten, Bereiche); sie bleibt eine
   Wand, und das ist Renés eigene Vorgabe vom 20.09.2026 („Icons oder sichtbare Bilder für
   das jeweilige Modul"). Die Wände heißen deshalb anders: `.modulkacheln`,
   `.wahlflaechen`, `.bereichswand`, `.dessertkacheln`. */
.kartenraster { display: grid; gap: var(--a4);
  grid-template-columns: repeat(2, minmax(0, 1fr)); }
.kartenraster.weit { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 760px) {
  .kartenraster, .kartenraster.weit { grid-template-columns: 1fr; }
}
/* Zwei Spalten mit fester Gewichtung: links die Arbeit, rechts die Auskunft. */
.zweispalt { display: grid; gap: var(--a5); grid-template-columns: 2fr 1fr; }
@media (max-width: 900px) { .zweispalt { grid-template-columns: 1fr; } }

/* **Ein Formular hat eine Obergrenze.** Über die ganze Breite eines 27-Zoll-Bildschirms
   ist es unbedienbar: Das Auge springt zwischen Beschriftung und Feld über 1.200 Pixel.
   Angewendet auf jede `.karte`, die ein Formular trägt — nicht als eigene Klasse, die
   jemand setzen müsste und dann vergisst. */
.karte > form, form.tafel { max-width: 720px; }
.karte > form.breit, form.tafel.breit { max-width: none; }

/* --- Erklärung hinter einem „i" ----------------------------------------------
   **Renés Wunsch vom 01.10.2026** zur Bestellübersicht: „Muss einfacher dargestellt
   werden. Wer wenig mit dem System Puls vertraut ist, sieht dies als zu unübersichtlich —
   ich möchte weniger Erklärtexte, mehr (i)."

   **Er hat recht, und das Problem ist nicht der Text, sondern seine Dauer.** Eine
   Begründung ist beim ersten Mal nötig und beim fünfzigsten Lärm — aber sie ganz
   wegzulassen hieße, eine Zahl ohne ihre Grundlage dastehen zu lassen. Das „i" löst
   genau das: **da, aber nicht im Weg** (dieselbe Überlegung wie „Zahlen statt Sätze" im
   Dashboard, 13.09.2026).

   **Drei Festlegungen:**

   * **`<details>`, kein Skript.** Was allein an einem Skript hängt, ist eine Falle.
   * **Die Überschrift bleibt sichtbar.** Im `<summary>` steht das Stichwort, nicht nur
     das Zeichen — ein nacktes „i" sagt nicht, worüber es spricht, und wird nicht
     angeklickt.
   * **Es ersetzt keinen Befund.** Eine Warnung („3 Messungen außerhalb der Grenze") steht
     weiter offen: Wer etwas tun muss, darf es nicht erst aufklappen. Hinter das „i"
     gehört, *warum* etwas so gerechnet wird — nicht, *dass* etwas klemmt. */
details.infotext { margin: var(--a2) 0; }
details.infotext > summary {
  display: inline-flex; align-items: center; gap: var(--a2);
  min-height: var(--hoehe-klein); padding: 0 var(--a2) 0 0;
  color: var(--gedaempft); font-size: 13px; cursor: pointer; list-style: none;
}
details.infotext > summary::-webkit-details-marker { display: none; }
/* Das Zeichen vor dem Stichwort — es trägt die Wiedererkennung, das Wort die Aussage. */
details.infotext > summary::before {
  content: "i"; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 19px; height: 19px; border-radius: 50%;
  border: 1px solid var(--linie); background: var(--flaeche);
  font-style: italic; font-weight: 700; font-size: 12px; line-height: 1;
}
details.infotext > summary:hover { color: var(--text); }
details.infotext > summary:hover::before { border-color: var(--mandant);
  color: var(--mandant); }
details.infotext[open] > summary::before { background: var(--mandant); color: #fff;
  border-color: var(--mandant); }
details.infotext > summary:focus-visible { outline: 2px solid var(--mandant);
  outline-offset: 2px; border-radius: var(--r-klein); }
details.infotext > div {
  max-width: 62ch; margin: var(--a2) 0 0; padding: var(--a3) var(--a4);
  border-inline-start: 3px solid var(--linie);
  color: var(--gedaempft); font-size: 13px; line-height: 1.55;
}
details.infotext > div p { margin: 0 0 var(--a2); }
details.infotext > div p:last-child { margin-bottom: 0; }

/* --------------------------------------------------- Die Symbolschau (09.10.2026) */
/* Nur auf der Musterseite `/gestaltung`: jedes Symbol einmal **jetzt** und einmal, wie es
   **vorher** aussah. Renés Frage war „welche Icons verwendest du?" — die Antwort ist eine
   Ansicht, keine Beschreibung. Das blasse Zeichen darunter ist das alte; es steht
   kleiner, damit die Reihe nicht zweimal dasselbe Gewicht hat. */
.symbolschau { display: grid; gap: var(--a4, 16px);
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); margin: var(--a4, 16px) 0; }
.symbolprobe { margin: 0; text-align: center; border: 1px solid var(--rand, #E5E7EB);
  border-radius: var(--r, 10px); padding: 10px 6px; background: #fff; }
/* **Eigene Namen, keine geborgten** — `.jetzt` und `.vorher` hätten gepasst und gehören
   in `dienstplan.css` und `mypuls.css` schon etwas anderem: *Eine Datei, die für alle
   Oberflächen gilt, darf keinen Namen belegen, den eine von ihnen anders benutzt* (die
   Lehre von `.raster` am 26.09.2026). Der Testlauf hat es sofort gesagt. */
.symbolprobe .symbolneu { display: block; color: var(--mandant, #4A5568); }
.symbolprobe .symbolalt { display: block; margin-top: 6px; opacity: .45; }
.symbolprobe .symbolalt svg { width: 20px; height: 20px; stroke: currentColor; fill: none;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.symbolschau.app .symbolneu svg, .symbolschau.app .symbolalt svg { width: 26px;
  height: 26px; stroke: currentColor; fill: none; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round; }
.symbolschau.app .symbolalt svg { width: 20px; height: 20px; }
.symbolprobe figcaption { font-size: 12px; color: var(--gedaempft, #6B7280);
  margin-top: 6px; }

/* **Das Unterschriftsfeld** — seit dem 16.10.2026 im Kanon statt in zwei Moduldateien.
   Es stand wortgleich in `dienstplan.css` (14.09.2026, Darlehen und Arbeitsvertrag) und
   in `mypuls.css`, mit zwei verschiedenen Höhen (160 und 180). Mit dem **Wachbericht**
   kam die dritte Oberfläche dazu — und genau dafür gibt es diese Datei: *Dieselbe Regel
   in drei Dateien ist dreimal dieselbe Entscheidung, und zwei davon laufen weg.*

   Flach und breit wie eine Zeile auf Papier, mit einer Linie darin — ohne sie schwebt
   die Schrift. `touch-action: none` hält die Seite still, während der Finger zeichnet.
   Die Höhe folgt dem Gerät: am Tablet und in der App großzügiger als am Schreibtisch. */
.unterschriftsfeld { position: relative; background: #fff; border: 1px solid var(--linie);
  border-radius: var(--radius); overflow: hidden; }
.unterschriftsfeld canvas { display: block; width: 100%; height: 160px;
  touch-action: none; cursor: crosshair; }
.unterschriftslinie { position: absolute; left: 24px; right: 24px; bottom: 34px;
  border-bottom: 1px dashed var(--linie); pointer-events: none; }
.unterschriftszeile { display: flex; align-items: center; gap: 12px; margin-top: 8px; }

/* **Der Hinweis, wenn das Feld nicht lebt** (14.09.2026). Er steht in der Vorlage und
   verschwindet, sobald `static/unterschrift.js` gelaufen ist (Klasse `bereit`). Ohne ihn
   sähe ein Feld ohne Skript genauso aus wie eines mit — und wer darauf zeichnet, hielte
   sich selbst für den Fehler. */
.unterschriftsfeld .ohne-skript { position: absolute; inset: 0; display: flex;
  align-items: center; justify-content: center; text-align: center; padding: 0 20px;
  font-size: 13px; line-height: 1.45; color: var(--gedaempft); background: #FFF9EE; }
.unterschriftsfeld.bereit .ohne-skript { display: none; }
