/* ==========================================================================
   Tokens, Grundelemente, Bootstrap-Anpassungen, Datenschutz-Blase
   --------------------------------------------------------------------------
   Der Anfang von allem: die Design-Tokens im :root, auf die jede andere
   Datei zugreift. Wer eine Farbe, einen Radius oder eine Höhe ändert,
   ändert sie HIER und nirgends sonst.

   TEIL 1 VON 9 von assets/css/style.css.

   ACHTUNG, REIHENFOLGE: CSS ist kaskadierend. Diese Dateien werden in
   includes/header.php in genau dieser Nummerierung eingebunden, und die
   Nummer im Dateinamen IST die Reihenfolge. Wer eine Datei dazwischen
   schiebt oder die Einbindung umsortiert, ändert stillschweigend, welche
   Regel bei gleicher Spezifität gewinnt.
   ========================================================================== */

/* ==========================================================================
   Design-Tokens – Look „B" (Arbeitsfläche):
   flach, dicht, kühl-neutral. Marke bleibt: Akzent-Rot, Blaugrau, Grün/Orange.
   ========================================================================== */
:root {
    --brand-accent: #f03c1e;
    --brand-accent-dark: #c92d13;
    /* Der Grund der Arbeitsfläche. Er war mit #f6f8fa fast weiß – die weißen
       Karten darauf hatten nichts, wovon sie sich abheben konnten, und die
       ganze Seite stand auf einer Ebene. Seit dem 21.08.2026 ist er eine
       Stufe tiefer und trägt den Blaustich des Hauses: dasselbe Hellgrau,
       nur als Grund erkennbar. */
    --brand-bg: #eef2f7;
    --brand-text: #1a2430;
    --brand-chip-bg: #fdeeeb;
    --brand-border: #dde4ec;

    /* Markenzeichen der Kopfleiste. Ohne gewählte Gesellschaft ist das der
       blasse Akzentton mit farbigem Zeichen; Häuser mit heller Signalfarbe
       (HUK-COBURG, VHV, R+V) füllen die Fläche stattdessen mit ihrem Gelb –
       die Schriftfarbe rechnet PHP dazu passend aus. */
    --brand-signal: var(--brand-chip-bg);
    --brand-signal-ink: var(--brand-accent);

    --brand-quiet: #66748a;       /* Sekundärtext */
    /* Tertiärtext – die leise dritte Stufe: Fußnoten unter den Kennzahlen,
       die blasse Null einer Kachel, in der nichts liegt. Sie stand auf
       #9aa6b6 und lag damit auf Weiß bei 2,5 : 1; selbst für eine Zahl von
       25 Pixeln sind 3 : 1 die Grenze, und die halbe Startseite besteht aus
       diesen Zahlen. Zwei Stufen tiefer: 3,3 : 1. Leise bleibt sie trotzdem –
       der Sekundärtext darüber (--brand-quiet) liegt bei 4,7 : 1, der
       Abstand zwischen den Stufen ist derselbe wie vorher. */
    --brand-faint: #828f9f;       /* Tertiärtext */
    --brand-surface: #ffffff;

    /* Das Graublau des Hauses – der Träger: Balken, Punkte, Marken.
       SEIT DEM 22.08.2026 TRÄGT ES KEINE BEDIENELEMENTE MEHR. Knöpfe,
       Segmentschalter, Wahl-Chips, Kästchen und die ausgewählte Zeile stehen
       im hellen Blau der Werbeseite (--btn-leucht / --btn-leucht-dark /
       --btn-leucht-tief, die Tönung --blau-hell darunter) – dieselbe Farbe,
       die der gefüllte Knopf seit demselben Tag trägt. Vorher standen beide
       Familien nebeneinander auf einem Bildschirm: der Knopf leuchtend, der
       Reiter daneben blaugrau, und der Unterschied bedeutete nichts. Was
       ANGEFASST wird, ist jetzt hellblau; was nur BERICHTET (Fortschritts-
       balken, Diagrammsäulen, der Punkt am klingelnden Telefon, die Marke
       „Firma"), bleibt blaugrau.
       Es stand bis zum 21.08.2026 auf #7691a0. Das ist der richtige Ton für
       eine FLÄCHE, aber weiße Schrift lag darauf bei 3,4 : 1 und damit unter
       der Grenze von 4,5 : 1 – jeder gefüllte Knopf der Anwendung war zu
       blass beschriftet. Derselbe Ton, zwei Stufen tiefer: 5,5 : 1.
       Die helle Seite der Familie steht darunter (--btn-blue-bg-light), das
       alte #7691a0 lebt dort als Rand weiter. */
    --btn-blue: #4b6c8b;
    --btn-blue-dark: #3d5b78;
    /* Das dunkle Blaugrau der Überschriften (der Titel jedes Seitenkopfs,
       .cal-title in 02-bausteine.css). Es ist das Blaugrau des Hauses, nur
       tief genug für Schrift: --btn-blue trägt Flächen und Knöpfe und läge
       als Wort auf dem Grund bei 2,9 : 1, dieser Ton bei 6,9 : 1. Derselbe
       Wert wie --marke-tief auf der Werbeseite, wo ihn das Zeichen trägt.
       Am 21.08.2026 stand hier kurz das helle Blau der Werbeseite; auf
       Überschriftengröße gehört es dorthin, wo es herkommt, nicht auf jede
       Seite der Arbeitsfläche. */
    --brand-titel: #33586e;
    --btn-blue-bg-light: #eaf0f6;
    --btn-blue-border-light: #c6d5e2;

    /* Das helle Blau der Werbeseite (dort --leucht in agenturorbit/webseite/
       assets/site.css). Seit dem 21.08.2026 trägt es zwei Dinge in der
       Arbeitsfläche: die Zeichen und den Offen-Ton der Kachelreihe auf der
       Startseite (assets/css/style/04-arbeitsflaechen.css) und dieselbe
       Sprache samt Knöpfen in der Handy-App (assets/css/mobil.css). Gefüllt
       wird wie auf der Werbeseite im Verlauf nach --btn-leucht-dark – weiße
       Schrift auf dem reinen Ton läge bei 2,8 : 1, auf dem tieferen bei
       4,1 : 1. */
    --btn-leucht: #00a2ef;
    --btn-leucht-dark: #0384c3;
    /* Eine dritte Stufe, seit dem 21.08.2026: die Schrift auf einer hellen
       Tönung des Leuchtblaus (die Knöpfe der Handy-App). --btn-leucht-dark
       reicht dafür nicht – er liegt auf der Tönung bei 3,8 : 1, genug für
       eine 1,5rem-Zahl, aber nicht für eine Beschriftung von 0,85rem. Dieser
       Ton liegt bei 5,3 : 1 und damit auch für kleine Schrift über 4,5 : 1. */
    --btn-leucht-tief: #026ca0;

    /* ----------------------------------------------------------------------
       Das helle Blau als FLÄCHE – die dritte der Hausfarben neben Hellgrau
       und Graublau. Bis zum 21.08.2026 gab es sie nicht: Wer eine blaue
       Tönung brauchte, mischte sie an Ort und Stelle (color-mix mit 9 %, mit
       18 %, mit 30 %), und nebeneinander waren das ein Dutzend Blautöne, die
       alle „hellblau" sein wollten. Drei Stufen reichen für die ganze
       Anwendung:

         --blau-hauch  der Anflug: Kartenköpfe, Tabellenköpfe, ruhige Bänder
         --blau-hell   die Tönung: ausgewählt, offen, unter dem Zeiger
         --blau-rand   die Kante dazu

       Sie hängen am Leuchtblau, NICHT an der Gesellschaft: Das Haus bleibt
       blau, auch wenn der Kunde rot oder gelb ist. Wer die Gesellschaft am
       Bildschirm erkennen soll, erkennt sie an den Bedienelementen
       (--brand-accent, --btn-blue) – nicht am Papier.
       ---------------------------------------------------------------------- */
    --blau-hauch: #f1f7fc;
    --blau-hell: #e2f1fb;
    --blau-rand: #bcdcf1;

    /* ----------------------------------------------------------------------
       Die dunkle Bühne der öffentlichen Seiten – Anmeldung, Terminbuchung,
       geteilter Kalender, Landingpages, Formularbogen. Jede dieser Seiten
       hatte ihren eigenen Satz: --lg-ink, --tb-ink, --kg-ink und --lp-ink
       trugen denselben Wert unter vier Namen, und der weiche Text darauf lag
       fünfmal knapp daneben (#8299a9 / #8ea2b1 / #8ea3b1 / #7f95a5 /
       #b7c6d1). Nebeneinander sieht man diese Unterschiede nie – man sieht
       nur, dass die Anmeldung und die Terminbuchung nicht dieselbe Seite
       sind, obwohl sie es sein sollen.

       Die Seitenblätter behalten ihre eigenen Namen (--lg-*, --tb-*, …),
       weil sie überall im Blatt stehen; sie zeigen nur alle hierher.
       ---------------------------------------------------------------------- */
    --stage-ink: #0d1a24;      /* Grund der Bühne */
    --stage-ink-2: #142633;    /* Verlaufspartner darüber */
    --stage-soft: #8ea2b1;     /* leiser Text auf der Bühne */
    --stage-line: rgba(255, 255, 255, .12);   /* Linie auf der Bühne */

    /* Die zweite Runde derselben Sache (23.08.2026). --stage-soft hatte 2026
       die fünf Fassungen des LEISEN Tons zusammengeführt; daneben stand
       unbemerkt der FLIESSTEXT auf der Bühne – der Absatz, den man wirklich
       liest – noch einmal viermal: #c3d0d9, #cfdae1, #d5e0e7, #c6d3db. Vier
       Töne, die alle „hell auf dunkel" sein wollten, keiner davon
       aufgeschrieben. Zwei Stufen reichen für jede dunkle Fläche:

         --stage-text  der Absatz (11,6 : 1 auf --stage-ink)
         --stage-soft  die Fußnote daneben (5,4 : 1)

       Genauso der Lichtpunkt und die Tiefe des Bühnenverlaufs: Sie standen
       Wort für Wort gleich in login.css und landingpage.css, also an zwei
       Stellen, von denen man beim Ändern immer eine vergisst. */
    --stage-text: #c6d3db;     /* Fließtext auf der Bühne */
    --stage-hell: #1b3040;     /* Lichtpunkt des Bühnenverlaufs (oben links) */
    --stage-tief: #0a151d;     /* Tiefe des Verlaufs (unten rechts) */
    --stage-fuss: #08131b;     /* der Fuß unter der Bühne, eine Stufe tiefer */
    --stage-fuss-2: #101f2b;   /* die Fläche darin (Anschrift, Karte) */
    /* Das Grün der Bestätigung AUF der Bühne. --btn-green (#1e7e34) ist der
       Ton für Papier und läge auf dem dunklen Grund bei 2,1 : 1; dieser bei
       9,6 : 1. Beide Male dasselbe Grün, nur für den jeweiligen Untergrund. */
    --stage-gruen: #7ddc9b;

    /* Der Fließtext der öffentlichen Seiten AUF PAPIER. Die Arbeitsfläche
       kennt drei Stufen (--brand-text / --brand-quiet / --brand-faint); die
       Landingpage setzt ihre Absätze eine Spur dunkler als --brand-quiet,
       weil sie in Fließtextgröße gelesen und nicht überflogen werden. Auch
       dieser Ton stand viermal knapp daneben: #46596b, #4a5d6e, #52657a,
       #5b6e80. Auf Weiß 6,4 : 1. */
    --brand-fliess: #4e6173;

    /* Der Radius der öffentlichen Seiten. Er stand als --lp-radius auf 16px
       und als --tb-radius / --kg-radius auf 18px – dieselbe Karte, je nach
       Seite anders gerundet. Die Arbeitsfläche bleibt bei --r-card (12px):
       dicht und ruhig; die Kundenseiten dürfen weicher sein, aber alle
       gleich. */
    --oe-radius: 18px;
    --oe-radius-sm: 10px;

    --btn-gray-bg: #eef2f6;
    --btn-gray-border: #dde4ec;
    --btn-gray-bg-hover: #e3eaf1;
    --btn-gray-border-hover: #ccd6e0;

    --btn-red-bg-light: #fdeeeb;
    --btn-red-border-light: #f6d5cf;
    --btn-red-text: #b3261e;

    /* Die Zählblase an den Filtern (.ml-count in 04-arbeitsflaechen.css).
       Dieselbe Familie wie die drei Werte darüber, nur eine Spur kräftiger:
       Die Blase ist 16 Pixel klein und trägt eine Zahl in --fs-2, da reicht
       der blasse Ton nicht. Sie standen bis zum 22.08.2026 als feste Werte
       im Blatt und wären damit die einzige Stelle gewesen, die der
       Dunkelmodus nicht erreicht. */
    --zahl-blase-bg: #f5d3cf;
    --zahl-blase-ink: #8f2318;

    /* ----------------------------------------------------------------------
       DAS ZIFFERBLATT DER KOPFLEISTE (includes/uhr.php). Die Uhr neben der
       Marke ist seit dem 25.08.2026 eine gezeichnete Uhr mit Gehäuse, Blatt
       und zwei Zeigern – kein Strichzeichen mehr. Ein Gegenstand also, und
       Gegenstände haben eigene Farben.

       WARUM SIE TROTZDEM AN TOKENS HÄNGEN und nicht wie beim Wetter daneben
       festgeschrieben sind: Eine Wolke ist eine Wolke, aber ein weißes
       Zifferblatt wäre im Dunkelmodus der hellste Fleck der ganzen Seite –
       22 Pixel Scheinwerfer neben der Marke. Die dunkle Fassung ist deshalb
       eine Uhr MIT SCHWARZEM BLATT und hellen Zeigern, wie es sie am
       Handgelenk auch gibt (farbschemaDunkelPalette()).
       ---------------------------------------------------------------------- */
    --uhr-rand-hell: #e3ebf4;   /* Lichtkante des Gehäuses (oben) */
    --uhr-rand: #a5b7cb;        /* Gehäuse unten */
    --uhr-blatt: #ffffff;       /* das Blatt oben */
    --uhr-blatt-2: #e8eff7;     /* das Blatt unten */
    --uhr-strich: #8ba0b5;      /* Stundenstriche und Punkte */
    --uhr-zeiger: #33475c;      /* die beiden Zeiger und die Achse */

    /* ----------------------------------------------------------------------
       Die Schrift auf einer GEFÜLLTEN MARKENFLÄCHE – die heutige Ziffer im
       Kalender, das Abzeichen am Assistentenschritt, der aktive Lead-Stand,
       die Marke des Testbands.

       Sie stand an zwölf Stellen als festes `#fff`, und im Hellen ist das
       auch richtig: Akzent, Träger, Grün und Orange sind dort dunkle Töne.
       Im Dunkelmodus (22.08.2026) kehrt sich das um – dieselben Farben werden
       hell, damit man sie auf dem dunklen Grund überhaupt sieht, und weiße
       Schrift darauf wäre Weiß auf Hellgrün.

       NICHT für Flächen im Leuchtblau (--btn-leucht-dark): Das ändert sich
       zwischen den beiden Fassungen nicht, dort bleibt Weiß richtig. Wer das
       verwechselt, macht den gefüllten Knopf im Hellen unlesbar.
       ---------------------------------------------------------------------- */
    --auf-marke: #ffffff;

    --btn-green: #1e7e34;
    --btn-green-dark: #1a6b2c;
    --btn-green-bg-light: #e6f4ea;
    --btn-green-border-light: #c3e6cc;
    /* Die zwei Kanten der WhatsApp-Zeile auf den öffentlichen Formularen:
       unter dem Zeiger und angehakt. Sie standen als #b6ddc2 / #9ed3b0
       gleichlautend in termin.css UND in landingpage.css – derselbe Kasten,
       zwei Dateien, und beim Nachziehen erwischt man immer nur eine. */
    --btn-green-border-hover: #b6ddc2;
    --btn-green-border-an: #9ed3b0;
    /* Das grelle Grün. --btn-green ist auf Knöpfen und Flächen richtig – dunkel
       genug, dass weiße Schrift darauf steht. Als 8-Pixel-Punkt auf hellem
       Grund geht es unter; dort trägt die Farbe die ganze Aussage und muss
       leuchten. Nur für Signalpunkte, nicht für Flächen: Weiße Schrift auf
       diesem Ton wäre nicht mehr zu lesen. */
    --btn-green-signal: #16c34a;

    --btn-orange-bg-light: #fdf1e3;
    --btn-orange-text: #b3620a;
    /* Rot, Blaugrau und Grün haben ihren hellen Rand von Anfang an; Orange
       fehlte er. Deshalb stand er zweimal von Hand im Blatt – als #f0dcc2 am
       Hinweiskasten und als #f0d9b8 am Lead-Stand, also zwei Werte für
       dieselbe Rolle. Dazu der gefüllte Ton für Balken und Punkte: Grün und
       Blaugrau tragen dort ihre Familienfarbe, Orange hatte keine.
       NICHT für weiße Schrift – dafür ist er zu hell, dafür steht
       --btn-orange-text. */
    --btn-orange-border-light: #f0dcc2;
    --btn-orange: #d9a24e;

    /* Der Kartenkopf trägt den Anflug von Blau, nicht das Grau des Grundes.
       Vorher war er derselbe Wert wie --brand-bg: Auf dem Grund der Seite war
       der Kopf einer Karte deshalb unsichtbar, und die Karte begann optisch
       erst bei ihrem Rumpf. */
    --card-header-bg: #f2f6fa;
    --card-header-border: #dde4ec;

    --brand-line-strong: #c8d3de;
    --brand-row: #f4f7fa;         /* Zebra/Hover-Ton für Zeilen */

    /* ----------------------------------------------------------------------
       Abstandsleiter. Vorher stand an jeder Stelle eine eigene rem-Zahl
       (0.4 / 0.55 / 0.6 / 0.7 / 0.75 / 0.8 / 0.85 / 0.9 …) – nebeneinander
       sieht das nicht wie eine Entscheidung aus, sondern wie Zufall. Acht
       Stufen reichen für die ganze Anwendung; wer eine neunte braucht,
       braucht in Wahrheit eine der acht.
       ---------------------------------------------------------------------- */
    --sp-1: 0.25rem;    /*  4px  – Fuge zwischen Zeichen und Wort */
    --sp-2: 0.375rem;   /*  6px  – Chips, Knöpfe in einer Reihe */
    --sp-3: 0.5rem;     /*  8px  – enge Innenkante */
    --sp-4: 0.75rem;    /* 12px  – Standardfuge zwischen Bausteinen */
    --sp-5: 1rem;       /* 16px  – Kartenpolster, Rasterfuge */
    --sp-6: 1.25rem;    /* 20px  – Abstand zwischen Abschnitten */
    --sp-7: 1.5rem;     /* 24px  – Abstand zwischen Blöcken */
    --sp-8: 2rem;       /* 32px  – Seitenrhythmus */

    /* ----------------------------------------------------------------------
       Schriftleiter. Dasselbe Argument wie bei der Abstandsleiter darüber –
       nur stand es beim Schriftgrad noch schlimmer: In der Anwendung lagen
       VIERUNDFÜNFZIG verschiedene Grade nebeneinander (0.55 / 0.56 / 0.57 /
       0.58 / 0.6 / 0.62 / 0.63 / 0.64 / 0.66 / 0.68 / 0.7 / 0.705 / 0.72 …).
       Zwei Werte, die 0,3 Pixel auseinanderliegen, sieht niemand als
       Unterschied – man sieht nur, dass zwei Beschriftungen nebeneinander
       nicht gleich groß sind.

       Elf Stufen, jede rund 7 % über der vorigen, --fs-7 ist die Grundschrift
       des body. Wer eine zwölfte braucht, braucht in Wahrheit eine der elf.
       ---------------------------------------------------------------------- */
    --fs-1: 0.6rem;      /*  9,6px – Mikroschrift in Kalenderzellen */
    --fs-2: 0.65rem;     /* 10,4px – Zeichenkürzel, Zählwerke */
    --fs-3: 0.7rem;      /* 11,2px – Mikrolabel in Versalien, Chips */
    --fs-4: 0.75rem;     /* 12,0px – Nebentext in Listen */
    --fs-5: 0.8rem;      /* 12,8px – Bedienelemente, Tabellen */
    --fs-6: 0.85rem;     /* 13,6px – Kartenköpfe, Knöpfe */
    --fs-7: 0.9375rem;   /* 15,0px – Grundschrift (body) */
    --fs-8: 1.05rem;     /* 16,8px – hervorgehobene Zeile, große Zahl */
    --fs-9: 1.2rem;      /* 19,2px – h3, Kachelzahlen */
    --fs-10: 1.3rem;     /* 20,8px – h2, Titel im Seitenkopf */
    --fs-11: 1.6rem;     /* 25,6px – h1 */
    --fs-12: 1.8rem;     /* 28,8px – die Bühnenzeile der öffentlichen Seiten */

    /* Form/Radius/Dichte (Look B) */
    --r-card: 12px;
    --r-ctl: 8px;
    --r-sm: 6px;
    --r-pill: 999px;
    --h-ctl: 34px;      /* Eingaben, Knöpfe, Segmente, Seitenkopf */
    --h-ctl-sm: 28px;   /* Knöpfe im Kartenkopf und in Zeilen */
    /* Die große Stufe – der eine Knopf, um den es auf einer Seite geht, und
       die Felder der öffentlichen Seiten. Sie stand viermal von Hand da und
       viermal anders: 42px am .btn-lg, 44px am Anmeldefeld, 46px am
       Anmeldeknopf und an der Uhrzeit der Landingpage. 44px, weil das das
       Maß ist, das ein Finger auf dem Handy sicher trifft. */
    --h-ctl-lg: 44px;

    /* ----------------------------------------------------------------------
       Erhebung – EINE Leiter für die ganze Anwendung.
       Bis zum 10.08.2026 gab es fünf davon: --cal-sh-*, --bd-sh-*, --tk-sh-*,
       --ml-sh-1, --bk-sh-*. Ihre Werte lagen um ein Hundertstel Deckkraft
       auseinander – nicht sichtbar nebeneinander, aber jede Änderung musste
       an fünf Stellen nachgezogen werden, und genau das ist nie passiert.
       Die alten Namen standen danach noch eine Weile als Verweise hier; am
       23.08.2026 sind sie gefallen. Von sieben war nur noch die Hälfte in
       Gebrauch, und ein Name, der nur auf einen anderen zeigt, kostet beim
       Lesen genauso viel wie ein echter.

         --sh-1  ruhende Fläche, die sich vom Grund abheben soll (Karte)
         --sh-2  Angefasstes: Hover einer Karte, klebende Kopfzeile
         --sh-3  Bewegtes: gezogene Karte, aufgeschlagener Dialog
       ---------------------------------------------------------------------- */
    /* Der Schatten ist blaugrau, nicht schwarz: Ein neutral grauer Schatten
       auf dem kühlen Grund sieht schmutzig aus. Und er ist seit dem
       21.08.2026 einen Hauch kräftiger – zusammen mit dem tieferen Grund
       (--brand-bg) steht eine Karte damit erkennbar auf der Fläche, statt in
       ihr zu liegen. */
    --sh-1: 0 1px 2px rgba(24, 44, 66, .05), 0 1px 3px rgba(24, 44, 66, .06);
    --sh-2: 0 2px 4px rgba(24, 44, 66, .06), 0 8px 20px rgba(24, 44, 66, .08);
    --sh-3: 0 4px 10px rgba(24, 44, 66, .10), 0 14px 32px rgba(24, 44, 66, .12);
    --shadow-pop: 0 8px 24px rgba(24, 44, 66, 0.13);

    /* Der Kurzhinweis an den Knöpfen der Kopfleiste (siehe weiter unten,
       „Kurzhinweis an den Knöpfen der Kopfleiste"). Er ist ein umgekehrtes
       Kästchen: dunkle Fläche, helle Schrift.
       BEIDE HÄLFTEN SIND TOKENS, und das ist keine Förmlichkeit. Vorher stand
       hier `background: var(--brand-text)` mit fest verdrahtetem `color: #fff`
       – im Dunkeln ist --brand-text fast weiß, und der Hinweis war weiß auf
       weiß. Genau der Fehler, vor dem der Kopf von includes/farbschema.php
       warnt: nie die eine Hälfte eines Farbpaares an ein Token hängen und die
       andere festschreiben. Die dunkle Fassung der drei Werte steht in
       farbschemaDunkelPalette(); dort ist die Fläche nicht die Umkehrung,
       sondern ein angehobenes Neutral – ein weißes Kästchen auf dunkler Seite
       blendet, und ein Hinweis soll man lesen, nicht abwehren.
       Der Rand ist im Hellen durchsichtig: Dort trennt der Schatten. */
    --tip-bg: var(--brand-text);
    --tip-ink: #ffffff;
    --tip-rand: transparent;

    /* Bewegung. Die eingebauten CSS-Kurven sind zu weich – diese beiden
       greifen sofort und kommen ruhig zum Stehen. ease-out für alles, was
       erscheint oder auf einen Druck antwortet; ease-in-out für Bewegung
       auf der Fläche. ease-in gibt es bewusst nicht: es beginnt langsam,
       und genau am Anfang schaut der Nutzer hin.

       Dazu drei Dauern. Vorher standen im Blatt 0.12s, 0.14s, 0.15s, 0.18s,
       0.2s, 0.28s und .45s nebeneinander – der Unterschied zwischen 0.12 und
       0.15 ist nicht zu sehen, wohl aber, dass zwei benachbarte Elemente
       verschieden schnell antworten. */
    --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
    --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
    --t-fast: 120ms;    /* Farbwechsel am Zeiger */
    --t-base: 180ms;    /* Erscheinen, Aufklappen, Heben */
    --t-slow: 280ms;    /* Umbau der Fläche (Spalte ein-/ausklappen) */

    /* Fokus. Eine Fassung für die ganze Anwendung: Eingaben tragen sie als
       Ring im Rahmen, alles andere als Umriss außen herum.

       Der Ring trägt das Leuchtblau des Hauses und NICHT den Träger der
       Gesellschaft: Wo der Finger gerade steht, ist eine Auskunft der
       Anwendung an ihren Benutzer – sie soll überall gleich aussehen und
       nicht bei jedem Kunden eine andere Farbe haben. Beim roten Haus wäre
       der Ring sonst rot und damit von einer Fehlermeldung nicht zu
       unterscheiden. */
    --focus-col: var(--btn-leucht-dark);
    --focus-ring: 0 0 0 3px rgba(0, 162, 239, 0.25);

    /* Marken der Arbeitsfläche. Sie hießen einmal nach dem Kalender, weil
       Seitenkopf und Segmentschalter dort entstanden sind – benutzt werden
       sie inzwischen auf jeder Seite. Deshalb stehen sie hier und nicht
       mehr auf .cal-page. */
    --cal-line: var(--brand-border);
    --cal-ink: var(--brand-text);
    --cal-quiet: var(--brand-quiet);
    --cal-today: var(--brand-accent);
    --cal-paper: #ffffff;
    /* Samstag und Sonntag. Der Ton stand bis zum 22.08.2026 auf #f9fafc –
       einem NEUTRALEN Grau aus der Farbwelt vor Look B, das auf dem
       blaustichigen Grund des Hauses als leicht vergilbt gelesen wurde. Jetzt
       derselbe Wert wie --brand-row, der ruhige Zeilenton der ganzen
       Anwendung: dasselbe Blau wie überall, nur ganz leise. Wer ihn tiefer
       setzt, muss den Wasch unter dem Zeiger (--blau-hell am .cal-cell)
       mitziehen – zwischen beiden liegen sonst keine 2 ΔE, und das Überfahren
       einer Zelle antwortet nicht mehr sichtbar. */
    --cal-weekend: #f4f7fa;

    /* ---- Die acht Farbtöne des Hauses und was auf ihnen steht ------------
       Die Töne selbst stehen in hausFarbtoene() (includes/functions/
       oberflaeche.php) – Kalenderfarben, importierte Quellen, Spalten des
       Boards. Sie sind FESTE WERTE und wechseln mit der Fassung nicht: Ein
       Kalender, der „Rosé" heißt, ist im Dunkeln derselbe Rosé, sonst zeigte
       die Auswahlreihe eine andere Farbe als die Fläche.

       DARAUS FOLGT DIE TINTE. Weil die Fläche fest ist, muss ihr Gegenstück
       es auch sein – „entweder beide Werte fest oder beide aus der Palette",
       siehe den Kopf von includes/farbschema.php. --auf-hausfarbe ist der
       feste Partner: dieselbe dunkle Tinte, die contrastColor() für alle
       acht Töne ausrechnet und die renderCalEvent() jedem Termin als
       --ev-ink mitgibt (calendar.php). Sie steht hier als Name, damit man
       im Board nicht wieder --brand-text hinschreibt – genau das war der
       Fehler: Im Dunkeln wurde daraus fast weiße Schrift auf hellem Pastell,
       und die Spaltennamen waren weg.

       ES GIBT KEINE DUNKLE FASSUNG DIESES TOKENS, und das ist Absicht.
       farbschemaDunkelPalette() lässt es bewusst stehen; wer es dort
       hineinschreibt, macht den Fehler von vorn.

       WAS FÜR DIE TINTE GILT, GILT FÜR DEN GANZEN FARBIGEN KOPF: Er ist in
       beiden Fassungen dieselbe helle Fläche, also gilt IN ihm die helle
       Sprache – dunkle Schrift, dunkle Marken, ein weißes Schreibfeld. Die
       Fassung der Seite hört an seiner Kante auf. */
    --auf-hausfarbe: #1a2430;
    /* Der Anteil des Tons an der Spaltenfläche. Im Hellen sind 26 % ein
       Hauch auf Weiß; dieselben 26 % auf dunklem Grund ergäben eine milchig
       aufgehellte Fläche – ein Pastell hat auf dunklem Grund keine zarte
       Fassung, es hellt auf. Im Dunkeln deshalb 8 %: eine getönte dunkle
       Fläche. Die Farbe der Spalte trägt ohnehin der Kopf, nicht sie. */
    --bd-tint: 26%;
    /* ---- Aufhellen statt einfärben ---------------------------------------
       Kein eigener Ton, sondern eine Aufhellung dessen, was darunter liegt.
       Das ist die Antwort für alles RANDLOSE, das erst beim Anfassen zu einem
       Bauteil wird: der Kopf einer Board-Spalte ohne Farbe, das Feld „Karte
       hinzufügen", die Zahlenfelder des Umsatzrasters unter dem Zeiger.

       WARUM NICHT --brand-surface, was dort überall stand: Im Hellen ist die
       Kartenfläche Weiß und hebt sich von jedem Zeilenton ab – im Dunkeln IST
       sie der Zeilenton (1,05 : 1). Ein Feld, das mit ihr antwortet,
       antwortet dort also gar nicht. Ein Schleier kennt dieses Problem nicht:
       Er hellt auf, was immer unter ihm liegt.

       Im Hellen 55 % Weiß, im Dunkeln 10 %. Dieselben 55 % ergäben dort eine
       fast weiße Fläche, auf der die helle Schrift verschwände.
       NICHT ZU VERWECHSELN mit einer Fläche in einer Hausfarbe: Die trägt
       einen festen Ton und damit die feste Tinte (--auf-hausfarbe). */
    --schleier: rgba(255, 255, 255, .55);
    /* Die leise Tönung AUF einer solchen Fläche: die Zählblase am Spaltenkopf,
       der Spaltenname beim Überfahren. Im Hellen dunkelt sie, im Dunkeln
       hellt sie auf – und dort eine Stufe kräftiger als der Schleier, sonst
       läge sie auf ihm und wäre nicht mehr zu sehen. */
    --schleier-ton: rgba(26, 36, 48, .07);

    /* Die Textmarkierung – siehe ::selection weiter unten. */
    --auswahl-bg: #bcdcf1;
    --auswahl-ink: #12283a;

    /* Die alten, modulweise erfundenen Schattennamen. Sie stehen hier, damit
       die Blätter 03–09 unverändert weiterlaufen – aber sie zeigen jetzt alle
       auf dieselben drei Stufen. Wer neu baut, schreibt --sh-1/2/3. */
    --cal-ease: var(--ease-out);
}

body {
    background-color: var(--brand-bg);
    color: var(--brand-text);
    font-family: 'Plus Jakarta Sans', 'IBM Plex Sans', sans-serif;
    font-size: var(--fs-7);
    line-height: 1.5;
    /* Auf Bildschirmen mit hoher Punktdichte rechnet macOS die Schrift sonst
       fetter, als sie gezeichnet ist – die Mikrolabels wirken dann verschmiert.
       Beides zusammen macht die dichte Oberfläche merklich sauberer. */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6 {
    font-family: 'Plus Jakarta Sans', sans-serif;
    font-weight: 700;
    letter-spacing: -0.015em;
    /* Überschriften bleiben in der Zeile stehen; ohne das rutscht ein
       einzelnes Wort in eine zweite Zeile, sobald die Karte schmaler wird. */
    text-wrap: balance;
}
h1, .h1 { font-size: var(--fs-11); }
h2, .h2 { font-size: var(--fs-10); }
h3, .h3 { font-size: var(--fs-9); }
h4, .h4 { font-size: var(--fs-8); }
h5, .h5 { font-size: var(--fs-7); }
h6, .h6 { font-size: var(--fs-6); }

/* ==========================================================================
   Fokus – eine Fassung für die ganze Anwendung
   --------------------------------------------------------------------------
   Vorher trugen ein Dutzend Bausteine je einen eigenen Ring (mal --btn-blue,
   mal --btn-blue-dark, Versatz mal 1px, mal 2px, mal -2px) und alle anderen
   gar keinen – dort blieb der graue Umriss des Browsers stehen, der auf der
   kühlen Fläche wie ein Fehler aussieht.

   :where() hat Spezifität NULL. Diese Regel ist also nur die Grundlage; jeder
   Baustein, der einen eigenen Ring braucht (Zeile mit -2px Versatz, weil der
   Ring sonst vom Nachbarn verdeckt wird), überschreibt sie ohne !important.
   ========================================================================== */
:where(a, button, summary, [tabindex], [role="button"]):focus-visible {
    outline: 2px solid var(--focus-col);
    outline-offset: 2px;
    border-radius: var(--r-sm);
}
/* Eingaben tragen den Ring innen im Rahmen statt außen – ein Umriss um ein
   Feld herum doppelt dessen Kante und lässt es springen. */
:where(input, select, textarea):focus-visible {
    outline: none;
}

/* DIE TEXTMARKIERUNG. Sie lag auf --btn-blue-bg-light, also auf der blassen
   Tönung des Trägers – im Hellen eine gerade noch sichtbare Fläche, im
   Dunkeln 1,06 : 1 gegen die Karte. Wer dort einen Wert doppelt anklickte,
   um ihn zu überschreiben, sah nicht, was markiert war.

   Sie hängt bewusst NICHT am Haus: Eine Textmarkierung ist eine Funktion des
   Browsers, keine Marke – dieselbe Überlegung wie beim Leuchtblau, das der
   Anker der Anwendung ist und in jedem Haus gleich bleibt. Feste Werte also,
   aber beide Hälften als Token, damit die dunkle Fassung sie als PAAR
   umdreht (siehe den Kopf von includes/farbschema.php). */
::selection {
    background: var(--auswahl-bg);
    color: var(--auswahl-ink);
}

/* ==========================================================================
   Wer keine Bewegung will, bekommt keine – aber die Farbe bleibt
   --------------------------------------------------------------------------
   Es gab neun einzelne Blöcke dieser Art im Blatt, jeder mit einer eigenen
   Liste von Klassen. Ein neuer Baustein war darin nie enthalten; die Regel
   galt also immer für den Stand von gestern.

   Diese eine Regel nennt keine Klassen, sondern die ERLAUBTEN Eigenschaften:
   Farbe, Fläche, Rand, Schatten, Deckkraft dürfen weiter überblenden – das
   ist Rückmeldung, keine Bewegung. Alles andere (transform, translate,
   width, grid-template-columns) fällt weg und springt sofort, genau wie
   gewünscht. Die alten Blöcke setzen zusätzlich `transform: none` und dürfen
   stehen bleiben.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 1ms !important;
        animation-iteration-count: 1 !important;
        transition-property: color, background-color, border-color, box-shadow, opacity, fill, stroke !important;
        scroll-behavior: auto !important;
    }
}

/* Bildlaufleisten. Die Anwendung hat viele scrollende Ausschnitte (Postfach,
   Board-Spalten, Seitenleisten); die breite Systemleiste zieht darin mehr
   Aufmerksamkeit auf sich als der Inhalt. Nur für Zeiger-Bedienung – auf dem
   Touchgerät blendet das System seine Leiste ohnehin aus. */
@media (hover: hover) and (pointer: fine) {
    * {
        scrollbar-width: thin;
        scrollbar-color: var(--brand-line-strong) transparent;
    }
    /* DER PLATZ FÜR DIE LEISTE BLEIBT IMMER STEHEN – und das ist die Folge
       der Regeln hier drüber, nicht eine Laune für sich: Sobald eine Seite
       ihre Bildlaufleisten selbst gestaltet, blendet der Browser sie nicht
       mehr über den Inhalt, sondern räumt ihr eigenen Platz ein. Damit war
       eine Seite, die scrollt, 11 Pixel schmaler als eine, die es nicht tut.
       Beim Umschalten von Kontakte auf Mailings sprang deshalb die ganze
       Spur: Der Inhalt steht in einer mittigen .container-Spur, und die
       rückt bei 11 Pixel weniger Fensterbreite um gut 5 Pixel zur Seite.

       `overflow-y: scroll` macht das Fenster zum Scrollbehälter, damit die
       Leiste immer steht – auch auf einer kurzen Seite. `scrollbar-gutter`
       allein reicht dafür NICHT: Die Eigenschaft greift nur auf einem
       Behälter, der bereits scrollt, und `html` steht von Haus aus auf
       `overflow: visible`. Gemessen: mit `stable` allein blieb der
       Unterschied bei 11 Pixeln, erst mit beidem ist er null.

       Zu sehen ist von der leeren Leiste nichts – die Bahn ist durchsichtig
       (`::-webkit-scrollbar-track` unten) und ohne Griff, solange es nichts
       zu schieben gibt. */
    html {
        overflow-y: scroll;
        scrollbar-gutter: stable;
    }
    *::-webkit-scrollbar { width: 10px; height: 10px; }
    *::-webkit-scrollbar-track { background: transparent; }
    *::-webkit-scrollbar-thumb {
        background: var(--brand-line-strong);
        border: 3px solid transparent;
        background-clip: content-box;
        border-radius: var(--r-pill);
    }
    *::-webkit-scrollbar-thumb:hover { background: var(--brand-faint); background-clip: content-box; }
    *::-webkit-scrollbar-corner { background: transparent; }
}

.text-muted {
    color: var(--brand-quiet) !important;
}
small, .small { font-size: var(--fs-5); }

code {
    font-size: 0.85em;
    color: var(--btn-blue-dark);
    background-color: var(--btn-blue-bg-light);
    padding: 0.1em 0.35em;
    border-radius: 4px;
}
pre code {
    background: none;
    padding: 0;
}

/* Sektions-Mikrolabel (Look B): kurze, gesperrte Versalien */
.section-label {
    font-size: var(--fs-3);
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--brand-quiet);
}

/* Links tragen das Blaugrau der Oberfläche – Rot bleibt Marke, HEUTE und Warnung.
   Wo ein Link doch akzentuiert sein soll: Klasse .link-accent. */
a {
    color: var(--btn-blue-dark);
}
a:hover {
    color: var(--brand-text);
}
a.link-accent {
    color: var(--brand-accent);
}
a.link-accent:hover {
    color: var(--brand-accent-dark);
}

/* DIE KOPFLEISTE IST KEIN TEIL DER SEITE, SONDERN IHR RAHMEN. Sie stand als
   weiße Fläche mit Haarlinie auf einem fast weißen Grund und war deshalb von
   der Seite darunter nicht zu unterscheiden; die zwanzig Modulknöpfe darin
   sahen aus wie zwanzig Kästchen im Inhalt. Jetzt trennt sie ein deutlicher
   Strich und ein Hauch Erhebung vom Grund – und die Knöpfe darin sind keine
   Kästchen mehr, siehe weiter unten. */
.site-navbar {
    background-color: var(--brand-surface);
    border-bottom: 1px solid var(--brand-line-strong);
    box-shadow: var(--sh-1);
    padding-top: var(--sp-3);
    padding-bottom: var(--sp-3);
    /* Der Abstand zur Seite stand bis zum 10.08.2026 als Bootstraps `mb-4` im
       Markup von includes/header.php. Dort war er unsichtbar für jeden, der
       den Rhythmus der Seite ändern wollte – er gehört ins Blatt. */
    margin-bottom: var(--sp-7);
}
/* Die Kopfleiste bekommt eine breitere Spur als der Seiteninhalt. Mit zehn
   Modulknöpfen passte die Leiste nicht mehr in die 1280px der .container-Spur
   und brach um – „GodMode / Abmelden" rutschten allein in eine zweite Zeile,
   was wie ein Fehler aussieht und auf jeder Seite zu sehen war. */
.site-navbar > .container {
    max-width: 1720px;
    width: 100%;
    flex-wrap: nowrap;
}
/* Auf dem Telefon reicht die Zeile für Marke und Knöpfe nicht mehr. Bleibt sie
   dort auf nowrap, wird die Marke zusammengequetscht und ihr Schriftzug läuft
   unter die Knöpfe – die Knopfzeile bekommt deshalb eine eigene Zeile. */
@media (max-width: 991.98px) {
    .site-navbar > .container { flex-wrap: wrap; row-gap: 0.5rem; }
    .site-navbar .nav-knopfleiste { width: 100%; }
}
/* Die Knöpfe der Kopfleiste sind ganze Module, keine Nebenaktionen. Sie waren
   auf 33x28px zusammengeschrumpft, um elf Stück in eine Zeile zu zwingen – zu
   klein, um sie im Vorbeigehen auseinanderzuhalten. Jetzt tragen sie die Höhe
   der übrigen Bedienelemente (34px, Look B) und ein größeres Zeichen; den Platz
   holt sich die Zeile über die Schwellen weiter unten zurück. */
.site-navbar .btn-sm {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 34px;
    padding: 0.3rem 0.72rem;
    font-size: var(--fs-5);
}
/* Nachfahre, nicht Kind: die Glocke des Melders steckt in einem span, das
   zwischen ihren zwei Zuständen umschaltet – sonst bliebe sie als einzige klein. */
.site-navbar .btn-sm svg {
    width: 18px;
    height: 18px;
    flex: none;
}
.site-navbar .btn-sm .nav-wort { margin-left: 0.4rem; }

/* Die Beschriftungen sollen so früh wie möglich stehen – ein Zeichen allein
   sagt zu wenig. Wieviel Platz nötig ist, hängt aber davon ab, wieviele Module
   freigegeben sind (acht bis zwölf Knöpfe) – eine feste Schwelle rät also immer
   falsch: zu hoch, und die Wörter fehlen auf einem Schirm, auf dem sie längst
   passten; zu niedrig, und die Leiste bricht um.

   Deshalb misst `assets/js/nav-breite.js` und setzt eine der drei Stufen:
     .nav-mass-wort     volle Knöpfe mit Wort
     .nav-mass-eng      Wort bleibt, Knopf rückt enger zusammen
     .nav-mass-zeichen  nur das Zeichen, dafür groß (Bedeutung im title)
   Ohne JavaScript entscheidet die Schwelle darunter – sie ist bewusst hoch
   angesetzt, weil sie für den ungünstigsten Fall (alle Module) halten muss. */
.nav-wort { display: none; }
@media (min-width: 1600px) {
    .nav-wort { display: inline; }
}
.site-navbar.nav-mass-wort .nav-wort,
.site-navbar.nav-mass-eng .nav-wort { display: inline; }
.site-navbar.nav-mass-zeichen .nav-wort { display: none; }
/* Bootstraps gap-2 an der Knopfzeile trägt !important, also hier auch. */
.site-navbar.nav-mass-eng .btn-sm {
    padding-left: var(--sp-3);
    padding-right: var(--sp-3);
    font-size: var(--fs-4);
}
.site-navbar.nav-mass-eng .btn-sm .nav-wort { margin-left: 0.3rem; }
.site-navbar.nav-mass-eng .nav-knopfleiste { gap: 0.3rem !important; }

/* ==========================================================================
   Die Modulknöpfe – eine Reihe Zeichen, kein Kästchenteppich
   --------------------------------------------------------------------------
   Zwanzig Knöpfe mit eigener Fläche und eigenem Rand nebeneinander ergeben
   keine Navigation, sondern ein Muster: Alles ist gleich laut, nichts sagt,
   wo man gerade ist. Deshalb tragen sie hier keine Fläche und keinen Rand –
   nur ihr Zeichen. Fläche bekommt, was angefasst wird (Zeiger) und was gilt
   (die Seite, auf der man steht).

   NUR IN DER LEISTE: Im Inhalt bleibt .btn-outline-secondary der graue Knopf
   mit Rand, den die Seiten überall sonst benutzen.
   ========================================================================== */
.site-navbar .nav-knopfleiste > .btn-outline-secondary {
    background-color: transparent;
    border-color: transparent;
    color: var(--brand-quiet);
}
.site-navbar .nav-knopfleiste > .btn-outline-secondary:hover,
.site-navbar .nav-knopfleiste > .btn-outline-secondary:focus-visible {
    background-color: var(--blau-hauch);
    border-color: var(--blau-rand);
    color: var(--btn-leucht-tief);
}

/* WO MAN GERADE IST. Die Leiste sagte es bisher nicht – wer vom Kalender ins
   Adressbuch wechselte, sah dieselbe Reihe wie vorher. Der Knopf der offenen
   Seite trägt jetzt als einziger eine Fläche: die helle Tönung des Hauses mit
   dem Zeichen im Leuchtblau. Gesetzt wird die Marke in
   assets/js/nav-breite.js, weil die Leiste an einer Stelle steht und für
   sechzig Seiten gilt.

   KEIN STRICH DARUNTER: Er hat hier kurz gestanden und lag genau dort, wo die
   Zählblase sitzt (.nav-badge, bottom: -6px) – zwei Marken übereinander an
   einem 34px hohen Knopf. Die Tönung allein sagt es deutlich genug. */
.site-navbar .nav-knopfleiste > .btn-outline-secondary.is-hier {
    background-color: var(--blau-hell);
    border-color: var(--blau-rand);
    color: var(--btn-leucht-tief);
    font-weight: 700;
}

/* Nicht lizenziert: Der gestrichelte Rand ist die ganze Aussage und darf
   deshalb nicht mit den anderen verschwinden (siehe .nav-gesperrt in
   06-verwaltung.css – dort steht nur der Strichel-Stil, die Farbe hier). */
.site-navbar .nav-knopfleiste > .btn-outline-secondary.nav-gesperrt {
    border-color: var(--brand-border);
}
.navbar-brand {
    font-family: 'Plus Jakarta Sans', sans-serif;
    font-weight: 700;
    color: var(--brand-text) !important;
    min-width: 0;
    flex-shrink: 1;
}
.navbar-brand .accent {
    color: var(--brand-accent);
}
.navbar-brand .brand-text {
    min-width: 0;
}
.navbar-brand .brand-subtitle {
    font-family: 'IBM Plex Sans', sans-serif;
    font-size: var(--fs-3);
}
@media (max-width: 420px) {
    .navbar-brand {
        font-size: var(--fs-6);
    }
    .navbar-brand .brand-subtitle {
        font-size: var(--fs-1);
    }
    .brand-home-icon {
        width: 32px;
        height: 32px;
    }
    .brand-home-icon svg {
        width: 16px;
        height: 16px;
    }
}
/* Zählblasen an den Knöpfen der Kopfleiste (unten rechts, leicht überstehend) */
.has-badge { position: relative; }
.nav-badge {
    position: absolute;
    right: -5px;
    bottom: -6px;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--r-pill);
    border: 1.5px solid var(--brand-surface);
    font-size: var(--fs-2);
    font-weight: 700;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    pointer-events: none;
}
/* Pastelltöne aus der Kalenderpalette, Schrift dunkel – ruhig, aber lesbar.
   ALLE SECHS WERTE STEHEN HIER FEST, und das ist Absicht: Die Blase ist ein
   Signal von 17 Pixeln und soll auf heller wie auf dunkler Kopfleiste
   gleich aussehen. Wer eine Hälfte an ein Token hängt, bekommt im
   Dunkelmodus zwei Farben, die sich unabhängig voneinander bewegen –
   genau das war bis zum 23.08.2026 bei „online" der Fall: Die Fläche stand
   fest hell, die Schrift kam aus --btn-green-dark und wurde im Dunkeln zu
   hellem Grün. Grün auf Grün, 1,8 : 1 – die Zahl war unlesbar, und zwar
   nur für die, die dunkel eingestellt haben. */
.nav-badge.is-alert { background: #f5d3cf; color: #8f2318; }
.nav-badge.is-info { background: #cfdce3; color: #41586a; }
.nav-badge.is-online { background: #cbe8d5; color: #1c5233; }

/* ==========================================================================
   Kurzhinweis an den Knöpfen der Kopfleiste
   --------------------------------------------------------------------------
   In der engsten Stufe steht auf den Knöpfen nur noch ein Zeichen. Der
   eingebaute title des Browsers sagt zwar, was dahintersteckt, aber erst nach
   gut einer Sekunde, in der Systemschrift und irgendwo neben dem Mauszeiger.
   Also ein eigener Hinweis: gleich unter dem Knopf, in der Schrift der
   Oberfläche, nach kurzem Verweilen.

   Zwei Zeilen: `data-tip` ist das Wort des Knopfes, das optionale
   `data-tip-info` eine Erklärung – die tragen nur die wenigen Knöpfe, die
   ohne sie missverstanden würden.
   Ohne Zusatz greift die erste Regel, mit Zusatz die zweite – ein leeres
   attr() ließe sonst eine Leerzeile stehen. Erzeugt werden beide von $tip()
   in includes/header.php; dort steht auch, warum die Knöpfe kein title mehr
   tragen (sonst käme der eingebaute Hinweis eine Sekunde später obendrauf).

   Kein JavaScript: Der Hinweis hängt am Knopf selbst, nicht an einer Karte im
   body – anders als die Terminvorschau muss er nirgends ausweichen.
   ========================================================================== */
.site-navbar [data-tip] { position: relative; }
.site-navbar [data-tip]::after {
    content: attr(data-tip);
}
.site-navbar [data-tip][data-tip-info]::after {
    content: attr(data-tip) "\A" attr(data-tip-info);
}
.site-navbar [data-tip]::before,
.site-navbar [data-tip]::after {
    position: absolute;
    top: calc(100% + 10px);
    left: 50%;
    z-index: 5;
    opacity: 0;
    pointer-events: none;
    background: var(--tip-bg);
    transition: opacity var(--t-fast) var(--ease-out), translate var(--t-fast) var(--ease-out);
}
.site-navbar [data-tip]::after {
    width: max-content;
    max-width: 15rem;
    padding: 0.3rem 0.55rem;
    border: 1px solid var(--tip-rand);
    border-radius: var(--r-sm);
    color: var(--tip-ink);
    font-size: var(--fs-3);
    font-weight: 500;
    line-height: 1.35;
    letter-spacing: 0;
    text-align: center;
    text-transform: none;
    white-space: pre-line;   /* trägt den Umbruch aus dem "\A" */
    box-shadow: var(--shadow-pop);
    translate: -50% -4px;
}
/* Spitze zum Knopf. Sie sitzt am Knopf, nicht am Kästchen – deshalb zeigt sie
   auch dann auf die Mitte, wenn das Kästchen am Rand rechtsbündig hängt. */
.site-navbar [data-tip]::before {
    content: "";
    width: 8px;
    height: 8px;
    /* Nur die beiden oberen Kanten. Das Quadrat ist um 45 Grad gedreht;
       danach liegen seine Kanten „oben" und „links" genau auf den beiden
       Seiten, die aus dem Kästchen herausschauen. Ein umlaufender Rand zöge
       stattdessen zwei Striche quer durch die Fläche. Im Hellen ist der Rand
       durchsichtig und die Regel damit wirkungslos. */
    border-top: 1px solid var(--tip-rand);
    border-left: 1px solid var(--tip-rand);
    border-radius: 1px;
    rotate: 45deg;
    translate: -50% -8px;
}
/* Am rechten Ende der Leiste ragte ein mittiger Hinweis aus dem Fenster und
   zöge einen waagerechten Rollbalken nach sich – die letzten vier Knöpfe
   hängen ihn deshalb an ihrer rechten Kante auf. */
.site-navbar .nav-knopfleiste > :nth-last-child(-n+4)[data-tip]::after {
    left: auto;
    right: 0;
    translate: 0 -4px;
    text-align: right;
}

/* Zeigen: Maus mit Feinzeiger nach kurzem Verweilen, Tastatur sofort. Das
   Verweilen verhindert, dass beim Überstreichen der Leiste zehn Hinweise
   hintereinander aufblitzen. Verschwinden darf er ohne Verzögerung. */
@media (hover: hover) and (pointer: fine) {
    .site-navbar [data-tip]:hover::before,
    .site-navbar [data-tip]:hover::after {
        opacity: 1;
        transition-delay: 0.25s;
    }
    .site-navbar [data-tip]:hover::after { translate: -50% 0; }
    .site-navbar [data-tip]:hover::before { translate: -50% -4px; }
    .site-navbar .nav-knopfleiste > :nth-last-child(-n+4)[data-tip]:hover::after {
        translate: 0 0;
    }
}
.site-navbar [data-tip]:focus-visible::before,
.site-navbar [data-tip]:focus-visible::after { opacity: 1; }
.site-navbar [data-tip]:focus-visible::after { translate: -50% 0; }
.site-navbar [data-tip]:focus-visible::before { translate: -50% -4px; }
.site-navbar .nav-knopfleiste > :nth-last-child(-n+4)[data-tip]:focus-visible::after {
    translate: 0 0;
}
/* Wer Bewegung abbestellt hat, bekommt den Hinweis trotzdem – nur ohne das
   Heranrücken. Die Blende bleibt, sie ist keine Bewegung. */
@media (prefers-reduced-motion: reduce) {
    .site-navbar [data-tip]::before,
    .site-navbar [data-tip]::after { transition-property: opacity; }
    .site-navbar [data-tip]::after { translate: -50% 0; }
    .site-navbar [data-tip]::before { translate: -50% -4px; }
    .site-navbar .nav-knopfleiste > :nth-last-child(-n+4)[data-tip]::after { translate: 0 0; }
}

.brand-home-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: var(--r-ctl);
    background-color: var(--brand-signal);
    color: var(--brand-signal-ink);
    flex: 0 0 auto;
    transition: background-color var(--t-fast) var(--ease-out);
}
.brand-home-icon svg {
    width: 19px;
    height: 19px;
}
/* Ein hochgeladenes Logo (Erscheinungsbild) füllt das ganze Plättchen: Ein
   transparenter Grund lässt die Signalfläche durchscheinen, eine eigene
   Fläche deckt sie ab – die Rundung erbt das Bild vom Plättchen. */
.brand-home-icon img {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: inherit;
}

/* Die Karte ist die Grundfläche der ganzen Anwendung. Sie bleibt flach – aber
   ein Hauch Erhebung (--sh-1, kaum ein Prozent Deckkraft) hebt sie sichtbar
   vom kühlen Grund ab, ohne dass irgendetwas schwebt. Ohne ihn stand ein
   Dutzend weißer Rechtecke mit 1px-Rand nebeneinander wie ein Formular. */
.card {
    background-color: var(--brand-surface);
    border: 1px solid var(--brand-border);
    border-radius: var(--r-card);
    box-shadow: var(--sh-1);
    overflow: hidden;
}
/* Kartenkopf: Beschriftung links, Aktion rechts – als Regel, nicht als
   Hilfsklassen-Kette. Vorher stand an manchen Karten
   „d-flex flex-wrap justify-content-between align-items-center gap-2",
   an anderen .um-kopf und an den meisten gar nichts; Karten mit Knopf sahen
   deshalb je nach Seite anders aus. */
.card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3) var(--sp-5);
    flex-wrap: wrap;
    background-color: var(--card-header-bg);
    border-bottom: 1px solid var(--card-header-border);
    font-family: 'Plus Jakarta Sans', sans-serif;
    font-weight: 700;
    font-size: var(--fs-6);
    letter-spacing: -0.005em;
    /* Die Überschrift der Karte im dunklen Blaugrau, wie der Titel im
       Seitenkopf (.cal-title). Sie stand im Tintenton des Fließtextes und war
       damit genauso laut wie der Inhalt darunter – auf der Startseite, wo ein
       Dutzend Karten nebeneinanderstehen, fehlte deshalb die Ebene zwischen
       „was ist das hier" und „was steht drin". */
    color: var(--brand-titel);
    /* Feste Mindesthöhe: Ein Kopf mit Knopf war 44px hoch, einer ohne 33px –
       zwei Karten nebeneinander begannen deshalb auf verschiedenen Höhen. */
    min-height: 44px;
    padding: var(--sp-3) var(--sp-5);
}
/* Das Zeichen vor der Überschrift trägt das Leuchtblau des Hauses – dieselbe
   Farbe wie die Zeichen der Kennzahlenkacheln darüber. Ein Zeichen ist keine
   Auskunft, sondern eine Marke; es darf deshalb Farbe tragen, ohne dass
   jemand es für eine Meldung hält. NUR das Zeichen der Überschrift, nicht die
   Zeichen in den Knöpfen daneben – die gehören zum Knopf. */
/* ==========================================================================
   DER ANKER IM KARTENKOPF (22.08.2026)

   Das Zeichen sitzt in einem Plättchen von 25 Pixeln. Auf der Startseite
   stehen neun Karten nebeneinander, deren Köpfe sich nur im Wort
   unterscheiden – das Plättchen macht daraus eine Reihe, die man von weitem
   auseinanderhält, ohne dass eine davon lauter wird.

   `box-sizing: content-box`, damit die 15 Pixel des Zeichens die 15 Pixel
   bleiben, die icon() zeichnet: Mit border-box schrumpfte das Zeichen auf
   5 Pixel und das Plättchen wäre fast leer.
   ========================================================================== */
.card-header > span:first-child {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    min-width: 0;
}
.card-header > svg:first-child,
.card-header > span:first-child > svg:first-child {
    box-sizing: content-box;
    flex: none;
    width: 15px;
    height: 15px;
    padding: 4px;
    border-radius: var(--r-sm);
    background: var(--blau-hell);
    /* Die Kante trägt das Plättchen, nicht die Fläche: Der Kartenkopf ist
       selbst schon eine Tönung (--card-header-bg), und die Tönung darauf
       liegt bei 1,1 : 1 – man sieht sie in keiner der beiden Fassungen. Eine
       Linie braucht diesen Abstand nicht, sie zeichnet die Form. */
    border: 1px solid var(--blau-rand);
    color: var(--btn-leucht-tief);
    /* Die Kartenköpfe setzen den Abstand bisher über Bootstraps `me-1` am
       Zeichen. Den macht jetzt `gap` – sonst stünde er doppelt. */
    margin: 0 !important;
}

/* Knöpfe im Kartenkopf sind überall gleich hoch – wie im Seitenkopf. */
.card-header .btn {
    height: var(--h-ctl-sm);
    display: inline-flex;
    align-items: center;
    font-size: var(--fs-4);
    padding: 0 var(--sp-4);
    border-radius: var(--r-sm);
}
.card-body {
    padding: var(--sp-5);
}
.card-footer {
    background-color: var(--card-header-bg);
    border-top: 1px solid var(--card-header-border);
    padding: var(--sp-3) var(--sp-5);
}
/* Eine Tabelle geht bis an die Kante der Karte – das Polster des Rumpfes
   liegt sonst zweimal um sie herum (Zelle plus Rumpf) und die Kopfzeile
   steht als schmales Band mitten in der Fläche. */
.card-body:not(.p-0):not([class*="p-"]) > .table:only-child,
.card-body:not(.p-0):not([class*="p-"]) > .table-responsive:only-child {
    margin: calc(var(--sp-5) * -1);
    width: calc(100% + var(--sp-5) * 2);
}
.card-body > .table:only-child > :not(caption) > * > *:first-child,
.card-body > .table-responsive:only-child > .table > :not(caption) > * > *:first-child { padding-left: var(--sp-5); }
.card-body > .table:only-child > :not(caption) > * > *:last-child,
.card-body > .table-responsive:only-child > .table > :not(caption) > * > *:last-child { padding-right: var(--sp-5); }
.card-body > .table:only-child > tbody > tr:last-child > *,
.card-body > .table-responsive:only-child > .table > tbody > tr:last-child > * { border-bottom: 0; }

/* Knöpfe. Look B kennt genau zwei Größen: --h-ctl (34px) für alles, was für
   sich steht, und --h-ctl-sm (28px) für Knöpfe in einer Zeile oder einem
   Kartenkopf. Vorher entschied das Polster über die Höhe, und die fiel je
   nach Schriftgröße und Zeichen im Knopf um zwei bis drei Pixel anders aus –
   nebeneinander sieht das aus, als stünde einer schief. */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    min-height: var(--h-ctl);
    border-radius: var(--r-ctl);
    font-weight: 600;
    font-size: var(--fs-6);
    line-height: 1.2;
    padding: 0.3rem var(--sp-4);
    transition: background-color var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out);
}

/* ==========================================================================
   ANFASSEN ANTWORTET (22.08.2026)

   Jedes Bedienelement geht unter dem Finger einen Hauch zusammen: 97 %,
   160 ms. Man sieht es nicht bewusst – man spürt nur, dass die Anwendung
   zuhört. Ohne das antwortet ein Klick erst, wenn die nächste Seite da ist,
   und in der Zwischenzeit weiß niemand, ob er getroffen hat.

   97 UND NICHT 95: Bei 95 % wackelt ein Knopf mit Text sichtbar, weil scale()
   auch die Schrift mitzieht. Drei Prozent sind die Grenze, unter der es sich
   nach Druck anfühlt und noch nicht nach Bewegung aussieht.

   160 ms ist die Stufe darunter für --t-fast (120) und darüber für --t-base
   (180). Sie steht hier ausgeschrieben, weil eine Druckantwort weder ein
   Farbwechsel noch ein Erscheinen ist – die beiden Dauern der Leiter meinen
   etwas anderes.

   NICHT FÜR :disabled: Was nicht geht, soll auch nicht antworten.
   ========================================================================== */
.btn:not(:disabled):not(.disabled):active,
a.kpi:active,
.cal-seg a:active,
.ld-status-btn:not(.is-active):active,
.bezug-option:active,
.fs-eintrag:active {
    transform: scale(0.97);
}
/* Die Kachelreihe der Startseite trägt ihre eigene, größere Schrift und
   braucht deshalb dieselbe Kurve wie die Knöpfe – sonst antwortet sie eine
   Spur später als alles daneben. */
a.kpi,
.cal-seg a,
.ld-status-btn,
.bezug-option {
    transition: background-color var(--t-fast) var(--ease-out),
                border-color var(--t-fast) var(--ease-out),
                color var(--t-fast) var(--ease-out),
                box-shadow var(--t-base) var(--ease-out),
                transform 160ms var(--ease-out);
}

@media (prefers-reduced-motion: reduce) {
    .btn:not(:disabled):not(.disabled):active,
    a.kpi:active,
    .cal-seg a:active,
    .ld-status-btn:not(.is-active):active,
    .bezug-option:active,
    .fs-eintrag:active {
        transform: none;
    }
}

.btn-sm {
    min-height: var(--h-ctl-sm);
    border-radius: var(--r-sm);
    font-size: var(--fs-5);
    padding: 0.2rem var(--sp-3);
}
.btn-lg {
    min-height: var(--h-ctl-lg);
    border-radius: var(--r-ctl);
    font-size: var(--fs-7);
    padding: var(--sp-3) var(--sp-6);
}
/* Druckantwort: der Knopf gibt unter dem Finger nach. Kein Weg, keine Dauer –
   nur die Größe, und die kommt beim Loslassen über --t-fast zurück. */
@media (hover: hover) and (pointer: fine) {
    .btn:active { transform: scale(0.97); }
}
.btn:disabled, .btn.disabled { opacity: 0.5; }
/* Der gefüllte Knopf ist auf einer Seite meist der eine, um den es geht. Er
   trägt deshalb seit dem 21.08.2026 einen Hauch Körper und ein Pixel Schatten
   darunter. Das ist wenig genug, dass Look B flach bleibt, und genug, dass der
   Knopf auf der Fläche steht statt in ihr zu liegen. Beim Drücken geht der
   Schatten weg – zusammen mit dem `scale(0.97)` weiter oben sinkt er ein.

   ZUR FARBE (22.08.2026): Er trug bis dahin das Blaugrau des Hauses
   (--btn-blue) und den Körper als Verlauf von einem Zehntel Weiß nach vier
   Hundertstel Schwarz. Daneben stand aber schon das helle Blau der Werbeseite:
   in der Kopfleiste am hervorgehobenen Knopf und an der Glocke, im
   Antwortkasten am Sendeknopf, in der Handy-App an allem. Das waren zwei
   verschiedene blaue Knöpfe auf einem Bildschirm, unterschieden nur danach, in
   welchem Jahr die Regel geschrieben wurde. Der gefüllte Knopf trägt jetzt
   ÜBERALL dieselbe Fassung wie dort – Verlauf --btn-leucht → --btn-leucht-dark,
   weiße Schrift, beim Anfassen eine Stufe tiefer nach --btn-leucht-tief. Der
   Körper kommt seitdem aus dem Farbverlauf selbst; ein zweiter darüber wäre
   Schlamm.

   ZUM KONTRAST: Weiß auf dem reinen --btn-leucht liegt bei 2,8 : 1, auf
   --btn-leucht-dark bei 4,1 : 1 – das ist die Rechnung, die die Werbeseite,
   die Kopfleiste und der Sendeknopf seit jeher tragen, und der Knopf ist
   fett gesetzt. Wer die 4,5 : 1 auch hier will, dreht den Verlauf eine Stufe
   tiefer (--btn-leucht-dark → --btn-leucht-tief, 4,1 : 1 bis 5,8 : 1) – dann
   aber HIER UND IN DER KOPFLEISTE, sonst stehen wieder zwei Blau da. */
.btn-primary {
    background-color: var(--btn-leucht-dark);
    background-image: linear-gradient(150deg, var(--btn-leucht), var(--btn-leucht-dark));
    border-color: var(--btn-leucht-dark);
    color: #fff;
    box-shadow: 0 1px 2px rgba(24, 44, 66, .16);
}
.btn-primary:hover, .btn-primary:focus, .btn-primary:active {
    background-color: var(--btn-leucht-dark) !important;
    background-image: linear-gradient(150deg, var(--btn-leucht-dark), var(--btn-leucht-tief)) !important;
    border-color: var(--btn-leucht-tief) !important;
    color: #fff !important;
}
.btn-primary:active { box-shadow: none; }
/* Die helle Seite desselben Knopfes – dieselbe Familie, nur als Tönung: die
   drei Stufen --blau-hell / --blau-rand aus dem :root und die Schrift in
   --btn-leucht-tief (auf der Tönung 5,3 : 1; --btn-leucht-dark käme dort nur
   auf 3,8 : 1 und ist für eine Beschriftung von 0,85rem zu blass). Er stand
   bis zum 22.08.2026 im blaugrauen Paar --btn-blue-bg-light /
   --btn-blue-border-light und wäre neben dem gefüllten Knopf oben als dessen
   leise Fassung nicht mehr zu erkennen gewesen. */
.btn-outline-primary {
    background-color: var(--blau-hell);
    color: var(--btn-leucht-tief);
    border-color: var(--blau-rand);
}
.btn-outline-primary:hover {
    background-color: var(--btn-leucht-dark);
    border-color: var(--btn-leucht-dark);
    color: #fff;
}

.btn-success {
    background-color: var(--btn-green-bg-light);
    border-color: var(--btn-green-border-light);
    color: var(--btn-green);
}
.btn-success:hover, .btn-success:focus, .btn-success:active {
    background-color: var(--btn-green) !important;
    border-color: var(--btn-green) !important;
    color: var(--auf-marke) !important;
}

.btn-outline-secondary {
    background-color: var(--btn-gray-bg);
    color: var(--brand-text);
    border-color: var(--btn-gray-border);
}
.btn-outline-secondary:hover {
    background-color: var(--btn-gray-bg-hover);
    border-color: var(--btn-gray-border-hover);
    color: var(--brand-text);
}

.btn-outline-danger {
    background-color: var(--btn-red-bg-light);
    color: var(--btn-red-text);
    border-color: var(--btn-red-border-light);
}
.btn-outline-danger:hover {
    background-color: var(--btn-red-text);
    border-color: var(--btn-red-text);
    color: var(--auf-marke);
}

/* Der Textknopf ist kein Knopf, sondern ein Link in Knopfschreibweise. Er darf
   deshalb die Mindesthöhe der echten Knöpfe nicht mitbringen – in einer
   Tabellenzeile machte er sonst jede Zeile sechs Pixel höher. */
.btn-link {
    min-height: 0;
    color: var(--btn-blue-dark);
}
.btn-link:hover, .btn-link:focus {
    color: var(--btn-blue-dark);
}

/* ==========================================================================
   Zeichenknöpfe – die Reihe am Kopf einer Person, einer Zeile, einer Karte
   --------------------------------------------------------------------------
   Ein Knopf, in dem nur ein Zeichen steht, ist quadratisch: sonst entscheidet
   die Breite des Zeichens über die Breite des Knopfes, und eine Reihe aus
   sechs Stück steht wie eine Klaviatur mit verschieden breiten Tasten.

   ZUM ROT: In einer solchen Reihe war der Löschknopf der einzige farbige –
   er zog jeden Blick auf sich, obwohl er die Handlung ist, die am seltensten
   gemeint ist. Er ruht jetzt neutral wie seine Nachbarn und wird erst unter
   dem Zeiger rot; die Warnung steht damit da, wo sie gebraucht wird, nämlich
   im Augenblick des Zugreifens. Knöpfe mit Wort bleiben unberührt – „Firma
   löschen" allein auf weiter Fläche darf und soll rot sein.

   ACHTUNG, WARUM EINE KLASSE UND KEIN SELEKTOR: Der naheliegende Weg
   `.btn:has(> svg:only-child)` ist falsch. `:only-child` zählt nur Elemente –
   der Text neben dem Zeichen ist ein Textknoten, also traf die Regel auch
   „Postfach abrufen" und quetschte jeden beschrifteten Knopf auf 34px. Die
   Klasse setzt deshalb das PHP dort, wo wirklich nur ein Zeichen im Knopf
   steht.
   ========================================================================== */
.btn-zeichen {
    width: var(--h-ctl);
    padding: 0;
    flex: none;
}
.btn-sm.btn-zeichen {
    width: var(--h-ctl-sm);
    padding: 0;
}
.btn-zeichen.btn-outline-danger {
    background-color: var(--btn-gray-bg);
    border-color: var(--btn-gray-border);
    color: var(--brand-quiet);
}
.btn-zeichen.btn-outline-danger:hover,
.btn-zeichen.btn-outline-danger:focus-visible {
    background-color: var(--btn-red-bg-light);
    border-color: var(--btn-red-border-light);
    color: var(--btn-red-text);
}

/* Dasselbe Prinzip für BESCHRIFTETE Löschknöpfe (.btn-leise): Ein „Verlauf
   löschen" mitten in der Arbeitsfläche war sonst der lauteste Knopf der Seite.
   Er ruht grau und zeigt sein Rot erst unter dem Zeiger – wer ihn sucht,
   findet ihn; wer arbeitet, wird nicht dauernd gewarnt. */
.btn-leise.btn-outline-danger {
    background-color: var(--btn-gray-bg);
    border-color: var(--btn-gray-border);
    color: var(--brand-quiet);
}
.btn-leise.btn-outline-danger:hover,
.btn-leise.btn-outline-danger:focus-visible {
    background-color: var(--btn-red-bg-light);
    border-color: var(--btn-red-border-light);
    color: var(--btn-red-text);
}

.list-group-item {
    border-color: var(--brand-border);
    padding: 0.55rem 0.8rem;
    font-size: var(--fs-6);
}
.list-group-item-action:hover {
    background-color: var(--brand-row);
}

/* Eingaben: einheitlich 34px hoch, 8px Radius, ruhiger Blaugrau-Fokus */
.form-control, .form-select {
    min-height: var(--h-ctl);
    border-radius: var(--r-ctl);
    border-color: var(--brand-line-strong);
    font-size: var(--fs-6);
    padding: 0.35rem 0.65rem;
    color: var(--brand-text);
}
textarea.form-control {
    min-height: 80px;
}
/* Die kleine Stufe. Das Polster kommt hierher und nicht von Bootstrap: Mit
   dessen Vorgabe wurde das Feld 32px hoch, der Knopf daneben (.btn-sm) 28 –
   in einer Zeile aus Feld und Knopf sah man den Versatz sofort. Textfelder
   (rows="3") dürfen darüber hinauswachsen, deshalb min-height und nicht
   height. */
.form-control-sm, .form-select-sm {
    min-height: var(--h-ctl-sm);
    border-radius: var(--r-sm);
    font-size: var(--fs-5);
    padding: 0.15rem var(--sp-3);
}
textarea.form-control-sm { padding: var(--sp-2) var(--sp-3); }
.form-control::placeholder {
    color: var(--brand-faint);
}
/* Dateiauswahl: der Knopf braucht eigene Maße, sonst quetscht ihn das Polster */
.form-control[type="file"] {
    padding: var(--sp-1) 0.55rem;
    line-height: 1.6;
}
.form-control[type="file"]::file-selector-button {
    padding: 0.3rem 0.7rem;
    margin: -0.25rem 0.65rem -0.25rem -0.55rem;
    border: 0;
    border-right: 1px solid var(--brand-border);
    border-radius: 0;
    background: var(--btn-gray-bg);
    color: var(--brand-text);
    font-size: var(--fs-5);
    font-weight: 600;
    transition: background-color var(--t-fast) var(--ease-out);
}
.form-control[type="file"]:hover::file-selector-button {
    background: var(--btn-gray-bg-hover);
}
/* Der Rahmen des Feldes unter dem Finger trägt dieselbe Farbe wie der Ring
   darum (--focus-col, das Leuchtblau). Er stand auf dem Träger der
   Gesellschaft: ein dunkelblaugrauer Rahmen in einem hellblauen Schein sah
   aus wie zwei verschiedene Meldungen an derselben Stelle. */
.form-control:focus, .form-select:focus {
    border-color: var(--focus-col);
    box-shadow: var(--focus-ring);
}
.form-label {
    font-size: var(--fs-5);
    font-weight: 600;
    color: var(--brand-quiet);
    margin-bottom: var(--sp-1);
}
/* Das angehakte Kästchen trägt seit dem 22.08.2026 dasselbe helle Blau wie
   der gefüllte Knopf – es ist die häufigste gefüllte Fläche der ganzen
   Anwendung und war die letzte, die noch blaugrau stand. */
.form-check-input:checked {
    background-color: var(--btn-leucht-dark);
    border-color: var(--btn-leucht-dark);
}
.form-check-input:focus {
    border-color: var(--focus-col);
    box-shadow: var(--focus-ring);
}
/* Das WhatsApp-Häkchen hinter einer Mobilnummer (privat_form.php): Kästchen,
   Zeichen und Wort stehen als Flex-Zeile statt im schwebenden .form-check,
   sonst sitzen Kästchen und Zeichen um zwei Pixel versetzt. Ohne
   .form-check-label fehlt der Zeigefinger von Bootstrap – hier nachgereicht. */
.wa-haken {
    cursor: pointer;
    user-select: none;
}
.wa-haken .form-check-input {
    cursor: pointer;
}
.input-group-text {
    background-color: var(--btn-gray-bg);
    border-color: var(--brand-line-strong);
    border-radius: var(--r-ctl);
    font-size: var(--fs-5);
    color: var(--brand-quiet);
}

/* Tabellen: dicht, Kopfzeile als Mikrolabel */
.table {
    font-size: var(--fs-6);
    /* Die Zeile unter dem Zeiger im hellen Blau statt im Grau: Grau ist die
       Farbe der Zebrastreifen und war von ihnen nicht zu unterscheiden – man
       sah nicht, welche Zeile man gerade traf. */
    --bs-table-hover-bg: var(--blau-hauch);
}

/* ==========================================================================
   DIE ZEILE ZEIGT, WO MAN STEHT (22.08.2026)

   Zur Tönung kommt eine 2-Pixel-Kante am linken Rand, die von der Mitte her
   aufwächst. Die Tönung allein sagt „diese Zeile"; die Kante sagt es auch
   dann noch, wenn die Tabelle in einer Karte steht und der Unterschied
   zwischen Tönung und Papier zwei Prozent Helligkeit beträgt.

   ÜBER ::after UND NICHT ÜBER border-left: Ein Rahmen an der Zelle schöbe den
   Text um zwei Pixel nach rechts, sobald er erscheint – die ganze Tabelle
   zuckte unter dem Zeiger. Das Pseudoelement liegt darüber und bewegt nichts.

   AN DER ERSTEN ZELLE, NICHT AN DER ZEILE: `position: relative` an einem <tr>
   ist in der Tabellenberechnung nicht verlässlich (Chrome zeichnet es, Safari
   nicht). Die erste Zelle ist ein gewöhnlicher Kasten und trägt es überall.

   NUR IN TABELLEN, DIE MAN ANFASST: `.table-hover` ist die Klasse, die
   Bootstrap dafür schon hat, und wo sie fehlt, ist die Tabelle ein Bericht
   und keine Liste.
   ========================================================================== */
.table-hover > tbody > tr > td:first-child,
.table-hover > tbody > tr > th:first-child {
    position: relative;
}
.table-hover > tbody > tr > :first-child::after {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 2px;
    border-radius: var(--r-pill);
    background: var(--btn-leucht);
    transform: scaleY(0);
    transition: transform var(--t-base) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
    .table-hover > tbody > tr:hover > :first-child::after { transform: scaleY(1); }
}
@media (prefers-reduced-motion: reduce) {
    .table-hover > tbody > tr > :first-child::after { transition: none; }
}
.table > :not(caption) > * > * {
    padding: var(--sp-3) var(--sp-4);
    border-bottom-color: var(--brand-border);
}
.table-sm > :not(caption) > * > * {
    padding: var(--sp-2) var(--sp-4);
}
.table > thead th {
    font-size: var(--fs-3);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    /* Das dunkle Blaugrau, nicht das Sekundärgrau: Auf der Tönung des Bandes
       läge --brand-quiet bei 4,4 : 1, und für Versalien von 11 Pixeln sind
       4,5 : 1 die Grenze. Dieser Ton liegt bei 7 : 1 – und eine Kopfzeile
       darf ohnehin deutlicher sein als der leise Nebentext, den sie sonst
       trägt. */
    color: var(--brand-titel);
    /* Die Kopfzeile als eigenes Band. Sie war weiß wie die Tabelle darunter
       und hing damit in der Fläche.

       DERSELBE TON WIE DER KARTENKOPF, nicht ein eigener: In einer Karte mit
       Tabelle liegen die beiden Bänder unmittelbar übereinander. Zwei Töne,
       die sich um ein paar Prozent Helligkeit unterscheiden, sieht niemand
       als Absicht – man sieht nur, dass sie nicht gleich sind. */
    background-color: var(--card-header-bg);
    border-bottom-color: var(--brand-line-strong);
    white-space: nowrap;
    /* Die Kopfzeile ist ein Mikrolabel und darf ruhig etwas Luft haben – sie
       trennt die Tabelle vom Kartenkopf darüber. */
    padding-top: var(--sp-4);
    padding-bottom: var(--sp-3);
}
/* Die letzte Zeile einer Tabelle braucht keine Trennlinie: darunter kommt
   entweder der Kartenrand oder der Kartenfuß, und beide sind selbst eine. */
.table:not(:has(tfoot)) > tbody:last-of-type > tr:last-child > * { border-bottom-width: 0; }
.table-light, .table > thead.table-light th {
    --bs-table-bg: var(--card-header-bg);
    background-color: var(--card-header-bg);
}

.dp-display-input {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23678595' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='3'/%3E%3Cline x1='16' y1='2' x2='16' y2='6'/%3E%3Cline x1='8' y1='2' x2='8' y2='6'/%3E%3Cline x1='3' y1='10' x2='21' y2='10'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.7rem center;
    background-size: 18px 18px;
    padding-right: 2.4rem;
    cursor: pointer;
    background-color: var(--brand-surface);
}
.dp-display-input:focus {
    cursor: pointer;
}
/* Tippbare Datumsfelder (ohne readonly) verhalten sich wie Textfelder: Der
   Zeigefinger würde hier lügen, es steht ein Schreibcursor drin. */
.dp-display-input:not([readonly]),
.dp-display-input:not([readonly]):focus {
    cursor: text;
}
.dp-display-input.dp-ungueltig,
.dp-display-input.dp-ungueltig:focus {
    border-color: var(--btn-red-text);
    box-shadow: none;
}

.dp-popup {
    position: absolute;
    /* Über allem, auch über den Dialogen des Boards (.bd-overlay: 1060) –
       dort hängt die Kalenderauswahl der Fälligkeit dran. */
    z-index: 1100;
    width: 268px;
    background-color: var(--brand-surface);
    border: 1px solid var(--brand-border);
    border-radius: var(--r-card);
    box-shadow: var(--shadow-pop);
    padding: var(--sp-4);
    font-family: 'Plus Jakarta Sans', 'IBM Plex Sans', sans-serif;
}
.dp-header {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 0.6rem;
}
.dp-nav {
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: var(--r-sm);
    background-color: transparent;
    color: var(--btn-blue-dark);
    font-size: var(--fs-8);
    line-height: 1;
    cursor: pointer;
    transition: background-color var(--t-fast) var(--ease-out);
}
.dp-nav:hover {
    background-color: var(--btn-blue-bg-light);
}
.dp-select {
    flex: 1 1 auto;
    min-width: 0;
    border: 1px solid var(--brand-border);
    border-radius: var(--r-ctl);
    padding: var(--sp-1) 0.35rem;
    font-family: 'Plus Jakarta Sans', sans-serif;
    font-weight: 600;
    font-size: var(--fs-6);
    color: var(--brand-text);
    background-color: var(--brand-surface);
}
.dp-select-year {
    flex: 0 0 5.2rem;
}
.dp-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
}
.dp-weekday {
    text-align: center;
    font-size: var(--fs-3);
    color: var(--brand-quiet);
    font-weight: 600;
    padding: 0.2rem 0;
}
.dp-day {
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    background-color: transparent;
    border-radius: var(--r-sm);
    font-size: var(--fs-6);
    font-variant-numeric: tabular-nums;
    color: var(--brand-text);
    cursor: pointer;
    transition: background-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.dp-day:hover {
    background-color: var(--blau-hell);
}
.dp-day-empty {
    cursor: default;
    pointer-events: none;
}
.dp-day-today {
    box-shadow: inset 0 0 0 1.5px var(--brand-accent);
    color: var(--brand-accent);
    font-weight: 600;
}
.dp-day-selected, .dp-day-selected:hover {
    background-color: var(--btn-leucht-dark);
    color: #fff;
}
.dp-footer {
    display: flex;
    justify-content: space-between;
    margin-top: 0.6rem;
    padding-top: 0.6rem;
    border-top: 1px solid var(--brand-border);
}
.dp-footer-btn {
    border: none;
    background: none;
    color: var(--btn-blue-dark);
    font-weight: 600;
    font-size: var(--fs-5);
    cursor: pointer;
    padding: 0.2rem 0.4rem;
    border-radius: var(--r-sm);
}
.dp-footer-btn:hover {
    background-color: var(--blau-hell);
}
.dp-footer-btn-clear {
    color: var(--btn-red-text);
}

/* HIER STAND DIE AUSNAHME FÜR DEN HERVORGEHOBENEN KNOPF DER KOPFLEISTE –
   „Update"/„Deploy", solange Änderungen offen sind (includes/header.php,
   $hebtHervor), und „Lizenz", solange kein Schlüssel hinterlegt ist. Er trug
   seit dem 21.08.2026 als EINZIGER .btn-primary das helle Blau der Werbeseite,
   weil er sonst neben der eingeschalteten Glocke in einem zweiten Blau stand.
   Am 22.08.2026 hat der gefüllte Knopf diese Fassung überall bekommen (oben,
   .btn-primary) – die Ausnahme ist damit die Regel geworden und hier heraus.
   Wer sie zurückholt, holt sich zwei blaue Knöpfe auf einen Bildschirm. */

/* Melder-Glocke in der Kopfleiste (assets/js/melder.js).
   Aus ist der Ruhezustand: durchsichtig wie die übrige Leiste, Zeichen in
   --brand-quiet. An trägt seit dem 22.08.2026 wieder das helle Blau der
   Werbeseite – derselbe Verlauf --btn-leucht → --btn-leucht-dark wie der
   hervorgehobene Knopf weiter oben, mit weißem Zeichen. Weiß ist dabei
   Bedingung und nicht Geschmack: Auf dem Leuchtblau verschwände sowohl das
   frühere Grau (--brand-text) als auch ein blaues Zeichen. Zwischenstand am
   21.08.2026 war das Hellgrau des Hauses (--btn-gray-bg) mit grauem Zeichen,
   davor bis zum 21.08.2026 das Blaugrau --btn-blue-dark.

   SPEZIFITÄT: Der Ruhezustand kommt aus
   `.site-navbar .nav-knopfleiste > .btn-outline-secondary` (0,3,0) und
   überschriebe ein bloßes `.melder-knopf.is-an` (0,2,0) – deshalb steht der
   Anzustand hier mit demselben Vorlauf. Der frühere Verlauf gewann nur, weil
   ein `background-image` von `background-color: transparent` nicht berührt
   wird; eine Fläche gewinnt so nicht. */
.melder-knopf { padding-left: 0.5rem; padding-right: 0.5rem; }
.melder-knopf .melder-icon-an { display: none; }
.melder-knopf.is-an .melder-icon-an { display: inline; }
.melder-knopf.is-an .melder-icon-aus { display: none; }
.site-navbar .nav-knopfleiste > .melder-knopf.is-an {
    background-color: var(--btn-leucht);
    background-image: linear-gradient(150deg, var(--btn-leucht), var(--btn-leucht-dark));
    border-color: var(--btn-leucht-dark);
    color: #fff;
}
.site-navbar .nav-knopfleiste > .melder-knopf.is-an:hover,
.site-navbar .nav-knopfleiste > .melder-knopf.is-an:focus-visible {
    background-color: var(--btn-leucht-dark);
    background-image: linear-gradient(150deg, var(--btn-leucht-dark), var(--btn-leucht-tief));
    border-color: var(--btn-leucht-tief);
    color: #fff;
}

/* ==========================================================================
   WÄHREND ETWAS NACHKOMMT (22.08.2026)

   Die Startseite holt sich Eingänge nach (dashboard_status.php im
   Minutentakt). Bisher stand dort nichts und dann plötzlich die Zahl. Der
   wandernde Schimmer sagt „gleich" – und dieselbe Wartezeit fühlt sich
   kürzer an, ohne dass sie kürzer wäre.

   `color: transparent` statt leerem Text: So behält der Platzhalter die
   Größe des Textes, der gleich dasteht, und die Karte springt beim Ankommen
   nicht.

   1,4 s LINEAR: Ein Schimmer ist eine Bewegung ohne Anfang und Ende – jede
   Beschleunigungskurve machte daraus ein Pulsieren. Das ist der einzige Ort
   in der Anwendung, an dem `linear` richtig ist.
   ========================================================================== */
.laedt {
    color: transparent !important;
    border-radius: var(--r-sm);
    background-image: linear-gradient(90deg,
        var(--btn-gray-bg) 25%,
        var(--brand-surface) 37%,
        var(--btn-gray-bg) 63%);
    background-size: 400% 100%;
    animation: schimmer 1.4s linear infinite;
    /* Ein Platzhalter ist kein Text – niemand soll ihn markieren können. */
    user-select: none;
}
.laedt * { visibility: hidden; }
@keyframes schimmer {
    from { background-position: 100% 0; }
    to   { background-position: 0 0; }
}
@media (prefers-reduced-motion: reduce) {
    /* Ohne Bewegung bleibt die Fläche stehen: Sie sagt weiterhin „hier kommt
       etwas", nur ohne zu wandern. */
    .laedt { animation: none; background-position: 50% 0; }
}

/* Ein Inhalt, der ausgetauscht wurde, blendet auf statt zu springen
   (assets/js/dashboard-eingaenge.js, 22.08.2026). Nur die Deckkraft und ein
   Pixel Weg – mehr wäre eine Vorstellung, und die Karte wechselt im
   Minutentakt. */
.ist-gewechselt { animation: inhaltAuf var(--t-base) var(--ease-out); }
@keyframes inhaltAuf {
    from { opacity: 0; transform: translateY(2px); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .ist-gewechselt { animation: none; }
}

/* ==========================================================================
   WO MAN GERADE IST – der Knopf der eigenen Seite (22.08.2026)

   Elf Modulknöpfe, alle im selben Grau: Der Knopf der Seite, auf der man
   steht, sah aus wie die zehn anderen. Ein Plättchen in der Tönung des
   Hauses genügt – kein Rahmen, keine Fettschrift, keine Farbe mehr als die,
   die die Anwendung ohnehin für „ausgewählt" benutzt.

   SPEZIFITÄT: Der Ruhezustand kommt aus
   `.site-navbar .nav-knopfleiste > .btn-outline-secondary` (0,3,0) – deshalb
   steht der Anzustand hier mit demselben Vorlauf. Dieselbe Falle wie beim
   Melder-Knopf ein paar Zeilen weiter unten.
   ========================================================================== */
.site-navbar .nav-knopfleiste > .btn.ist-hier,
.site-navbar .nav-knopfleiste > .btn.ist-hier:hover {
    background-color: var(--blau-hell);
    border-color: var(--blau-rand);
    color: var(--btn-leucht-tief);
}
.site-navbar .nav-knopfleiste > .btn.ist-hier svg { color: var(--btn-leucht-tief); }

/* ==========================================================================
   Darstellung hell/dunkel – der Knopf rechts in der Kopfleiste
   (includes/header.php, includes/farbschema.php).

   Ein <details> mit einem <summary>, das wie ein Zeichenknopf aussieht: So
   klappt das Menü auch ohne JavaScript auf. Der Pfeil, den der Browser von
   sich aus an ein <summary> setzt, muss dafür weg – in beiden Schreibweisen,
   denn WebKit kennt nur ::-webkit-details-marker.
   ========================================================================== */
.fs-wahl { position: relative; display: inline-flex; }
.fs-knopf { list-style: none; cursor: pointer; }
.fs-knopf::-webkit-details-marker { display: none; }
.fs-knopf::marker { content: ""; }
/* Aufgeklappt sieht der Knopf aus wie gedrückt – sonst wäre nicht zu sehen,
   wozu das Menü darunter gehört. */
.fs-wahl[open] > .fs-knopf {
    background-color: var(--blau-hell);
    border-color: var(--blau-rand);
    color: var(--btn-leucht-tief);
}
.fs-menu {
    position: absolute;
    top: calc(100% + var(--sp-2));
    right: 0;
    z-index: 1040;
    min-width: 15rem;
    padding: var(--sp-2);
    border: 1px solid var(--brand-border);
    border-radius: var(--r-card);
    background: var(--brand-surface);
    box-shadow: var(--sh-3);
}
.fs-menu form { display: grid; gap: 2px; margin: 0; }
.fs-eintrag {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    width: 100%;
    padding: var(--sp-3);
    border: 0;
    border-radius: var(--r-ctl);
    background: transparent;
    color: var(--brand-text);
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: background-color var(--t-fast) var(--ease-out);
}
.fs-eintrag > svg { flex: none; color: var(--brand-quiet); }
.fs-eintrag b { display: block; font-size: var(--fs-6); font-weight: 600; line-height: 1.3; }
.fs-eintrag small { display: block; font-size: var(--fs-4); color: var(--brand-faint); }
@media (hover: hover) and (pointer: fine) {
    .fs-eintrag:hover { background: var(--brand-row); }
}
.fs-eintrag:focus-visible { outline: 2px solid var(--focus-col); outline-offset: -2px; }
/* Die getroffene Wahl. Sie trägt die Tönung des Hauses und nicht nur ein
   Häkchen: In einem Menü aus drei Zeilen, die alle gleich aussehen, ist die
   Fläche schneller zu lesen als ein Zeichen am Rand. */
.fs-eintrag.is-an {
    background: var(--blau-hell);
    color: var(--btn-leucht-tief);
}
.fs-eintrag.is-an > svg { color: var(--btn-leucht-tief); }
.fs-eintrag.is-an small { color: var(--btn-leucht-tief); opacity: 0.8; }

/* ==========================================================================
   Uhr und Wetter neben der Marke
   (includes/uhr.php, includes/wetter.php, assets/js/uhr.js, wetter.js)
   --------------------------------------------------------------------------
   EIN PLATZ FÜR BEIDE, und er ist es, der sie an der Marke hält: Die Spur der
   Leiste ist ein Flexcontainer mit space-between; mit drei Kindern (Marke,
   Auskünfte, Knopfreihe) rückte das mittlere in die Mitte des Bildschirms,
   weit weg von dem, wozu es gehört. `margin-inline-end: auto` schiebt die
   ganze Restbreite dahinter.

   Dass es EIN Platz ist und nicht zwei Kinder nebeneinander, hat denselben
   Grund: Wer die Uhr abschaltet, bekäme sonst ein Wetter, das in die Mitte
   wandert.
   ========================================================================== */
.kopf-neben {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
    margin-inline-start: var(--sp-4);
    margin-inline-end: auto;
    /* Der Platz darf schrumpfen, aber nicht wachsen: Wenn die Leiste eng wird,
       sollen die Modulknöpfe den Raum bekommen, nicht die Gradzahl. */
    flex: 0 1 auto;
    min-width: 0;
}
/* Unter 768px steht die Leiste zweizeilig (Marke oben, Knöpfe darunter). Uhr
   und Wetter drängten sich dort in die Zeile der Marke und quetschten den
   Schriftzug – auf dem Telefon stehen sie deshalb nicht. Die Uhrzeit hat das
   Telefon ohnehin in seiner eigenen Leiste, und die Handy-App (mobil.php)
   bringt ihre eigene Kopfzeile mit. */
@media (max-width: 767.98px) {
    .kopf-neben { display: none; }
}

/* --- Die Uhr --------------------------------------------------------------
   Zeichen und Zahl, sonst nichts – sie ist kein Knopf und tut auch nichts,
   wenn man sie anfasst. Das volle Datum steht im title.

   TABELLENZIFFERN sind hier keine Feinheit, sondern der ganze Punkt: Ohne sie
   ist die „1" schmaler als die „8", und die Uhr zappelte bei jedem
   Minutenwechsel um ein, zwei Pixel – mit ihr die Marke daneben gleich mit. */
.kopf-uhr {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem var(--sp-3);
    color: var(--brand-quiet);
    white-space: nowrap;
}
.kopf-uhr[hidden] { display: none; }
/* Das Zifferblatt (includes/uhr.php). Es darf einen Tick größer sein als das
   Strichzeichen, das hier bis zum 25.08.2026 stand: Ein Kreis mit Zeigern
   braucht Fläche, sonst sind die Zeiger nur noch ein Punkt. */
.uhr-zeichen { display: inline-flex; }
.uhr-zeichen svg { width: 22px; height: 22px; }
.uhr-zeit {
    font-size: var(--fs-5);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--brand-text);
}

/* --- Das Wetter -----------------------------------------------------------
   Gebaut wie die Darstellungswahl weiter oben: ein <details>, dessen
   <summary> wie ein Knopf aussieht. Wer das eine kennt, kennt das andere –
   und ohne JavaScript klappt beides auf.

   ZWEI UNTERSCHIEDE, und beide haben einen Grund:
   1. Es steht LINKS, also klappt der Kasten nach links aus (left statt right).
      Ein Menü, das nach rechts über die halbe Leiste läuft, verdeckte die
      Modulknöpfe.
   2. Der Knopf trägt keinen Rand und keine Fläche. Er ist keine Aktion,
      sondern eine Auskunft – dieselbe Haltung wie bei den Modulknöpfen, die
      in dieser Leiste ebenfalls nur ihr Zeichen tragen.
   -------------------------------------------------------------------------- */
.kopf-wetter {
    display: flex;
    align-items: center;
    min-width: 0;
}
/* Ausgeblendet im Anpassen-Modus („Ansicht anpassen", Knopf „Wetter"). Zwar
   trägt schon Bootstraps [hidden] ein !important und gewänne auch so – aber
   das display:flex darüber ist stärker als die eingebaute Regel des Browsers,
   und darauf will sich eine Sichtbarkeit nicht verlassen müssen. */
.kopf-wetter[hidden] { display: none; }
.wetter-wahl { position: relative; display: inline-flex; }
.wetter-knopf {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-height: 34px;
    padding: 0.2rem var(--sp-3);
    border-radius: var(--r-ctl);
    color: var(--brand-quiet);
    list-style: none;
    cursor: pointer;
    transition: background-color var(--t-fast) var(--ease-out);
}
/* Der Pfeil, den der Browser von sich aus an ein <summary> setzt – in beiden
   Schreibweisen, denn WebKit kennt nur ::-webkit-details-marker. */
.wetter-knopf::-webkit-details-marker { display: none; }
.wetter-knopf::marker { content: ""; }
@media (hover: hover) and (pointer: fine) {
    .wetter-knopf:hover { background-color: var(--blau-hauch); color: var(--btn-leucht-tief); }
}
.wetter-knopf:focus-visible { outline: 2px solid var(--focus-col); outline-offset: 2px; }
.wetter-wahl[open] > .wetter-knopf {
    background-color: var(--blau-hell);
    color: var(--btn-leucht-tief);
}
/* Das Wetterbild (wetterBild(), includes/wetter.php) – gezeichnet und in
   Farbe, nicht gestrichelt wie die Zeichen der Knöpfe daneben. Der Grund
   dafür steht dort; hier steht nur die Größe. */
.wetter-zeichen { display: inline-flex; }
.wetter-zeichen svg { width: 24px; height: 24px; }
/* Tabellenziffern: Die Zahl wechselt alle halbe Stunde, und ohne sie
   verschöbe sich bei jedem Wechsel von 9° auf 11° die ganze Marke daneben. */
.wetter-grad {
    font-size: var(--fs-5);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--brand-text);
}
.wetter-menu {
    position: absolute;
    top: calc(100% + var(--sp-2));
    left: 0;
    z-index: 1040;
    /* 17rem und nicht 14: Seit dem 25.08.2026 stehen unter der Vorhersage zwei
       Eingabefelder (der eigene Ort). In 14rem stünde die PLZ neben einem
       Ortsfeld von zwei Zentimetern. */
    min-width: 17rem;
    padding: var(--sp-3);
    border: 1px solid var(--brand-border);
    border-radius: var(--r-card);
    background: var(--brand-surface);
    box-shadow: var(--sh-3);
}
.wetter-kopf { margin-bottom: var(--sp-3); }
.wetter-kopf b { display: block; font-size: var(--fs-6); font-weight: 600; line-height: 1.3; }
.wetter-kopf small { display: block; font-size: var(--fs-4); color: var(--brand-faint); }
.wetter-tage { margin: 0; padding: 0; list-style: none; }
/* Drei Spalten, feste Ordnung: Tag – Zeichen – Grad. Die Zeichenspalte ist
   deshalb so schmal wie ihr Inhalt und die Gradspalte rechtsbündig; sonst
   stünden die Zahlen von drei Tagen an drei Stellen. */
.wetter-tage li {
    display: grid;
    grid-template-columns: 1fr auto 4.5rem;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-2) 0;
    border-top: 1px solid var(--brand-border);
}
.wetter-tage li:first-child { border-top: 0; }
.wt-name { font-size: var(--fs-4); color: var(--brand-text); }
/* Die drei Tage tragen dieselben Bilder, eine Spur kleiner. Eine Farbe
   bekommen sie nicht mehr mit (die Bilder bringen ihre eigene). */
.wt-zeichen { display: inline-flex; }
.wt-zeichen svg { width: 22px; height: 22px; }
.wt-grad {
    text-align: right;
    font-size: var(--fs-4);
    font-variant-numeric: tabular-nums;
    color: var(--brand-faint);
}
.wt-grad b { font-weight: 600; color: var(--brand-text); }
.wetter-quelle {
    display: block;
    margin-top: var(--sp-3);
    font-size: var(--fs-3);
    color: var(--brand-faint);
}

/* --- Der eigene Ort (includes/wetter.php, wetterOrtFormular()) -------------
   Zwei Felder unter der Vorhersage, zugeklappt, solange ein Ort feststeht.
   Ein Formular, das jedes Mal offen stünde, machte aus einer Auskunft eine
   Einstellungsseite – und angesehen wird das Wetter hundertmal öfter, als
   der Ort gewechselt wird.

   Der Kasten ist deshalb auch nur so breit, wie die Vorhersage ihn ohnehin
   macht: Die PLZ bekommt eine feste schmale Spalte, der Ortsname den Rest.
   -------------------------------------------------------------------------- */
.wetter-ort { margin-top: var(--sp-3); border-top: 1px solid var(--brand-border); padding-top: var(--sp-2); }
.wo-knopf {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.15rem 0;
    font-size: var(--fs-3);
    color: var(--brand-quiet);
    list-style: none;
    cursor: pointer;
}
.wo-knopf::-webkit-details-marker { display: none; }
.wo-knopf::marker { content: ""; }
@media (hover: hover) and (pointer: fine) {
    .wo-knopf:hover { color: var(--btn-leucht-dark); }
}
.wo-knopf:focus-visible { outline: 2px solid var(--focus-col); outline-offset: 2px; }
.wo-knopf svg { width: 14px; height: 14px; }
.wo-form { margin-top: var(--sp-2); }
.wo-zeile { display: flex; gap: var(--sp-2); }
.wo-feld { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.wo-feld > span { font-size: var(--fs-2); color: var(--brand-faint); }
.wo-plz { flex: 0 0 4.6rem; }
.wo-ortsname { flex: 1 1 auto; }
/* Die Felder selbst sind gewöhnliche .form-control – nur eine Spur flacher,
   weil sie in einem Aufklapper stehen und nicht in einem Formular. Alles
   andere (Rand, Fläche, dunkle Fassung) kommt von dort, wo es für die ganze
   Anwendung steht. */
.wo-feld .form-control { min-height: 1.9rem; padding: 0.2rem 0.5rem; font-size: var(--fs-4); }
.wo-knoepfe {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    margin-top: var(--sp-2);
}
/* „Wieder die Agentur" ist die Rücknahme und kein zweiter Weg: Sie sieht aus
   wie ein Verweis, nicht wie ein Knopf – sonst stünden zwei gleich laute
   Möglichkeiten nebeneinander, von denen eine fast nie gemeint ist. */
.wo-zurueck {
    padding: 0;
    border: 0;
    background: none;
    font-size: var(--fs-3);
    color: var(--brand-quiet);
    text-decoration: underline;
    cursor: pointer;
}
@media (hover: hover) and (pointer: fine) {
    .wo-zurueck:hover { color: var(--btn-leucht-dark); }
}
.wo-hinweis {
    margin: var(--sp-2) 0 0;
    font-size: var(--fs-3);
    color: var(--brand-quiet);
}
/* Das Fenster „Wetterort" (index.php, wetterOrtFenster()). Der Rahmen kommt
   von .bd-overlay/.bd-dialog wie beim Hintergrund, die Breite von dessen
   kleiner Stufe (.bd-dialog-sm) – zwei Felder brauchen keine 860 Pixel. Hier
   steht nur, was drinnen anders liegt als im Aufklapper der Kopfleiste. */
.wo-dialog .wo-form { margin-top: 0; }
.wo-dialog .wo-zeile { gap: var(--sp-3); }
.wo-dialog .wo-plz { flex: 0 0 6rem; }
.wo-erklaerung {
    margin: 0 0 var(--sp-4);
    font-size: var(--fs-4);
    color: var(--brand-quiet);
}
.wo-vorgabe { margin: var(--sp-4) 0 0; font-size: var(--fs-3); }
.wo-vorgabe b { color: var(--brand-text); }

/* Der Platz ohne jeden Ort: Dort steht die Nadel allein im Knopf, ohne
   Gradzahl daneben – es gibt ja keine. Sie ist ein Strichzeichen und kein
   Wetterbild, weil sie kein Wetter behauptet. */
.wetter-nadel { color: var(--brand-quiet); }
.wetter-nadel svg { width: 20px; height: 20px; }

/* Uhrzeit-Auswahl (assets/js/timepicker.js) – dieselbe Sprache wie der
   Datepicker, nur als Liste in Viertelstunden statt als Raster. */
.tp-input {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23678595' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3 2'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.6rem center;
    background-size: 17px 17px;
    padding-right: 2.1rem;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    background-color: var(--brand-surface);
}
.tp-popup {
    position: absolute;
    /* Über allem, auch über den Dialogen (.bd-overlay: 1060) – im Fenster
       „Neuer Termin" (calendar.php) hängen beide Uhrzeitfelder darin.
       Mit 1050 ging die Liste hinter dem Fenster auf. Dieselbe Falle wie
       beim Datepicker, siehe .dp-popup. */
    z-index: 1100;
    width: 178px;
    background-color: var(--brand-surface);
    border: 1px solid var(--brand-border);
    border-radius: var(--r-card);
    box-shadow: var(--shadow-pop);
    padding: 0.3rem;
    font-family: 'Plus Jakarta Sans', 'IBM Plex Sans', sans-serif;
}
.tp-liste {
    max-height: 244px;
    overflow-y: auto;
    overscroll-behavior: contain;
}
.tp-liste::-webkit-scrollbar { width: 8px; }
.tp-liste::-webkit-scrollbar-thumb { background: var(--brand-border); border-radius: 4px; }
.tp-item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-3);
    width: 100%;
    padding: 0.3rem 0.55rem;
    border: none;
    border-radius: var(--r-sm);
    background-color: transparent;
    color: var(--brand-text);
    font-size: var(--fs-6);
    font-variant-numeric: tabular-nums;
    text-align: left;
    cursor: pointer;
    transition: background-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.tp-item:hover { background-color: var(--blau-hell); }
.tp-zeit { font-weight: 600; }
.tp-dauer { font-size: var(--fs-3); color: var(--brand-faint); }
.tp-item:hover .tp-dauer { color: var(--brand-quiet); }
.tp-item.is-gewaehlt,
.tp-item.is-gewaehlt:hover { background-color: var(--btn-leucht-dark); color: #fff; }
.tp-item.is-gewaehlt .tp-dauer { color: rgba(255, 255, 255, 0.75); }

/* Empfängervorschläge im Postfach (assets/js/mail-empfaenger.js).
   Derselbe Kasten wie die Uhrzeitliste, nur dreizeilig: Name, Adresse,
   Herkunft. Die Breite setzt das JavaScript auf die des Feldes.
   z-index über .bd-overlay (1060), weil die Liste im Dialog „Neue E-Mail"
   aufgeht – dieselbe Falle wie beim Datepicker, siehe .dp-popup. */
.mk-popup {
    position: absolute;
    z-index: 1100;
    max-height: 320px;
    overflow-y: auto;
    overscroll-behavior: contain;
    background-color: var(--brand-surface);
    border: 1px solid var(--brand-border);
    border-radius: var(--r-card);
    box-shadow: var(--shadow-pop);
    padding: 0.3rem;
    font-family: 'Plus Jakarta Sans', 'IBM Plex Sans', sans-serif;
}
.mk-popup::-webkit-scrollbar { width: 8px; }
.mk-popup::-webkit-scrollbar-thumb { background: var(--brand-border); border-radius: 4px; }
.mk-item {
    display: block;
    width: 100%;
    padding: 0.35rem 0.55rem;
    border: none;
    border-radius: var(--r-sm);
    background-color: transparent;
    color: var(--brand-text);
    text-align: left;
    cursor: pointer;
    transition: background-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.mk-item:hover,
.mk-item.is-aktiv { background-color: var(--blau-hell); }
.mk-name {
    display: block;
    font-size: var(--fs-6);
    font-weight: 600;
    line-height: 1.3;
}
.mk-zusatz {
    font-weight: 500;
    font-size: var(--fs-3);
    color: var(--brand-quiet);
    margin-left: 0.35rem;
}
.mk-mail {
    display: block;
    font-size: var(--fs-5);
    color: var(--btn-blue-dark);
    line-height: 1.3;
    overflow-wrap: anywhere;
}
.mk-quelle {
    display: block;
    font-size: var(--fs-3);
    color: var(--brand-faint);
    line-height: 1.3;
}

.alert {
    border-radius: var(--r-card);
    border-width: 1px;
    padding: var(--sp-4) var(--sp-5);
    font-size: var(--fs-6);
}
/* Meldungen stehen nie direkt auf der nächsten Karte. */
.alert:not(:last-child) { margin-bottom: var(--sp-5); }

.badge-accent {
    background-color: var(--brand-accent) !important;
    color: var(--auf-marke);
}

.badge {
    font-weight: 600;
    border-radius: var(--r-sm);
    padding: 0.32em 0.55em;
    font-size: var(--fs-3);
}
/* Look B kennt keine Pillen – Bootstrap-Utility wird eingefangen */
.badge.rounded-pill {
    border-radius: var(--r-sm) !important;
}
.badge-soft-green {
    background-color: var(--btn-green-bg-light);
    color: var(--btn-green);
}
.badge-soft-blue {
    background-color: var(--btn-blue-bg-light);
    color: var(--btn-blue-dark);
}
.badge-soft-red {
    background-color: var(--btn-red-bg-light);
    color: var(--btn-red-text);
}
.badge-soft-gray {
    background-color: var(--btn-gray-bg);
    color: var(--brand-text);
}
.badge-soft-orange {
    background-color: var(--btn-orange-bg-light);
    color: var(--btn-orange-text);
}

/* ==========================================================================
   DER PUNKT VOR DEM ZUSTAND (22.08.2026)

   Die fünf Töne oben sagen den Stand einer Anfrage („neu", „in Arbeit",
   „abgeschlossen"). Sie sagen ihn ALLEIN ÜBER DIE FARBE – und rund acht
   Prozent der Männer unterscheiden Rot und Grün nicht zuverlässig. Für sie
   ist eine Spalte aus fünf blassen Kästchen eine Spalte aus fünf blassen
   Kästchen; das Wort darin müssen sie lesen, Zeile für Zeile.

   Der Punkt in derselben Farbe ändert daran nichts an der Lesbarkeit – aber
   er macht aus dem Kästchen einen ZUSTAND: Man sieht auf einen Blick, dass
   diese Spalte einen Stand führt, und findet die Zeile, die anders ist, an
   der Form und nicht am Ton.

   `currentColor`, damit jeder der fünf Töne seinen eigenen Punkt bekommt,
   ohne dass die Liste ein zweites Mal dasteht. `flex: none`, sonst quetscht
   ihn ein langes Wort auf einen Strich.

   AN DER BEDEUTUNG FESTGEMACHT, NICHT AN DER FARBE: `.badge-soft-*` steht an
   81 Stellen und meint längst nicht überall einen Zustand – im Seitenkopf
   ist es ein Zähler („612 Kontakte"), anderswo eine Kennzeichnung. Ein Punkt
   davor wäre dort Zierrat. Die Klasse `.ist-stand` setzen nur die sechs
   Funktionen, die einen BEARBEITUNGSSTAND zurückgeben
   (leadStatusBadgeClass(), bewerbungStatusBadgeClass(),
   formularStatusBadgeClass(), statusBadgeClass(), bavStatusBadgeClass(),
   bkvStatusBadgeClass()) – damit greift sie überall dort von selbst, wo ein
   Stand steht, und nirgends sonst.
   ========================================================================== */
.badge.ist-stand {
    display: inline-flex;
    align-items: center;
    gap: 0.4em;
}
.badge.ist-stand::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}

.alert-accent {
    background-color: var(--brand-chip-bg);
    border: 1px solid var(--brand-accent);
    color: var(--brand-text);
}

/* Freundlicher Hinweis (z. B. Geburtstag) – Rot bleibt den echten Ausnahmen. */
.alert-hinweis {
    background-color: var(--btn-blue-bg-light);
    border: 1px solid var(--brand-line-strong);
    color: var(--brand-text);
}

.border-accent {
    border-color: var(--brand-accent) !important;
}

.table-accent-row {
    background-color: var(--brand-chip-bg) !important;
}

/* HIER STAND DIE SCHRITTANZEIGE DES FIRMEN-ASSISTENTEN (.wizard-steps,
   .wizard-step-circle, .step-label) – 44 Zeilen für eine Seite, die es nicht
   mehr gibt. Was vom Assistenten geblieben ist, ist sein Bogen (.wizard-card,
   direkt darunter): Der trägt heute jedes Formular der Anwendung. Entfernt am
   23.08.2026. */

/* Der Formularbogen. Er hieß nach dem Assistenten, in dem er entstanden ist,
   trägt aber seit dem 10.08.2026 jedes Formular der Anwendung: Ein Bogen mit
   zwanzig Feldern lag vorher auf sechs Seiten nackt auf dem Seitengrund,
   während die Nachbarseite denselben Bogen in einer Karte zeigte – zwei
   Auskünfte darüber, wo das Formular anfängt und wo es aufhört. */
.wizard-card {
    background-color: var(--brand-surface);
    border: 1px solid var(--brand-border);
    border-radius: var(--r-card);
    box-shadow: var(--sh-1);
    padding: var(--sp-7);
}
/* Die Knopfzeile am Fuß eines Bogens: abgesetzt statt angeklebt. */
.wizard-card > .form-aktionen,
.form-aktionen {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-3);
    margin-top: var(--sp-6);
    padding-top: var(--sp-5);
    border-top: 1px solid var(--brand-border);
}

/* --------------------------------------------------------------------------
   Terminformular: der Zeitraum als ein zusammenhängender Block.
   Vorher standen Startdatum, Startzeit, Enddatum und Endzeit als vier gleich
   große Felder nebeneinander – vier Fragen, wo es eine ist. Jetzt: ein Kasten,
   „Datum – von – bis", Dauer als Knöpfe, und das Enddatum erscheint nur, wenn
   der Termin wirklich an einem anderen Tag endet.
   -------------------------------------------------------------------------- */
.zeit-box {
    border: 1px solid var(--brand-border);
    border-radius: var(--r-ctl);
    background-color: var(--brand-bg);
    padding: 0.8rem 0.95rem 0.9rem;
}
.zeit-kopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    margin-bottom: 0.7rem;
}
.zeit-titel {
    font-size: var(--fs-3);
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--brand-quiet);
}
.zeit-zeile {
    display: flex;
    align-items: flex-end;
    gap: 0.55rem;
    flex-wrap: wrap;
}
.zeit-feld {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.zeit-label {
    font-size: var(--fs-2);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--brand-faint);
}
.zeit-datum { flex: 0 1 170px; }
.zeit-uhr { flex: 0 0 116px; }
.zeit-box .form-control { height: var(--h-ctl); background-color: var(--brand-surface); }
.zeit-bis {
    padding-bottom: 0.55rem;
    color: var(--brand-faint);
    font-weight: 700;
}
.zeit-fuss {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
    margin-top: 0.8rem;
}
.zeit-dauer { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.zeit-chip {
    height: 26px;
    padding: 0 0.62rem;
    border: 1px solid var(--brand-line-strong);
    border-radius: var(--r-pill);
    background-color: var(--brand-surface);
    color: var(--brand-quiet);
    font-size: var(--fs-3);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    transition: background-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out);
}
/* ZUR FARBE (22.08.2026): Die Wahl-Chips (Dauer, Wochentage, Zeichenwahl,
   Bezug) trugen das Blaugrau des Hauses. Sie sind Schalter wie der
   Segmentschalter über jeder Liste und tragen deshalb dieselbe Fassung:
   Tönung unter dem Zeiger, tiefes Leuchtblau am Gewählten. */
.zeit-chip:hover { background-color: var(--blau-hell); color: var(--btn-leucht-tief); }
.zeit-chip.active {
    background-color: var(--btn-leucht-dark);
    border-color: var(--btn-leucht-dark);
    color: #fff;
}
.zeit-link {
    padding: 0;
    border: 0;
    background: none;
    color: var(--btn-blue-dark);
    font-size: var(--fs-4);
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}
.zeit-link:hover { color: var(--brand-text); }
/* Der leise Satz am Fuß des Kastens – bei der Erinnerung steht dort, was der
   Vorlauf bewirkt. Kein `.form-text`: Der Kasten hat seinen eigenen Grund,
   und der Satz gehört hinein, nicht darunter. */
.zeit-hinweis {
    font-size: var(--fs-4);
    color: var(--brand-quiet);
    line-height: 1.4;
}
/* Ausgeblendete Felder sind Flex-Kinder – ohne das gewinnt display:flex */
.zeit-box [hidden] { display: none !important; }

/* --------------------------------------------------------------------------
   Terminformular: das Zeichen vor dem Titel.
   Ein Knopf links neben dem Titelfeld – so, wie der Termin nachher im Raster
   aussieht. Aufgeklappt wird über <details>; die Tafel liegt darüber und
   schiebt das Formular nicht auseinander.
   -------------------------------------------------------------------------- */
.titel-zeile {
    display: flex;
    align-items: stretch;
    gap: var(--sp-3);
}
.titel-zeile .form-control { flex: 1 1 auto; min-width: 0; }

.emoji-wahl { position: relative; flex: 0 0 auto; }
.emoji-knopf {
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--h-ctl);
    height: var(--h-ctl);
    border: 1px solid var(--brand-line-strong);
    border-radius: var(--r-ctl);
    background-color: var(--brand-surface);
    color: var(--brand-faint);
    cursor: pointer;
    list-style: none;
    transition: border-color var(--t-fast) var(--ease-out), background-color var(--t-fast) var(--ease-out);
}
/* Das Dreieck der Klappe gehört hier nicht hin – der Knopf ist das Zeichen. */
.emoji-knopf::-webkit-details-marker { display: none; }
.emoji-knopf::marker { content: ''; }
.emoji-knopf:hover { border-color: var(--blau-rand); background-color: var(--blau-hell); }
.emoji-wahl[open] .emoji-knopf { border-color: var(--btn-leucht-dark); background-color: var(--blau-hell); }
.emoji-knopf:focus-visible { box-shadow: var(--focus-ring); outline: none; }
.emoji-knopf-zeichen {
    font-size: var(--fs-9);
    line-height: 1;
    /* Die Emoji-Schriften des Systems zuerst – ohne sie zeichnet manche
       Textschrift ein leeres Kästchen statt des Bildes. */
    font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
}

.emoji-tafel {
    position: absolute;
    z-index: 40;
    top: calc(100% + 6px);
    left: 0;
    width: min(340px, calc(100vw - 3rem));
    max-height: 320px;
    overflow-y: auto;
    padding: 0.7rem 0.8rem 0.8rem;
    border: 1px solid var(--brand-border);
    border-radius: var(--r-ctl);
    background-color: var(--brand-surface);
    box-shadow: var(--sh-2);
}
.emoji-tafel-kopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    margin-bottom: 0.6rem;
}
.emoji-gruppe + .emoji-gruppe { margin-top: 0.7rem; }
.emoji-gruppe-name {
    display: block;
    margin-bottom: 0.35rem;
    font-size: var(--fs-2);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--brand-faint);
}
.emoji-felder { display: flex; flex-wrap: wrap; gap: 4px; }

/* Wie die Wochentag-Knöpfe der Wiederholung: Das Optionsfeld ist unsichtbar,
   der Zustand hängt an :has(input:checked). Sonst täte ein Klick sichtbar
   nichts, bis gespeichert ist. */
.emoji-feld,
.emoji-ohne {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    background-color: transparent;
    cursor: pointer;
    transition: background-color var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out);
}
.emoji-feld {
    width: 34px;
    height: 34px;
    font-size: var(--fs-8);
    line-height: 1;
    font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
}
.emoji-ohne {
    height: 26px;
    padding: 0 0.62rem;
    border-color: var(--brand-line-strong);
    border-radius: var(--r-pill);
    background-color: var(--brand-surface);
    color: var(--brand-quiet);
    font-size: var(--fs-3);
    font-weight: 600;
}
.emoji-feld input,
.emoji-ohne input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}
.emoji-feld:hover { background-color: var(--blau-hell); }
.emoji-ohne:hover { background-color: var(--blau-hell); color: var(--btn-leucht-tief); }
.emoji-feld:has(input:checked) {
    border-color: var(--btn-leucht-dark);
    background-color: var(--blau-hell);
}
.emoji-ohne:has(input:checked) {
    background-color: var(--btn-leucht-dark);
    border-color: var(--btn-leucht-dark);
    color: #fff;
}
.emoji-feld:has(input:focus-visible),
.emoji-ohne:has(input:focus-visible) { box-shadow: var(--focus-ring); }

/* --------------------------------------------------------------------------
   Terminformular: die Wiederholung.
   Derselbe Kasten wie der Zeitraum darüber (er erbt dessen Regeln über die
   gemeinsamen Klassen .zeit-kopf/.zeit-label/.zeit-feld), nur tritt er zurück,
   solange nichts wiederholt wird: geschlossene Frage, kein Aufforderung.
   -------------------------------------------------------------------------- */
.serie-box {
    border: 1px solid var(--brand-border);
    border-radius: var(--r-ctl);
    background-color: var(--brand-bg);
    padding: 0.8rem 0.95rem 0.9rem;
}
.serie-box.is-an { border-color: var(--btn-blue); }
.serie-box .form-control,
.serie-box .form-select { height: var(--h-ctl); background-color: var(--brand-surface); }
.serie-box [hidden] { display: none !important; }
.serie-zeile {
    display: flex;
    align-items: flex-end;
    gap: 0.55rem;
    flex-wrap: wrap;
}
.serie-art { flex: 1 1 260px; max-width: 340px; }
.serie-frei { flex: 0 1 210px; }
.serie-frei-zeile { display: flex; gap: 0.4rem; }
.serie-frei-zeile .form-control { width: 68px; }

.serie-tage,
.serie-ende {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-top: var(--sp-4);
}
.serie-tage-chips,
.serie-ende-zeilen {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

/* Wochentag und Auswahl sind Knöpfe, das Kästchen darin ist versteckt. Der
   Zustand hängt an :has(input:checked) und nicht an einer vom Server gesetzten
   Klasse – sonst täte ein Klick sichtbar nichts, bis gespeichert ist (dieselbe
   Falle wie bei den Labels des Aufgaben-Boards). */
.serie-tag,
.serie-wahl {
    display: inline-flex;
    align-items: center;
    height: 28px;
    padding: 0 0.62rem;
    border: 1px solid var(--brand-line-strong);
    border-radius: var(--r-pill);
    background-color: var(--brand-surface);
    color: var(--brand-quiet);
    font-size: var(--fs-4);
    font-weight: 600;
    cursor: pointer;
    transition: background-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out);
}
.serie-tag { min-width: 38px; justify-content: center; }
.serie-tag input,
.serie-wahl input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}
.serie-tag:hover,
.serie-wahl:hover { background-color: var(--blau-hell); color: var(--btn-leucht-tief); }
.serie-tag:has(input:checked),
.serie-wahl:has(input:checked) {
    background-color: var(--btn-leucht-dark);
    border-color: var(--btn-leucht-dark);
    color: #fff;
}
/* Tastaturbedienung: Das Kästchen ist unsichtbar, der Ring gehört deshalb an
   die Umrandung, sonst sieht man beim Durchtabben nicht, wo man steht. */
.serie-tag:has(input:focus-visible),
.serie-wahl:has(input:focus-visible) { box-shadow: var(--focus-ring); }

.serie-ende-zeilen .form-control { width: 148px; }
.serie-ende-zeilen .serie-anzahl { width: 72px; }
.serie-nach { font-size: var(--fs-5); color: var(--brand-quiet); }

/* Der Hinweis über dem Formular: worauf ein Speichern gleich wirkt. */
.serie-hinweis {
    display: flex;
    align-items: flex-start;
    gap: 0.7rem;
    flex-wrap: wrap;
    border: 1px solid var(--brand-border);
    border-left: 3px solid var(--btn-blue);
    border-radius: var(--r-ctl);
    background-color: var(--brand-bg);
    padding: 0.7rem 0.9rem;
    margin-bottom: var(--sp-5);
}
.serie-hinweis-icon { color: var(--btn-blue-dark); line-height: 1; padding-top: 2px; }
.serie-hinweis-text {
    flex: 1 1 300px;
    font-size: var(--fs-5);
    line-height: 1.5;
    color: var(--brand-quiet);
}
.serie-hinweis-text strong { display: block; color: var(--brand-text); }
.serie-hinweis-wege { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.serie-hinweis-wege a {
    display: inline-flex;
    align-items: center;
    height: 28px;
    padding: 0 0.7rem;
    border: 1px solid var(--brand-line-strong);
    border-radius: var(--r-pill);
    background-color: var(--brand-surface);
    color: var(--brand-quiet);
    font-size: var(--fs-4);
    font-weight: 600;
    text-decoration: none;
}
.serie-hinweis-wege a:hover {
    background-color: var(--btn-blue-bg-light);
    border-color: var(--btn-blue);
    color: var(--brand-text);
}

.person-photo {
    height: 128px;
    width: 128px;
    object-fit: cover;
    border-radius: var(--r-card);
    border: 1px solid var(--brand-border);
}
.person-photo-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--btn-blue-bg-light);
    color: var(--btn-blue-dark);
}

/* ==========================================================================
   Datenschutz-Blase (datenschutzHinweis() in includes/functions.php)

   Steht bewusst hier und nicht in termin.css: Sie wird auf der Terminierung,
   auf der Landingpage und überall sonst gebraucht, style.css lädt jede Seite.
   Helle Karte statt dunkler – der Fuß der Landingpage ist selbst dunkel.
   ========================================================================== */
.ds-hinweis {
    position: relative;
    display: inline-block;
    cursor: help;
    border-bottom: 1px dotted currentColor;
}

.ds-blase {
    position: absolute;
    bottom: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    width: min(320px, 80vw);
    padding: 13px 15px;
    /* Leicht durchscheinend statt deckend: Die Blase legt sich damit über den
       Untergrund, ohne ihn wie ein Fremdkörper auszustanzen. Der Weichzeichner
       hält den Text trotzdem lesbar – auch über der dunklen Landingpage. */
    background: rgba(255, 255, 255, .8);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    color: var(--brand-text);
    border: 1px solid rgba(227, 232, 238, .8);
    border-radius: var(--r-card);
    box-shadow: 0 14px 34px rgba(13, 26, 36, .22);
    font-size: var(--fs-5);
    line-height: 1.55;
    font-weight: 400;
    text-align: left;
    text-transform: none;
    letter-spacing: 0;
    white-space: normal;
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out), visibility var(--t-fast) var(--ease-out);
    z-index: 60;
}

/* Der Zeiger schließt zugleich die Lücke nach unten, damit die Blase beim
   Hinüberfahren mit der Maus nicht verschwindet. */
.ds-blase::after,
.ds-blase::before {
    content: '';
    position: absolute;
    top: 100%;
    left: 50%;
    margin-left: -8px;
    border: 8px solid transparent;
    border-top-color: rgba(227, 232, 238, .8);
}

/* Deckt den Rand des Zeigers ab – gleiche Deckkraft wie die Blase, sonst
   entstünde an der Spitze ein hellerer Fleck. Der Zeiger kann den Untergrund
   nicht weichzeichnen (backdrop-filter wirkt nicht auf Rahmenflächen), bei
   dieser Größe fällt das aber nicht auf. */
.ds-blase::before { margin-top: -1px; border-top-color: rgba(255, 255, 255, .8); z-index: 1; }

/* Eine Klasse mehr, damit nichts von der Gastseite hereinfärbt: Im Fuß der
   Landingpage gilt `.lp-footer strong { color: #fff }` – auf der hellen Karte
   wäre die Überschrift damit unsichtbar. Gleiches gilt für den Fließtext. */
.ds-hinweis .ds-blase { color: var(--brand-text); }

.ds-hinweis .ds-blase strong {
    display: block;
    margin-bottom: 4px;
    color: var(--brand-text);
}

/* Zwei Klassen tief, damit die Regel gewinnt: Die Blase steht im Fuß der
   Landingpage mitten in .lp-footer-links, und dessen `a:hover { color: #fff }`
   ließ den Link auf der hellen Karte unsichtbar werden. Beim Überfahren wird er
   deshalb ausdrücklich dunkler statt heller. */
.ds-hinweis .ds-blase a {
    display: inline-block;
    margin-top: 8px;
    padding: 2px 6px;
    margin-left: -6px;
    border-radius: var(--r-sm);
    color: var(--btn-blue-dark);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.ds-hinweis .ds-blase a:hover,
.ds-hinweis .ds-blase a:focus-visible {
    color: var(--brand-text);
    background: var(--btn-blue-bg-light);
}

.ds-hinweis:hover .ds-blase,
.ds-hinweis:focus .ds-blase,
.ds-hinweis:focus-within .ds-blase {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}

/* Nahe am Fensterrand würde die mittige Blase heraushängen – dann links bzw.
   rechts ausrichten statt zentrieren. */
.ds-hinweis.ds-links .ds-blase { left: 0; transform: translateX(0) translateY(4px); }
.ds-hinweis.ds-links:hover .ds-blase,
.ds-hinweis.ds-links:focus-within .ds-blase { transform: translateX(0) translateY(0); }
.ds-hinweis.ds-links .ds-blase::after,
.ds-hinweis.ds-links .ds-blase::before { left: 24px; }

/* AUF DEM HANDY EIN BLATT ÜBER DER SEITE, KEINE BLASE (11.08.2026).
   Die Blase ist 320 px breit und hängt mittig unter ihrem Wort. Steht dieses
   Wort am rechten Rand – im Fuß der Landingpages und der Formularstrecke ist
   „Datenschutz" der letzte Link –, ragte sie über das Display hinaus. Und weil
   sie nur `visibility: hidden` ist und nicht `display: none`, ragte sie AUCH
   ZUGEKLAPPT hinaus: Die ganze Seite ließ sich seitwärts schieben, alles
   wackelte beim Scrollen. Genau das sah auf dem Handy „komisch" aus.

   Statt sie kleiner zu rechnen, bekommt sie am schmalen Schirm einen festen
   Platz: unten am Rand, über die volle Breite. Der Zeiger entfällt – er zeigte
   dort auf nichts mehr. Aufgeklappt wird sie unverändert durch Antippen
   (`tabindex="0"` in datenschutzHinweis()), auf dem Handy ist das der einzige
   Weg, denn einen Mauszeiger gibt es nicht. */
@media (max-width: 680px) {
    .ds-blase {
        position: fixed;
        left: 12px;
        right: 12px;
        bottom: 12px;
        top: auto;
        width: auto;
        max-width: none;
        transform: translateY(8px);
        background: rgba(255, 255, 255, .96);
    }

    .ds-hinweis:hover .ds-blase,
    .ds-hinweis:focus .ds-blase,
    .ds-hinweis:focus-within .ds-blase,
    .ds-hinweis.ds-links:hover .ds-blase,
    .ds-hinweis.ds-links:focus-within .ds-blase { transform: translateY(0); }

    .ds-hinweis.ds-links .ds-blase { left: 12px; transform: translateY(8px); }

    .ds-blase::after,
    .ds-blase::before { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    .ds-blase { transition: none; }
}

/* Profilbild als Dateiauswahl (user_form.php): Das Bild trägt in der Mitte ein
   Pluszeichen und öffnet angeklickt den Dateidialog. Das <input type="file">
   bleibt bestehen, ist aber unsichtbar – abgeschaltet oder entfernt würde das
   Formular seinen Anhang verlieren. */
.foto-waehler {
    position: relative;
    display: inline-block;
    cursor: pointer;
    border-radius: var(--r-card);
}

.foto-plus {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 38px;
    height: 38px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: var(--btn-leucht-dark);
    color: #fff;
    box-shadow: 0 2px 8px rgba(13, 26, 36, .28);
    transition: background-color var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out);
}

.foto-plus svg { width: 20px; height: 20px; }

.foto-waehler:hover .foto-plus {
    background: var(--btn-leucht-tief);
    transform: translate(-50%, -50%) scale(1.06);
}

/* Liegt schon ein Bild vor, verdeckt das Pluszeichen es nicht dauerhaft –
   es kommt erst beim Überfahren oder bei Tastaturfokus hervor. */
.foto-waehler:has(img:not(.d-none)) .foto-plus { opacity: 0; }
.foto-waehler:has(img:not(.d-none)):hover .foto-plus,
.foto-waehler:has(img:not(.d-none))::after { opacity: 1; }

.foto-waehler:has(img:not(.d-none))::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: var(--r-card);
    background: rgba(13, 26, 36, .32);
    opacity: 0;
    transition: opacity var(--t-fast) var(--ease-out);
}

.foto-waehler:has(img:not(.d-none)):hover::after { opacity: 1; }
.foto-waehler .foto-plus { z-index: 1; }

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

/* Tastaturbedienung: Ohne sichtbares Feld braucht das Bild den Fokusring. */
.foto-feld-versteckt:focus-visible + .foto-name,
.foto-feld-versteckt:focus-visible ~ .form-text { color: var(--btn-blue-dark); }

.foto-waehler:has(+ .foto-feld-versteckt:focus-visible) {
    outline: 2px solid var(--focus-col);
    outline-offset: 3px;
}

.foto-waehler:has(+ .foto-feld-versteckt:focus-visible) .foto-plus,
.foto-waehler:has(+ .foto-feld-versteckt:focus-visible)::after { opacity: 1; }

.foto-name {
    font-size: var(--fs-5);
    color: var(--brand-quiet);
    text-align: center;
    max-width: 150px;
    overflow-wrap: anywhere;
}

/* „Zuschnitt ändern" – ein Wort, kein Knopf: Es steht unter dem Bild und soll
   den Blick nicht vom Bild wegziehen. Das Element entsteht in
   assets/js/foto-waehler.js, weil es ohne JavaScript nichts zu tun hätte. */
.foto-zuschnitt-knopf {
    margin-top: 2px;
    padding: 2px 6px;
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    color: var(--btn-blue-dark);
    font-size: var(--fs-5);
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}
.foto-zuschnitt-knopf:hover { background: var(--blau-hell); color: var(--btn-leucht-tief); }
.foto-zuschnitt-knopf[disabled] { opacity: .5; cursor: default; }

/* ==========================================================================
   Bild zuschneiden (assets/js/foto-waehler.js)

   Ein eigener Dialog statt eines der vorhandenen: Die Dialoge des Boards
   (.bd-overlay) hängen an dessen Seite, dieser hier gehört zum Bildwähler und
   steht damit überall, wo fotoWaehler() steht. Er liegt bei z-index 1200 –
   über dem Board (1060) und über Datepicker und Vorschlagsliste (1100), denn
   solange er offen ist, gibt es nichts anderes zu bedienen.
   ========================================================================== */
.fw-overlay {
    position: fixed;
    inset: 0;
    z-index: 1200;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--sp-5);
    background: rgba(26, 36, 48, .46);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
}

body.fw-offen { overflow: hidden; }

.fw-dialog {
    width: 100%;
    max-width: 400px;
    max-height: 100%;
    overflow-y: auto;
    background: var(--brand-surface);
    border-radius: var(--r-card);
    box-shadow: var(--sh-3);
}

.fw-kopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    padding: var(--sp-4) var(--sp-5);
    border-bottom: 1px solid var(--brand-border);
}

.fw-titel { margin: 0; font-size: var(--fs-8); font-weight: 600; }

.fw-schliessen {
    width: var(--h-ctl-sm);
    height: var(--h-ctl-sm);
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    color: var(--brand-quiet);
    font-size: var(--fs-9);
    line-height: 1;
    cursor: pointer;
}
.fw-schliessen:hover { background: var(--btn-gray-bg); color: var(--brand-text); }

.fw-body {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-4);
    padding: var(--sp-5);
}

/* Der Rahmen der Bühne trägt denselben Radius wie jedes Gesicht in der
   Anwendung (.person-photo) – man sieht beim Schieben schon, wie das Bild
   später sitzt. Die Maße setzt das Skript, weil sie vom Fenster abhängen. */
.fw-buehne {
    position: relative;
    border-radius: var(--r-card);
    overflow: hidden;
    background: var(--btn-blue-bg-light);
    box-shadow: inset 0 0 0 1px var(--brand-border);
}

.fw-leinwand {
    display: block;
    cursor: grab;
    /* Ohne das übernimmt der Browser Wischen und Kneifen und scrollt die
       Seite, statt den Ausschnitt zu bewegen. */
    touch-action: none;
    user-select: none;
}
.fw-leinwand:active { cursor: grabbing; }
.fw-leinwand:focus-visible { outline: 2px solid var(--focus-col); outline-offset: 2px; }

.fw-regler {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    width: 100%;
    max-width: 340px;
}
/* Der einzige Schieberegler in Look B. Bootstrap färbt ihn blau (#0d6efd) –
   der Griff trägt seit dem 22.08.2026 das helle Blau des Hauses, dasselbe wie
   jeder Knopf und jeder gewählte Reiter. Die Regeln stehen bewusst nur hier:
   Die Regler der Werbeseiten (.lp-range) haben ihre eigene Ebene und sollen
   davon nichts abbekommen. */
.fw-regler .form-range { flex: 1 1 auto; }
.fw-regler .form-range:focus { box-shadow: none; }
.fw-regler .form-range::-webkit-slider-thumb {
    background: var(--btn-leucht-dark);
    box-shadow: 0 1px 3px rgba(13, 26, 36, .3);
}
.fw-regler .form-range::-webkit-slider-thumb:active { background: var(--btn-leucht-tief); }
.fw-regler .form-range::-moz-range-thumb {
    background: var(--btn-leucht-dark);
    border: 0;
}
.fw-regler .form-range::-moz-range-thumb:active { background: var(--btn-leucht-tief); }
.fw-regler .form-range:focus-visible::-webkit-slider-thumb { outline: 2px solid var(--focus-col); outline-offset: 2px; }
.fw-regler .form-range::-webkit-slider-runnable-track { background: var(--btn-gray-border-hover); }
.fw-regler .form-range::-moz-range-track { background: var(--btn-gray-border-hover); }
.fw-regler-zeichen {
    width: 1rem;
    color: var(--brand-quiet);
    font-size: var(--fs-7);
    text-align: center;
}

.fw-hinweis {
    margin: 0;
    color: var(--brand-quiet);
    font-size: var(--fs-5);
    line-height: 1.5;
    text-align: center;
}

.fw-fuss {
    display: flex;
    justify-content: flex-end;
    gap: var(--sp-3);
    padding: var(--sp-4) var(--sp-5);
    border-top: 1px solid var(--brand-border);
}

.text-whatsapp {
    color: #25d366;
}

/* .stat-tile ist in .kpi aufgegangen - siehe Abschnitt Kennzahlenkacheln. */

.avatar-sm {
    height: 36px;
    width: 36px;
    border-radius: var(--r-sm);
    object-fit: cover;
    flex: 0 0 auto;
}
.avatar-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--btn-blue-bg-light);
    color: var(--btn-blue-dark);
    font-family: 'Plus Jakarta Sans', sans-serif;
    font-weight: 700;
    font-size: var(--fs-5);
}
/* Steht statt der Initialen die Silhouette drin, kommt sie mit 15px aus
   icon() – im 36er Rahmen ein Fliegendreck. Dasselbe Verhältnis wie bei
   .kt-foto-leer in den Kontakten. */
.avatar-placeholder svg {
    width: 20px;
    height: 20px;
    vertical-align: unset;
}
/* Das Logo des Versicherers – steht in den Absicherungstabellen anstelle des
   ausgeschriebenen Namens (siehe versichererZeichen() in
   includes/functions/oberflaeche.php).

   Die Höhe ist die des Plättchens darunter, damit die Zeile gleich hoch
   bleibt, ob nun eine Logodatei vorliegt oder nicht. Die Breite ist frei bis
   zu einer Grenze: Wortmarken sind lang (Württembergische), Bildmarken kurz
   (R+V) – object-fit hält beide unverzerrt. */
.vers-logo {
    height: 22px;
    max-width: 104px;
    object-fit: contain;
    object-position: left center;
    display: inline-block;
    vertical-align: middle;
}

/* Das Ersatzplättchen, solange für ein Haus keine Logodatei da ist.

   Fläche und Schrift kommen als --vers-* aus PHP: die Hausfarbe aus
   gesellschaftListe(), die Schriftfarbe gerechnet. Steht das Haus nicht in
   der Liste, bleibt es bei den Vorgaben hier – demselben gedeckten Grau, das
   .avatar-placeholder trägt. Ein erfundener Hausfarbton wäre schlimmer als
   gar keiner: Farbe ist hier die Auskunft, und eine falsche Auskunft liest
   man genauso schnell wie eine richtige.

   Die Mindestbreite ist die Höhe: Bei einem Buchstaben steht dort ein Quadrat
   in der Form der Logokacheln nebenan, längere Kürzel wachsen darüber hinaus.
   So bleibt die Spalte ruhig, gleich ob in der Zeile ein Logo oder ein
   Plättchen steht. */
.vers-zeichen {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 22px;
    padding: 0 0.4rem;
    border-radius: var(--r-sm);
    background-color: var(--vers-flaeche, var(--btn-blue-bg-light));
    color: var(--vers-schrift, var(--btn-blue-dark));
    font-family: 'Plus Jakarta Sans', sans-serif;
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0.02em;
    white-space: nowrap;
    vertical-align: middle;
    cursor: default;
}
/* Je mehr Zeichen, desto kleiner – sonst sprengt „HUK" das Plättchen, das
   dem „A" seine Höhe gibt. */
.vers-zeichen-1 { font-size: var(--fs-5); }
.vers-zeichen-2 { font-size: var(--fs-3); }
.vers-zeichen-3 { font-size: var(--fs-2); }
.vers-zeichen-4 { font-size: var(--fs-1); }

.company-header-logo {
    height: 64px;
    width: 64px;
    object-fit: contain;
    border-radius: var(--r-ctl);
    border: 1px solid var(--brand-border);
    background-color: var(--brand-bg);
    flex: 0 0 auto;
}
/* Ohne Foto: die Silhouette einer Person statt der Initialen – dasselbe
   Zeichen wie auf der Kachel im Adressbuch (.kt-foto-leer). Sie kommt mit
   15px aus icon() und braucht im 64er Rahmen dasselbe Verhältnis. */
.company-header-logo-leer {
    display: flex;
    align-items: center;
    justify-content: center;
    object-fit: unset;
    background-color: var(--btn-blue-bg-light);
    color: var(--btn-blue-dark);
}
.company-header-logo-leer svg {
    width: 34px;
    height: 34px;
    vertical-align: unset;
}

/* HIER STANDEN DIE PERSONENKAESTEN DER FIRMENSEITE (.person-entry,
   .personen-raster, .person-tabelle) und die Eintragszeilen ihrer Verläufe
   (.kontakt-entry, .kontakt-kanal-icon) - am 10.08.2026 mit dem Firmenbereich
   gegangen. .kontakt-panel bleibt: den Kasten nutzt privat_detail.php. */
.kontakt-panel {
    background-color: var(--brand-bg);
    border: 1px solid var(--brand-border);
    border-radius: var(--r-ctl);
    padding: 0.8rem 0.95rem;
    margin: 0.6rem 0.9rem 0.9rem;
}

/* WhatsApp-Chat */
.wa-thread {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 340px;
    overflow-y: auto;
    padding: var(--sp-1);
}
.wa-msg {
    display: flex;
}
/* Nachrichten derselben Seite rücken zusammen; nur die erste einer Reihe
   bekommt Luft (die Klasse setzt renderWhatsappThread()). */
.wa-msg.hat-abstand {
    margin-top: 8px;
}
.wa-msg-in {
    justify-content: flex-start;
}
.wa-msg-out {
    justify-content: flex-end;
}
.wa-bubble {
    max-width: 78%;
    padding: 0.45rem 0.65rem;
    border-radius: var(--r-ctl);
    font-size: var(--fs-6);
    /* flow-root, damit die schwebende Zeitangabe die Blase mit aufspannt */
    display: flow-root;
}
.wa-msg-in .wa-bubble {
    background-color: var(--brand-surface);
    border: 1px solid var(--brand-border);
    border-top-left-radius: 4px;
}
/* Die eigene Nachricht trägt das Blaugrau, das in dieser Anwendung überall
   die eigene Seite markiert – nicht das Grün des Originals. Grün bleibt hier
   Zustandsfarbe (offenes Antwortfenster), Rot die Ausnahme (Fehlschlag). */
.wa-msg-out .wa-bubble {
    background-color: var(--btn-blue-bg-light);
    border: 1px solid var(--btn-blue-border-light);
    border-top-right-radius: 4px;
}
/* IM DUNKELN BLEIBT DIE EIGENE BLASE HELLBLAU (24.08.2026).
   -------------------------------------------------------------------------
   --btn-blue-bg-light hängt am Haus. Im Dunkeln wird das Token aus dem Grund
   und dem gedämpften Akzent gemischt – bei einem roten Haus also braun, und
   genau so stand die eigene Nachricht bei der Württembergischen da. Die
   dunkle Palette bringt für diesen einen Fall sieben eigene Werte mit
   (--wa-eigen-*, siehe farbschemaDunkelPalette()); im Hellen sind sie nicht
   gesetzt, und dann greift hinter jedem var() der Rückfall auf das Token,
   das dort schon immer galt.

   WARUM JEDE ZEILE EINZELN UND NICHT DIE TOKENS AN DER BLASE UMGESTELLT:
   Der kurze Weg wäre `--brand-quiet: var(--wa-eigen-quiet)` an der Blase –
   der Inhalt erbt die Tokens ja. Im Dunkeln geht das auch; im Hellen aber
   ist --wa-eigen-quiet nicht gesetzt, und eine Custom-Property mit
   ungültiger Substitution fällt NICHT auf den geerbten Wert zurück, sondern
   wird ungültig. Die Uhrzeit stand daraufhin im hellen Modus in der vollen
   Textfarbe statt gedämpft. Ein Rückfall im Rückfall
   (`var(--wa-eigen-quiet, var(--brand-quiet))`) wäre ein Kreis, weil er
   dasselbe Token meint, das hier gerade gesetzt wird. Also ausgeschrieben.

   :not(.ist-fehler), weil eine nicht zugestellte Nachricht rot bleibt – mit
   der roten Fläche aus 05-vertrieb.css und deren hellem Text. */
.wa-msg-out .wa-bubble:not(.ist-fehler) {
    background-color: var(--wa-eigen-bg, var(--btn-blue-bg-light));
    border-color: var(--wa-eigen-rand, var(--btn-blue-border-light));
}
.wa-msg-out .wa-bubble:not(.ist-fehler) .wa-body {
    color: var(--wa-eigen-ink, var(--brand-text));
}
/* Uhrzeit, der nachgeschlagene Wortlaut und die Größe eines Anhangs – die
   zweite Stufe. */
.wa-msg-out .wa-bubble:not(.ist-fehler) .wa-meta,
.wa-msg-out .wa-bubble:not(.ist-fehler) .wa-speichern,
.wa-msg-out .wa-bubble:not(.ist-fehler) .wa-anhang-mass,
.wa-msg-out .wa-bubble:not(.ist-fehler) .wa-body.ist-nachgeschlagen {
    color: var(--wa-eigen-quiet, var(--brand-quiet));
}
/* Zustellhaken, die Zeile „Vorlage · …" und ihr Hinweis – die dritte. */
.wa-msg-out .wa-bubble:not(.ist-fehler) .wa-haken,
.wa-msg-out .wa-bubble:not(.ist-fehler) .wa-vorlage,
.wa-msg-out .wa-bubble:not(.ist-fehler) .wa-nachgeschlagen-hinweis {
    color: var(--wa-eigen-faint, var(--brand-faint));
}
/* Der gelesene Haken ist das eine Blau in der Blase, das Farbe sein soll. */
.wa-msg-out .wa-bubble:not(.ist-fehler) .wa-haken.ist-gelesen {
    color: var(--wa-eigen-haken, var(--btn-blue));
}
/* Die Zeile eines Anhangs liegt als eigene Fläche IN der Blase – auf einer
   hellen Blase muss sie deshalb ebenfalls hell sein. */
.wa-msg-out .wa-bubble:not(.ist-fehler) .wa-anhang {
    background: var(--wa-eigen-flaeche, var(--brand-surface));
    border-color: var(--wa-eigen-rand, var(--brand-border));
    color: var(--wa-eigen-ink, var(--brand-text));
}

/* Das Bild aus dem Kopf einer Vorlage sitzt oben in der Blase und füllt sie
   in der Breite – wie in WhatsApp. Die Höhe ist gedeckelt, damit ein Aufsteller
   im Hochformat den Verlauf nicht auseinanderzieht; `contain` statt `cover`,
   weil ein beschnittener Aufsteller die Kernaussage verlieren kann. */
.wa-bild {
    display: block;
    width: 100%;
    max-height: 220px;
    margin-bottom: 0.35rem;
    border-radius: var(--r-sm);
    object-fit: contain;
    background: var(--brand-row);
}
/* Liegt die Datei bei uns, ist das Bild ein Link auf sich selbst: ein Klick,
   und das Schadenfoto steht in voller Größe im eigenen Tab. Der Zeiger sagt es
   vorher an; der Rahmen ist der des Bildes, deshalb hier nur der Block. */
.wa-bild-gross { display: block; text-decoration: none; }
.wa-bild-gross:hover .wa-bild { filter: brightness(0.94); }

/* Sprachnachricht und Video spielen in der Blase. Die Höhe des Tonspielers ist
   festgelegt, weil Chrome und Safari sonst zwei verschiedene Blasenhöhen
   ergeben; die Breite füllt, wie beim Bild. */
.wa-spieler {
    display: block;
    width: 100%;
    margin-bottom: 0.35rem;
}
audio.wa-spieler { height: 34px; }
.wa-spieler-video {
    max-height: 240px;
    border-radius: var(--r-sm);
    background: #000;
}

/* „Speichern" unter Bild und Spieler – kleiner als der Text daneben, denn es
   ist ein Handgriff, keine Aussage. Bei der Dateizeile fehlt es: Die ganze
   Zeile ist dort schon der Link. */
.wa-speichern {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    margin-bottom: 0.3rem;
    color: var(--brand-quiet);
    text-decoration: none;
    font-size: var(--fs-3);
}
.wa-speichern:hover { color: var(--brand-accent); }
.wa-speichern svg { width: 13px; height: 13px; }

/* Der Anhang, der kein Bild ist: eine Zeile zum Anklicken – Name links, Art
   und Größe rechts. Dieselbe Form wie die Anhänge im Postfach (.ml-anhaenge),
   nur in der Blase und deshalb ohne eigene Rahmenfarbe: Sie liegt schon auf
   einer getönten Fläche. */
.wa-anhang {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    margin-bottom: 0.35rem;
    padding: 0.45rem 0.55rem;
    border: 1px solid var(--brand-border);
    border-radius: var(--r-sm);
    background: var(--brand-surface);
    color: var(--brand-text);
    text-decoration: none;
    font-size: var(--fs-5);
}
.wa-anhang:hover { border-color: var(--brand-accent); color: var(--brand-text); }
.wa-anhang-name {
    flex: 1 1 auto;
    min-width: 0;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.wa-anhang-mass {
    flex: none;
    color: var(--brand-quiet);
    font-size: var(--fs-3);
    white-space: nowrap;
}

.wa-body {
    /* inline, damit die Zeitangabe daneben rutschen kann statt darunter */
    display: inline;
    color: var(--brand-text);
    word-break: break-word;
}
/* Die Zeit schwebt rechts: Ist am Ende der letzten Zeile Platz, steht sie
   dort – sonst rückt sie von selbst eine Zeile tiefer. Genau das Verhalten
   kennt man aus WhatsApp, und es spart bei kurzen Nachrichten eine Zeile. */
.wa-meta {
    float: right;
    margin: 0.3rem 0 0 0.7rem;
    font-size: var(--fs-3);
    color: var(--brand-quiet);
    white-space: nowrap;
    /* Ziffern gleicher Breite: Uhrzeiten stehen dadurch untereinander
       ruhig, statt bei jeder 1 zu zappeln. */
    font-variant-numeric: tabular-nums;
}
.wa-haken { margin-left: 3px; }
/* Zustellhaken: einer gesendet, zwei zugestellt, zwei blaue gelesen.
   Steht hier und nicht in whatsapp.css, weil Lead-Detail und Personenpanel
   denselben Verlauf rendern, diese Datei aber nicht laden. */
.wa-haken {
    color: var(--brand-faint);
    font-size: var(--fs-3);
    letter-spacing: -0.12em;
}
.wa-haken.ist-gelesen { color: var(--btn-blue); }
.wa-haken.ist-fehler { color: var(--btn-red-text); letter-spacing: 0; }

/* E-Mail-Verlauf */
.todo-row {
    padding: 0.6rem 0;
}
.todo-row + .todo-row {
    border-top: 1px solid var(--brand-border);
}
.todo-checkbox {
    appearance: none;
    -webkit-appearance: none;
    width: 18px;
    height: 18px;
    border-radius: var(--r-sm);
    border: 1.5px solid var(--brand-line-strong);
    background-color: var(--brand-surface);
    cursor: pointer;
    flex: 0 0 auto;
    position: relative;
    padding: 0;
    transition: background-color var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out);
}
.todo-checkbox:hover {
    border-color: var(--btn-leucht-dark);
}
.todo-checkbox.checked {
    background-color: var(--btn-leucht-dark);
    border-color: var(--btn-leucht-dark);
}
.todo-checkbox.checked::after {
    content: '';
    position: absolute;
    left: 5px;
    top: 1px;
    width: 5px;
    height: 9px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

/* ==========================================================================
   Die Hover-Sprache der Anwendung – drei Antworten, mehr nicht
   --------------------------------------------------------------------------
   Vorher antwortete jede Fläche anders: die eine wurde grau, die nächste
   blau, die dritte hob sich, die vierte tat nichts. Nebeneinander liest sich
   das nicht als Gestaltung, sondern als Zufall. Es gibt jetzt genau drei:

     ZEILE (Tabellenzeile, Listenzeile, Adressbuchzeile)
        Fläche wird --brand-row. Sonst nichts. Eine Zeile ist ein Ausschnitt
        einer Liste, sie soll sich nicht aus ihr herauslösen.

     KACHEL, DIE EIN LINK IST (Kontaktkachel, Aufgabenkarte)
        Rand nimmt Farbe an und die Erhebung geht von --sh-1 auf --sh-2.
        Sie hebt sich einen Hauch – das ist das Versprechen, dass ein Klick
        woanders hinführt.

     BEDIENELEMENT (Knopf, Segment, Zeichenknopf)
        Nur Farbe, keine Bewegung, keine Erhebung. Ein Knopf steht schon da,
        wo er hingehört; er soll nicht ausweichen, wenn man auf ihn zielt.

   Alles unter --t-fast und hinter (hover: hover), damit die Zustände auf dem
   Touchgerät nicht kleben bleiben.
   ========================================================================== */
/* HIER STAND DIE FIRMENKACHEL (.company-card*) des Bestands - am 10.08.2026
   mit dem Firmenbereich gegangen. Die Hover-Sprache oben gilt unverändert;
   .kt-card im Adressbuch und .bd-card im Board sprechen sie weiter. */
.min-w-0 {
    min-width: 0;
}
/* Die Kachelwahl aus den Formularen (Kundenart in privat_form.php; bis zum
   10.08.2026 auch der Bezug in insurance_form.php). Sie trägt zwei Bauweisen: als <label> mit verstecktem
   Radio im Formular, und als <a class="is-aktiv"> dort, wo die Wahl in der
   Adresse steht statt im Formular – so im Versandkasten der Formulare
   (formulare.php, „1. Welches Formular?"). Beide sehen gleich aus; nur der
   ausgewählte Zustand kommt einmal von :checked und einmal von der Klasse. */
.bezug-selector {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-4);
}
.bezug-option {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex: 1 1 200px;
    padding: 0.65rem 0.8rem;
    border: 1px solid var(--brand-line-strong);
    border-radius: var(--r-ctl);
    background-color: var(--brand-surface);
    cursor: pointer;
    text-decoration: none;
    transition: border-color var(--t-fast) var(--ease-out), background-color var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out);
}
.bezug-option:hover {
    border-color: var(--btn-blue-border-light);
    background-color: var(--btn-blue-bg-light);
}
.bezug-option input[type="radio"] {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}
.bezug-option-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 30px;
    height: 30px;
    border-radius: var(--r-sm);
    background-color: var(--brand-bg);
    color: var(--brand-faint);
    transition: background-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.bezug-option-label {
    font-weight: 600;
    font-size: var(--fs-7);
    color: var(--brand-text);
}
.bezug-option:has(input:checked),
.bezug-option.is-aktiv {
    border-color: var(--blau-rand);
    background-color: var(--blau-hell);
    box-shadow: inset 0 0 0 1px var(--blau-rand);
}
.bezug-option:has(input:checked) .bezug-option-icon,
.bezug-option.is-aktiv .bezug-option-icon {
    background-color: var(--btn-leucht-dark);
    color: #fff;
}

/* --- Ortsvorschläge im Terminformular ------------------------------------
   Aufbau wie beim Zeitwähler oben: eine Liste, die unter dem Feld aufgeht.
   Sie liegt absolut, damit sie das Formular nicht auseinanderschiebt. */
.ort-feld { position: relative; }
.ort-liste {
    position: absolute;
    z-index: 1050;
    left: calc(var(--bs-gutter-x, 1.5rem) * 0.5);
    right: calc(var(--bs-gutter-x, 1.5rem) * 0.5);
    margin: 0.15rem 0 0;
    padding: 0.3rem;
    list-style: none;
    max-height: 244px;
    overflow-y: auto;
    overscroll-behavior: contain;
    background-color: var(--brand-surface);
    border: 1px solid var(--brand-border);
    border-radius: var(--r-card);
    box-shadow: var(--shadow-pop);
}
.ort-liste li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.6rem;
    padding: 0.35rem 0.55rem;
    border-radius: var(--r-sm);
    font-size: var(--fs-6);
    cursor: pointer;
}
.ort-liste li:hover,
.ort-liste li.ist-markiert { background-color: var(--blau-hell); }
.ort-text { color: var(--brand-text); }
/* Woher der Vorschlag stammt – leise, aber lesbar: „aus dem Bestand" heißt,
   dass die Straße stimmt, „PLZ-Liste" heißt, dass nur der Ort bekannt ist. */
.ort-herkunft {
    flex: none;
    font-size: var(--fs-3);
    color: var(--brand-quiet);
}
