/*
 * Designsystem von commectONE - siehe DESIGN.md, dort maßgeblich.
 * Farb- und Maßänderungen passieren ausschließlich hier im :root-Block,
 * nie verstreut in Templates, und werden in DESIGN.md nachgezogen.
 */

:root {
  /* Flächen */
  --bg: #ffffff;
  --surface: #ffffff;
  --menu: #f6f7f8;

  /* Linien */
  --border: #ebedf0;
  --border-strong: #dcdfe3;

  /* Text */
  --text: #16191d;
  --text-2: #5c6570;
  /* #8b939c hatte nur 3,11:1 Kontrast auf Weiss und 2,90:1 auf dem
     Menuegrau. Fuer normalen Text verlangt WCAG 4,5:1 - das war also
     nicht Geschmack, sondern zu wenig. Michael hat es zweimal gemeldet
     ("etwas zu schwach dargestellt"), bei den Feldbeschriftungen und im
     Hauptmenue. Jetzt 5,02:1 auf Weiss und 4,68:1 auf dem Menuegrau.
     Der Farbton bleibt, nur die Helligkeit sinkt - wie schon beim Blau. */
  --text-3: #67707b;
  /* Eine Stufe WENIGER Schwarz als --text, fuer Ueberschriften, die
     kraeftig sein sollen, ohne hart zu wirken (Michael, 16.09.2026:
     "die Ueberschriften einen Schwarzton weniger"). 10,9:1 auf Weiss -
     Kraft kommt hier vom Gewicht, nicht von der Tiefe. */
  --text-1: #333b44;

  /* Markenfarben - die Werte stehen so in app/static/logo.svg. Zuvor
     standen hier aus einem Bildschirmfoto abgelesene Werte (#3a92fa /
     #5cd6a1); die waren um ein paar Grad verschoben, weil ein Foto vom
     Bildschirm durch das Farbprofil geht. Die Datei ist die Quelle,
     nicht das Foto. */
  --marke-blau: #0099ff;
  --marke-gruen: #2bd89e;
  --marke-verlauf: linear-gradient(90deg, var(--marke-blau), var(--marke-gruen));

  /* Akzent: dasselbe Blau (204°), nur dunkler. #0099ff traegt weisse
     Schrift mit 3,0:1 und ist damit fuer Text zu hell - noetig sind
     4,5:1. Der Farbton bleibt, die Helligkeit sinkt.

     NACHGEMESSEN am 16.09.2026, weil Michael sagte "lass uns mal unser
     Blau pruefen". Er hatte recht, und es war knapper als gedacht:
     #007acc kam auf Weiss auf genau 4,51:1 - bestanden mit einem
     Hundertstel. Und weil dieselbe Farbe nicht nur auf Weiss steht,
     fiel sie an zwei Stellen durch:

       auf dem Menuegrau  #f6f7f8   4,21:1   (aktiver Eintrag, Verweise)
       auf dem blassen Blau #e9f6fe 4,10:1   (Aufgabenzahl, Filterpille,
                                              Hinweisfeld am Zeiger)

     Eine Farbe, die an ihrer eigenen Grenze steht, ist keine
     Entscheidung, sondern ein Zufall. Eine Stufe tiefer - gleicher
     Farbton, 205 statt 204 Grad - und es traegt ueberall:

       auf Weiss 5,78:1 | Menuegrau 5,39:1 | blasses Blau 5,25:1
       weisse Schrift darauf 5,78:1 (Knoepfe, Plaketten, "heute")

     Das LOGO-Blau (--marke-blau) bleibt unangetastet: es traegt keine
     Schrift, es ist die Marke. */
  --primary: #0068b3;
  --primary-hover: #005694;
  --primary-soft: #e9f6fe;
  --primary-rand: #a8dcfd;  /* Rahmen in Markenblau, ohne zu schreien */

  /* Status: Gruen wie im Logo (160°), fuer Schrift abgedunkelt -
     #2bd89e kaeme auf 1,8:1 und waere auf Weiss kaum zu lesen. */
  --ok-bg: #ecfbf6;
  --ok-text: #188560;
  --ok-dot: var(--marke-gruen);
  --warn-bg: #fdf3e3;
  --warn-text: #8a5a10;
  --danger: #a8453c;
  --danger-bg: #faeeec;
  /* Die drei Raender fehlten, obwohl vier Regeln sie benutzten
     (.lg-freigegeben, .entscheiden.ja/.nein, .engstelle). Eine
     undefinierte Variable macht die ganze Erklaerung ungueltig - der
     Rahmen wurde dann in der Textfarbe gezeichnet. */
  --ok-rand: #9bd9bd;
  --warn-rand: #e8cea0;
  --danger-rand: #e0b3ad;

  /* ---- Die Ampel ----------------------------------------------------
     Michael, 16.09.2026: "Die Einteilung Farbe an der Zeitleiste auf der
     Quote sollte ebenfalls nicht blau sein. Hier wuerden sich die
     Ampelfarben anbieten."

     Die Ampel BEWERTET (wie voll ist es), die Artfarbe BENENNT (was ist
     es). Deshalb gehoeren Gruen, Gelb und Rot ab jetzt allein der
     Bewertung - keine Abwesenheitsart darf sie tragen. Und weil die
     Ampel ein SIGNAL ist, ist sie gesaettigter als jede Artfarbe, die
     nur eine getoente Flaeche ist. Gleicher Farbkreis, andere Lautstaerke
     - so verwechselt man die beiden Aufgaben nicht. */
  --ampel-gruen-bg: #d9f0e3;
  --ampel-gruen-text: #0f6b45;
  --ampel-gelb-bg: #ffeaa8;
  --ampel-gelb-text: #6f4a08;
  --ampel-rot-bg: #f9d2cb;
  --ampel-rot-text: #8d2f24;

  /* Breiten. Eine Maske ist ueberall gleich breit, und die Kopfzeile
     einer Detailseite ist genauso breit wie der Inhalt darunter -
     sonst haengen die Knoepfe rechts frei im Raum. */
  --maske: 780px;
  --inhalt: calc(280px + 24px + var(--maske));  /* linke Spalte + Abstand + Maske */
}

/* ---------------------------------------------------------------------
   Die Schrift - selbst ausgeliefert, nicht von Google geladen.

   Begruendung steht in app/templates/grundgeruest.html. Kurz: bei
   dynamischer Einbindung geht die IP jedes Benutzers an Google (LG
   Muenchen I, 20.01.2022, 3 O 17493/20), und ein internes Werkzeug soll
   ohnehin ohne Internet lesbar sein.

   `font-display: swap` sorgt dafuer, dass die Seite sofort mit der
   Systemschrift lesbar ist und die richtige Schrift nachruecken darf -
   und dass die Suite auch dann benutzbar bleibt, wenn die Dateien
   fehlen.
   --------------------------------------------------------------------- */
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/ibm-plex-sans-400.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/static/fonts/ibm-plex-sans-500.woff2") format("woff2");
}

* { box-sizing: border-box; }

html { font-size: 13px; }  /* 17.09.2026: von 12px angehoben, Verhaeltnisse unveraendert - alle Groessen haengen in rem daran */

body {
  margin: 0;
  font-family: "IBM Plex Sans", system-ui, -apple-system, sans-serif;
  font-weight: 400;
  line-height: 1.5;
  background: var(--menu);
  color: var(--text);
}

a { color: var(--primary); }

img { max-width: 100%; }

/* ---------------------------------------------------------------------
   Seitenaufbau: Seitenmenü links (236px) + Kopfzeile (52px) + Inhalt
   ------------------------------------------------------------------- */

/* Die Seite selbst rollt NICHT. Sie ist genau so hoch wie das Fenster,
   und gerollt wird nur im Inhaltsbereich - dadurch bleiben Seitenmenue
   und Kopfzeile stehen.

   100dvh nach 100vh: auf dem Handy rechnet 100vh die Adressleiste mit,
   dadurch waere der untere Rand abgeschnitten. Browser, die dvh nicht
   kennen, nehmen die Zeile davor. */
.shell {
  display: flex;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

/* 192px. Nachgemessen mit IBM Plex Sans bei 12px, der Groesse der
   Menueeintraege:

     Benutzerverwaltung       98px
     Personalentwicklung     101px
     Arbeitsmittelverwaltung 118px

   Deutsche Komposita sind schmaler als sie aussehen - fast nur
   Kleinbuchstaben. Nach Abzug der Polsterungen (2x10 aussen, 2x8 am
   Eintrag) bleiben 156px fuer den Text, also rund 35px Luft selbst beim
   laengsten realistischen Modulnamen. Ein Name, der doch nicht passt,
   bricht auf zwei Zeilen um - lesbar bleibt besser als abgeschnitten. */
.sidebar {
  width: 192px;
  flex-shrink: 0;
  background: var(--menu);
  display: flex;
  flex-direction: column;
  padding: 14px 10px;
  /* Eigener Rollbalken, damit eine lange Modulliste nicht unten
     abgeschnitten wird. */
  overflow-y: auto;
}

.sidebar .brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 1rem;
  font-weight: 500;
  color: var(--text);
  text-decoration: none;
  padding: 0 8px;
  margin-bottom: 18px;
}

/* Die Marke am Fuss der Leiste. margin-top:auto schiebt sie nach unten,
   egal wie viele Menuepunkte darueber stehen. 120px sind bewusst
   zurueckhaltend - sie schliesst die Leiste ab und konkurriert nicht mit
   der Navigation. Der Zusatz "vernetzen.einrichten.entstoeren." ist in
   dieser Fassung nicht enthalten; er waere hier sechs Pixel hoch. */
.sidebar-fuss {
  margin-top: auto;
  padding: 18px 8px 4px;
  line-height: 0;  /* kein Nachraum unter dem Bild */
}

.sidebar-fuss img { width: 104px; height: auto; display: block; }

/* Das Zeichen neben "commectONE" oben in der Leiste: der Verlauf des
   Logos, blau nach gruen. Es doppelt die Marke unten nicht, weil es
   etwas anderes sagt - oben steht der Name der Anwendung, unten die
   Firma dahinter. */
.brand-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 6px;
  background: var(--marke-verlauf);
  color: #fff;
  font-weight: 500;
  flex-shrink: 0;
}


/* Anmeldeseite: eine Karte auf leerer Flaeche, ohne Seitenmenue und
   Kopfzeile. Vor der Anmeldung gibt es nichts zu bedienen. */
/* Oben statt mittig. Senkrecht zentriert wandert die Karte, sobald eine
   Wartungsmeldung darueber erscheint - und ein Anmeldefeld, das seinen
   Platz wechselt, sucht man. */
.anmeldeseite {
  min-height: 100vh;
  padding: 64px 20px 32px;
  background: var(--menu);
}

.anmelde-marke {
  width: 100%;
  max-width: 380px;
  margin: 0 auto 24px;
  padding-bottom: 20px;
  border-bottom: 2px solid;
  border-image: var(--marke-verlauf) 1;
}

.anmelde-marke img { width: 175px; height: auto; display: block; }

.anmeldeseite .card { width: 100%; max-width: 380px; margin: 0 auto; }
.anmeldeseite .meldung { width: 100%; max-width: 380px; margin: 0 auto 12px; }

.nav { flex: 1; overflow-y: auto; }

.nav-group { margin-bottom: 16px; }

/* ---- Die Ebene traegt das SYMBOL, nicht die Schriftart -------------
   Michael, 16.09.2026: "Die unterschiedlichen Schriftarten sind nicht
   mehr Kriterium genug fuer eine Unterscheidung, so dass man Obermenue
   und Untermenue erkennen kann. Vielleicht kann man es dadurch loesen,
   dass man die Schriftart und Schreibweise vereinheitlicht und nur vor
   die Menuepunkte ein kleines Symbol setzt."

   Gemessen war der Befund eindeutig: Rubrik 11px/500/GROSSSCHRIFT,
   Punkt 12px/400 - und BEIDE in derselben Farbe (--text-2), beide am
   selben linken Rand. Ein Pixel Groesse und die Schreibweise mussten
   die ganze Rangfolge tragen.

   Jetzt tragen sie drei Dinge gemeinsam:
     1. Symbol   - ein Punkt hat eines, eine Rubrik nicht.
     2. Einrueckung - die durch das Symbol von selbst entsteht.
     3. Farbe    - die Rubrik in --text, der Punkt in --text-2.
   Schriftgroesse und Schreibweise sind VEREINHEITLICHT: beide 12px,
   beide normal geschrieben. */
.nav-label {
  font-size: 1rem;
  letter-spacing: 0;
  text-transform: none;
  font-weight: 600;
  color: var(--text-1);
  padding: 0 8px;
  margin-bottom: 6px;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 8px;
  border-radius: 5px;
  font-size: 1rem;
  color: var(--text-2);
  text-decoration: none;
  margin-bottom: 2px;
}
/* Das Symbol ist eine Spalte und darf nicht schrumpfen - sonst rutschen
   die Woerter je nach Laenge unterschiedlich weit ein. */
.nav-item > svg { flex: none; opacity: .75; }
.nav-item.active > svg { opacity: 1; }
.nav-item > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Der Start-Eintrag traegt nur ein Symbol. Gleiche Zeilenhoehe wie die
   beschrifteten Eintraege, Symbol dort, wo sonst das Wort beginnt - sonst
   steht es einsam in der Mitte und wirkt wie ein Fehler. */
.nav-item-symbol { display: flex; align-items: center; min-height: 20px; }

.nav-item:hover { background: #ebedf0; }

.nav-item.active { background: #ffffff; color: var(--primary); }

/* Wer ist angemeldet - steht oben rechts, nicht unten in der Seitenleiste:
   dort sucht man es, und es fuehrt direkt in "Mein Bereich". */
.topbar-user {
  font-size: 1rem;
  color: var(--text-2);
  text-decoration: none;
  padding: 5px 8px;
  border-radius: 5px;
  white-space: nowrap;
}

.topbar-user:hover { background: var(--bg); color: var(--text); }

/* min-height: 0 ist hier tragend: ohne das weigert sich ein Flex-Kind,
   kleiner zu werden als sein Inhalt - der Rollbereich darin bekaeme nie
   eine begrenzte Hoehe und wuerde nie rollen. */
.main-col { flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; background: var(--bg); }

.inhalt-roller { flex: 1; min-height: 0; overflow-y: auto; }

.topbar {
  height: 52px;
  flex-shrink: 0;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 24px;
}

.topbar-title { font-size: 1.25rem; font-weight: 500; color: var(--text); }

/* min-width: 0 und das Rollen sind hier tragend: die Reiterreihe darf
   schmaler werden als ihre Reiter breit sind. Ohne das schiebt sie die
   Schaltflaechen rechts aus der Kopfzeile - bei 13px Wurzel und voller
   Reiterreihe waren es 3px zu viel (gemessen am 17.09.2026 auf der
   Gebietsseite bei 900px Breite). Die Reiter rollen dann waagerecht, wie
   das Zeitband und die Tabellen; die Schaltflaechen bleiben stehen, und
   die Kopfzeile behaelt ihre eine Zeile. Der Messlauf zeigt: damit
   verschwinden auch zwei Ueberlaeufe, die es schon bei 12px gab. */
.topbar-tabs { display: flex; gap: 16px; flex: 1; min-width: 0; overflow-x: auto;
  scrollbar-width: none; }
.topbar-tabs::-webkit-scrollbar { display: none; }
.topbar-tabs a { flex: 0 0 auto; }
.topbar-tabs a {
  font-size: 1rem;
  color: var(--text-2);
  text-decoration: none;
  padding: 4px 0;
  border-bottom: 2px solid transparent;
}
.topbar-tabs a.active { color: var(--primary); border-bottom-color: var(--primary); }

.topbar-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; }

.menu-btn {
  display: none;
  font-size: 1.3333rem;
  cursor: pointer;
  color: var(--text-2);
}

/* EINE Inhaltsbreite fuer die ganze Suite. Vorher legte jede Seite sie
   fuer sich fest: Detailseiten waren begrenzt, Meldungen und Listen
   liefen bis zum Fensterrand - auf einem breiten Bildschirm standen
   deshalb Kanten versetzt, die zusammengehoeren. Wer eine Breite
   braucht, nimmt sie ab jetzt von hier und nicht aus einem style-Attribut
   in einer Vorlage. */
.content {
  padding: 24px 32px;
  max-width: calc(var(--inhalt) + 64px);  /* Inhalt + linke/rechte Polsterung */
  width: 100%;
}

/* DIE AUSNAHME (16.09.2026, von Michael entschieden). Eine Zeitleiste ist
   der eine Inhalt, dessen Nutzen an seiner LAENGE haengt: bei 1148px waren
   im Tagesraster 30 von 38 Spalten zu sehen, auch auf einem
   2560px-Monitor. Ausdruecklich als Zusatzklasse und nicht als Aufweichen
   der Regel - so ist die Ausnahme sichtbar und zaehlbar, statt dass wieder
   jede Seite ihre Breite selbst festlegt.
   Fliesstext darf NICHT mitwachsen: eine Zeile ueber 2000px liest kein
   Mensch. Deshalb behalten Absaetze in einer weiten Seite ihre Grenze. */
.content.weit { max-width: none; }
.content.weit .card > p,
.content.weit .card > .field-help,
.content.weit .sicht-tabelle,
.content.weit table.befund { max-width: 100ch; }

@media (max-width: 860px) {
  .sidebar {
    position: fixed;
    top: 0; bottom: 0; left: 0;
    z-index: 30;
    transform: translateX(-100%);
    transition: transform .18s ease;
  }
  .nav-toggle:checked ~ .shell .sidebar {
    transform: translateX(0);
    box-shadow: 0 0 24px rgba(0, 0, 0, .18);
  }
  .menu-btn { display: inline-flex; }
  .content { padding: 16px; }
  .topbar { padding: 0 16px; }
  body { font-size: 1.0833rem; }
}

/* ---------------------------------------------------------------------
   Karten, Tabellen, Formulare
   ------------------------------------------------------------------- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 16px;
  margin-bottom: 16px;
}

.card h2 { font-size: 1rem; font-weight: 500; margin: 0 0 12px; }
.card h3 { font-size: 1rem; font-weight: 500; margin: 16px 0 8px; }

.table-scroll { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }

table { width: 100%; border-collapse: collapse; }

/* Der Tabellenkopf traegt haeufig Inhalt und nicht nur eine Beschriftung
   (Rollennamen in der Rechte-Matrix). Er sieht deshalb aus wie die Zellen
   darunter - gleiche Groesse, keine Versalien, gleiche Textfarbe. Abgesetzt
   wird er ueber Flaeche, Linie und den 500er Schnitt, nicht ueber Daempfung. */
thead th {
  font-size: 1rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text);
  background: #fbfcfc;
  border-bottom: 1px solid var(--border-strong);
  text-align: left;
  padding: 8px 14px;
  font-weight: 500;
}

tbody td {
  padding: 8px 14px;
  border-bottom: 1px solid #f3f5f6;
  font-size: 1rem;
  vertical-align: middle;
}

tbody tr:hover { background: #fafbfc; }
tbody tr:last-child td { border-bottom: none; }

tr.row-link { cursor: pointer; }
tr.row-link a { color: inherit; text-decoration: none; }
tr.row-link a:hover { text-decoration: underline; }

.chevron { color: #c4c9cf; text-align: right; }

.group-row td {
  background: #fbfcfc;
  font-size: 0.875rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-3);
  font-weight: 400;
}

.inline-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; }

form.stack { display: flex; flex-direction: column; gap: 12px; max-width: 380px; }
/* Ein Formular, das ausdruecklich Maskenbreite haben soll, schlaegt die
   380px von form.stack - sonst waere die Klasse wirkungslos. */
form.stack.maske { max-width: var(--maske); }
/* Ein Knopf ist so breit wie seine Beschriftung, nicht so breit wie das
   Formular - sonst wird aus "Speichern" ein Balken ueber die halbe Seite. */
form.stack > button, form.stack > .btn { align-self: flex-start; }
/* :not(.field-row) ist hier kein Beiwerk. Diese Regel ist
   spezifischer als .field-row und hat ihr deshalb das
   flex-direction: row weggenommen - eine Feldzeile wurde damit zur
   Spalte, die Felder standen untereinander statt nebeneinander. Neue
   Regeln dieser Art immer mit demselben Ausschluss. */
form.stack > div:not(.field-row) { display: flex; flex-direction: column; }

label { display: block; font-size: 0.9167rem; color: var(--text-2); margin-bottom: 3px; font-weight: 400; }

.field-help { font-size: 0.875rem; color: var(--text-3); margin: 3px 0 0; }

.field-row { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-start; }

/* Standard: waechst und schrumpft. Eine Zeile ohne Breitenangaben sieht
   aus wie vorher. */
.field-row > div { flex: 1 1 170px; min-width: 140px; }

/* Breite nach Inhalt, nicht nach Gleichmacherei: eine Postleitzahl
   braucht keine 170px, und wenn sie welche bekommt, wird die Maske
   unnoetig hoch. Die kleinen Klassen wachsen bewusst NICHT mit - sonst
   waeren wir wieder bei gleich breiten Feldern. */
.field-row > .f-xs { flex: 0 1 92px;  min-width: 80px; }   /* PLZ, Tage */
.field-row > .f-s  { flex: 0 1 150px; min-width: 120px; }  /* Land, Typ, Kürzel */
.field-row > .f-m  { flex: 1 1 190px; min-width: 150px; }  /* Telefon, Ort */
.field-row > .f-l  { flex: 2 1 260px; min-width: 180px; }  /* Name, E-Mail, IBAN */

/* Ueber die Ausschlussliste und NICHT ueber input[type="text"]: ein
   <input> ohne type-Attribut ist zwar ein Textfeld, wird von
   input[type="text"] aber nicht getroffen. Genau daran lagen die
   schmalen, ungestylten Felder - die meisten Masken schreiben kein
   type. Hier stehen die Ausnahmen, alles andere ist ein Textfeld. */
input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="file"]):not([type="hidden"]),
select,
textarea {
  padding: 0 10px;
  border: 1px solid var(--border-strong);
  border-radius: 5px;
  background: #fff;
  font-size: 1rem;
  font-family: inherit;
  color: var(--text);
  width: 100%;
}

input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="file"]):not([type="hidden"]),
select {
  height: 30px;
}

textarea { padding: 8px 10px; line-height: 1.5; resize: vertical; }

@media (max-width: 860px) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="file"]):not([type="hidden"]),
  select {
    min-height: 44px;
  }
}

input:focus, select:focus { outline: 2px solid var(--primary-soft); border-color: var(--primary); }

.field-error input, .field-error select { border-color: var(--danger); }

/* ---------------------------------------------------------------------
   Schaltflächen - höchstens eine gefüllte pro Ansicht
   ------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 30px;
  padding: 0 14px;
  border-radius: 5px;
  font-size: 1rem;
  font-family: inherit;
  font-weight: 400;
  text-decoration: none;
  cursor: pointer;
  /* Eine Beschriftung bricht nicht um. "Wieder zeigen" auf zwei Zeilen in
     einem 26px hohen Knopf sieht nach Fehler aus - und ist einer.
     Gefunden am 15.09.2026 in einem Fixture-Test bei 840px Fensterbreite. */
  white-space: nowrap;
  /* Fallback, falls .btn ohne Variante (-primary/-secondary/-quiet/-delete)
     verwendet wird: sieht aus wie Sekundär statt unsichtbar. */
  border: 1px solid var(--border-strong);
  background: #fff;
  color: var(--text);
}

.btn.compact { height: 26px; padding: 0 10px; }

/* Mindesthoehe fuer Fingerkuppen - aber erst dort, wo die Suite
   wirklich auf Fingerbedienung umstellt (700px, siehe .mobile-list).
   Vorher stand hier 860px: zwischen 701 und 860px blieb die Tabelle
   stehen, und ein 26px-Knopf in einer Tabellenzeile wurde auf 44px
   gestreckt - die Zeile verrutschte und die Beschriftung brach um.
   Gefunden am 15.09.2026. */
@media (max-width: 700px) {
  .btn { min-height: 44px; }
  /* Ein kompakter Knopf in einer Zeile bleibt kompakt - 36px ist noch
     gut zu treffen und sprengt die Zeile nicht. */
  .btn.compact { min-height: 36px; }
}

/* Grundstil für <button>-Elemente ohne eigene .btn-*-Klasse -
   Sekundär-Optik, damit nichts unstyled bleibt. */
button {
  font-family: inherit;
  height: 30px;
  padding: 0 14px;
  border-radius: 5px;
  font-size: 1rem;
  border: 1px solid var(--border-strong);
  background: #fff;
  color: var(--text);
  cursor: pointer;
}

.btn-primary, button.btn-primary { background: var(--primary); border-color: var(--primary); color: #fff; }
.btn-primary:hover, button.btn-primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); }

.btn-secondary, button.btn-secondary { background: #fff; border: 1px solid var(--border-strong); color: var(--text); }

.btn-quiet, button.btn-quiet { background: transparent; border-color: transparent; color: var(--text-2); }
.btn-quiet:hover, button.btn-quiet:hover { background: #f0f2f4; }
/* Verweis aus einem Block heraus ("In Personal öffnen"): leise, klein,
   aber ein Bedienelement - ein Textlink mitten in einer Karte sieht aus
   wie Fließtext und wird überlesen. Der Akzent bleibt dem Ziel
   vorbehalten, nicht dem Weg. */
.btn-quiet.compact { font-size: 0.9583rem; padding: 0 8px; margin-left: -8px; }
.btn-quiet.compact:hover { color: var(--text); }

.btn-delete, button.btn-delete {
  background: #fff;
  border: 1px solid var(--border-strong);
  color: var(--danger);
}
.btn-delete:hover, button.btn-delete:hover { background: var(--danger-bg); border-color: var(--danger); }

.error {
  color: var(--danger);
  background: var(--danger-bg);
  border: 1px solid var(--danger);
  border-radius: 8px;
  padding: 10px 14px;
  margin: 0 0 12px;
  font-size: 1rem;
}
.muted { color: var(--text-2); font-size: 0.9167rem; }

/* ---------------------------------------------------------------------
   Plaketten (Badges)
   ------------------------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  /* Klein und eng am Text: in einer Zeile koennen mehrere Abzeichen
     nebeneinander stehen (Zugangsart, Zustand, Passwort veraltet, ohne
     Person). Je grosszuegiger jedes einzelne, desto voller die Zeile. */
  height: 17px;
  padding: 0 6px;
  border-radius: 999px;
  font-size: 0.8333rem;
  border: 1px solid transparent;
  white-space: nowrap;
}

.badge-neutral { background: #f0f2f4; color: var(--text-2); }
.badge-outline { background: #fff; border-color: var(--border-strong); color: var(--text-2); }
.badge-ok { background: var(--ok-bg); color: var(--ok-text); }
.badge-warn { background: var(--warn-bg); color: var(--warn-text); }

.badge-dot { width: 6px; height: 6px; border-radius: 999px; background: var(--ok-dot); display: inline-block; }

/* Rollen-Plaketten in Listen */
.pill-role {
  display: inline-flex;
  height: 22px;
  align-items: center;
  padding: 0 8px;
  border-radius: 4px;
  background: var(--primary-soft);
  color: var(--primary);
  font-size: 0.875rem;
  margin: 2px 4px 2px 0;
}

/* Rechtestufen: immer weiße Fläche, Stufe nur über Rahmen + Schrift */
.perm {
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 10px;
  border-radius: 5px;
  background: #fff;
  font-size: 1rem;
  border: 1px solid #eff1f3;
  color: var(--text-3);
}
.perm-read { border-color: var(--border-strong); color: var(--text-2); }
/* Ein Farbwert war hier festgeschrieben: #bcd4e2, eine Toenung des
   alten Petrolblaus. Mit dem Markenblau passte er nicht mehr - deshalb
   jetzt aus der Variablen, wie alles andere auch. */
.perm-write { border-color: var(--primary-rand); color: var(--primary); }
.perm-admin { border-color: var(--primary); color: var(--primary); }

/* ---------------------------------------------------------------------
   Listen: Werkzeugleiste (Suche + Filter), Fußzeile
   ------------------------------------------------------------------- */

.list-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}

.list-search { max-width: 280px; flex: 1; min-width: 180px; }
.list-search input { width: 100%; }

.filter-row { display: flex; flex-wrap: wrap; gap: 6px; }

.filter-pill {
  display: inline-flex;
  align-items: center;
  /* Eng am Text. Die Filterzeile ist mit der Zeit gewachsen (acht
     Eintraege in der Benutzerliste); jedes Pixel Polsterung je Pille
     macht die Zeile ein Stueck laenger und drueckt die eigentliche
     Liste nach unten. */
  height: 24px;
  padding: 0 9px;
  /* Gleicher Radius wie die Schaltflaechen (5px). Vollrund sah aus wie
     eine Plakette und nicht wie etwas zum Anklicken - Plaketten sind die
     .badge-Elemente, und die sollen sich unterscheiden. */
  border-radius: 5px;
  border: 1px solid var(--border-strong);
  background: #fff;
  color: var(--text-2);
  font-size: 0.9167rem;
  text-decoration: none;
  white-space: nowrap;
}

.filter-pill.active { background: var(--primary-soft); border-color: var(--primary-soft); color: var(--primary); }

/* Rechteliste einer Rolle: waechst nur nach unten. Die Stufenspalte
   bleibt schmal, damit kein waagerechter Balken entsteht. */
.rechte td:last-child, .rechte th:last-child { width: 150px; }
.rechte select { width: 100%; }

.list-footer { color: var(--text-2); font-size: 0.9167rem; padding: 10px 4px 0; }

/* Leerer Zustand einer Liste. Eine leere Liste ist kein Fehler, aber sie
   muss sagen, warum sie leer ist und wohin man geht - siehe DESIGN.md,
   "Leere Listen". */
.leer { padding: 24px 16px; text-align: left; }
.leer p { margin: 0; }
.leer .leer-satz { color: var(--text); }
.leer .leer-grund { color: var(--text-2); font-size: 0.9167rem; margin-top: 3px; }
.leer .btn { margin-top: 12px; }

/* ---------------------------------------------------------------------
   Detailseiten: Kopf mit Rücksprung/Name/Plaketten/Handlungen,
   zweispaltiger Aufbau darunter
   ------------------------------------------------------------------- */

.detail-back { display: inline-block; margin-bottom: 8px; font-size: 0.9167rem; color: var(--text-2); text-decoration: none; }
.detail-back:hover { text-decoration: underline; }

.detail-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-bottom: 20px;
}

.detail-header h1 { font-size: 1.25rem; font-weight: 500; margin: 0; }

.detail-actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }

/* Tätigkeitsliste mit der Haupt-Auswahl rechts. Zwei getrennte Labels je
   Zeile - lag die Haupt-Auswahl im Label des Kästchens, schaltete ein
   Klick auf ihr Wort die Tätigkeit um. Die Spalte ist weg, solange es
   nichts zu entscheiden gibt (Klasse .aus, gesetzt von seite.js). */
.taetigkeit-zeile { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
.taetigkeit-name { display: flex; align-items: center; gap: 6px; font-weight: 400; margin: 0; }
.haupt-wahl {
  margin: 0 0 0 auto; display: flex; align-items: center; gap: 4px;
  font-size: 1rem; font-weight: 400;
}
.haupt-wahl.aus { display: none; }

/* "Nicht gespeichert" neben dem Speichern-Knopf. Bernstein, weil es
   auffallen soll, ohne ein Fehler zu sein (DESIGN.md, Farben). Das
   Element erzeugt seite.js, es steht in keiner Vorlage. */
/* Rueckfrage bei ungespeicherten Eingaben.

   Die Suite bestaetigt sonst auf einer eigenen Seite (Loeschen, Sperren),
   nicht in einem Fenster. Hier geht das nicht: die Rueckfrage darf die
   Seite gerade NICHT verlassen, sonst ist das Eingetippte weg - genau
   das, was sie verhindern soll. Deshalb die einzige Ausnahme. */
.rueckfrage::backdrop { background: rgba(22, 25, 29, .35); }
.rueckfrage {
  border: 1px solid var(--border-strong); border-radius: 10px;
  padding: 20px 22px; max-width: 420px; background: var(--surface);
  color: var(--text); font: inherit; box-shadow: 0 8px 28px rgba(22, 25, 29, .13);
}
.rueckfrage h2 { margin: 0 0 8px; font-size: 1.25rem; font-weight: 500; }
.rueckfrage p { margin: 0 0 14px; font-size: 1.0417rem; color: var(--text-2); }
.rueckfrage .knoepfe { display: flex; gap: 8px; flex-wrap: wrap; }

/* Eine Aufgabenzeile auf der Startseite: Titel links, Frist rechts. */
/* Rubrikzeile auf der Startseite: Wort links, feine Linie bis zum Rand.
   Eine Überschrift wäre zu laut für eine Gliederung, eine Linie allein
   sagt nicht, was folgt. */
.rubrik { display: flex; align-items: center; gap: 10px; margin: 22px 0 10px; }
.rubrik:first-of-type { margin-top: 4px; }
.rubrik span {
  font-size: 0.875rem; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-3); white-space: nowrap;
}
.rubrik i { flex: 1; height: 1px; background: var(--border); }

.nicht-gespeichert {
  align-self: center; font-size: 0.9167rem; color: var(--warn-text);
  background: var(--warn-bg); border-radius: 99px; padding: 2px 9px;
  white-space: nowrap;
}

.detail-grid { display: flex; gap: 24px; align-items: flex-start; flex-wrap: wrap; }

.detail-side { width: 280px; flex-shrink: 0; }
.detail-main { flex: 1; min-width: 280px; }

.feldliste dt { font-size: 0.875rem; letter-spacing: .04em; text-transform: uppercase; color: var(--text-3); margin-top: 12px; }
.feldliste dt:first-child { margin-top: 0; }
.feldliste dd { margin: 2px 0 0; font-size: 1rem; color: var(--text); }

@media (max-width: 700px) {
  .detail-side { width: 100%; }
}

/* ---------------------------------------------------------------------
   Hinweisboxen
   ------------------------------------------------------------------- */

.hint {
  margin: 0 0 12px;
  padding: 8px 12px;
  border: 1px solid transparent;
  border-radius: 8px;
  font-size: 0.9167rem;
}

.hint-warn { background: var(--warn-bg); color: var(--warn-text); border-color: var(--warn-text); }
.hint-warn a { color: var(--warn-text); }

.hint-ok { background: var(--ok-bg); color: var(--ok-text); }

/* ---------------------------------------------------------------------
   Dashboard
   ------------------------------------------------------------------- */

.module-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 16px;
}

.module-card { display: block; text-decoration: none; color: var(--text); }
.module-card .icon { color: var(--text-2); line-height: 0; }
.module-card:hover .icon { color: var(--primary); }
.module-card h3 { margin: 8px 0 3px; font-size: 1rem; font-weight: 500; color: var(--text); }
.module-card p { margin: 0; color: var(--text-2); font-size: 0.9167rem; }

/* ---------------------------------------------------------------------
   Handy: aus der Tabelle wird eine gestapelte Liste
   ------------------------------------------------------------------- */

.avatar-circle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 999px;
  background: var(--primary-soft);
  color: var(--primary);
  font-size: 0.9167rem;
  flex-shrink: 0;
}

/* Auf dem Telefon wird aus einer Tabelle eine Liste aus Karten - ABER
   nur, wo es diese Karten auch gibt. Die Regel hiess vorher
   ".table-scroll table" und galt damit fuer jede Tabelle: zwoelf
   Tabellen ohne Kartenliste waren auf schmalen Fenstern SPURLOS
   verschwunden, unter anderem Meldungen, Protokoll, Aufgaben und die
   Benachrichtigungen. Gefunden am 15.09.2026.
   Jetzt muss eine Vorlage es ausdruecklich sagen: `table-scroll
   mobil-karten`. Wer eine neue Tabelle baut und daran nicht denkt,
   bekommt eine seitlich rollbare Tabelle - unschoen, aber lesbar. Das
   ist die richtige Richtung fuer einen Fehler. */
@media (max-width: 700px) {
  .table-scroll.mobil-karten table,
  .table-scroll.mobil-karten thead { display: none; }
  .mobile-list { display: flex; flex-direction: column; }
  .mobile-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 4px;
    border-bottom: 1px solid var(--border);
    text-decoration: none;
    color: var(--text);
    min-height: 44px;
  }
  .mobile-row .info { flex: 1; min-width: 0; }
  .mobile-row .name { font-size: 1rem; }
  .mobile-row .email { font-size: 0.9167rem; color: var(--text-2); }
  .mobile-row .badges { margin-top: 4px; display: flex; flex-wrap: wrap; gap: 4px; }
}

@media (min-width: 701px) {
  .mobile-list { display: none; }
}

/* Erstpasswort: wird einmal angezeigt und meist abgetippt oder vorgelesen -
   deshalb Festbreitenschrift und grosszuegiger Zeichenabstand. */
.erstpasswort {
  margin: 0;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 1.3333rem;
  letter-spacing: .06em;
  color: var(--text);
  user-select: all;
  /* Passt auch in die schmale linke Spalte der Detailseiten. */
  overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------------
   Bloecke: aufklappbare Abschnitte innerhalb EINES Formulars.
   Siehe DESIGN.md, "Blöcke statt langer Formulare". Zugeklappte Bloecke
   werden mitgespeichert - <details> versteckt nur, es entfernt nichts.
   ------------------------------------------------------------------- */
/* Senkrechte Feldfolge innerhalb einer Karte - was form.stack fuer ein
   Formular tut, nur eine Ebene tiefer. */
.stapel { display: flex; flex-direction: column; gap: 12px; }
.stapel > div:not(.field-row) { display: flex; flex-direction: column; }

/* Eine Maske ist ueberall gleich breit. Die feste Grunddatenkarte und
   die Bloecke darunter gehoeren optisch zusammen; steht die Karte
   breiter, sieht die Seite aus, als waere etwas verrutscht. Beide
   nehmen dieselbe Breite aus einer Stelle. */
.maske { max-width: var(--maske); }

.bloecke { display: flex; flex-direction: column; gap: 8px; max-width: var(--maske); }

.block {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.block > summary {
  list-style: none;
  cursor: pointer;
  padding: 11px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 1rem;
  font-weight: 500;
}

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

.block > summary::before {
  content: "›";
  display: inline-block;
  color: var(--text-3);
  font-size: 1.1667rem;
  line-height: 1;
  transition: transform .15s ease;
}

.block[open] > summary::before { transform: rotate(90deg); }

.block > summary:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

/* Was drinsteht, ohne aufzuklappen - man klappt nicht ins Blaue. */
.block .block-info {
  margin-left: auto;
  font-weight: 400;
  color: var(--text-3);
  font-size: 0.9167rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.block .block-inhalt {
  padding: 0 14px 14px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.block .block-inhalt > div:not(.field-row) { display: flex; flex-direction: column; }

@media (prefers-reduced-motion: reduce) {
  .block > summary::before { transition: none; }
}

/* ---------------------------------------------------------------------
   Meldungen auf der Startseite. Drei Stufen, mehr nicht: mehr Farben
   heissen nicht mehr Aufmerksamkeit, sondern weniger.
   ------------------------------------------------------------------- */
/* Die Farbe traegt der Rahmen, nicht die Flaeche. Eine farbig gefuellte
   Flaeche ganz oben auf der Startseite zieht staerker als alles andere
   auf der Seite - bei einer Wartungsankuendigung ist das zu viel. Der
   Rahmen sagt dasselbe leiser. */
.meldung {
  border: 1px solid var(--text-3);
  border-radius: 8px;
  background: var(--surface);
  padding: 12px 16px;
  margin-bottom: 12px;
}

.meldung-kopf { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }

.meldung-art {
  font-size: 0.875rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-3);
}

.meldung-kopf strong { font-size: 1.0833rem; font-weight: 500; }
.meldung-text { margin: 6px 0 0; font-size: 1rem; color: var(--text-2); white-space: pre-wrap; }
.meldung-fuss { margin: 8px 0 0; font-size: 0.9167rem; color: var(--text-3); }

/* Farbe nach Art: Information gruen, Hinweis blau, Stoerung rot. Gruen
   und Blau kommen aus dem Designsystem oben, Rot ist die vorhandene
   Danger-Farbe. */
.meldung-info { border-color: var(--ok-text); }
.meldung-info .meldung-art { color: var(--ok-text); }

.meldung-warnung { border-color: var(--primary); }
.meldung-warnung .meldung-art { color: var(--primary); }

.meldung-stoerung { border-color: var(--danger); }
.meldung-stoerung .meldung-art { color: var(--danger); }

/* Kopieren in die Zwischenablage - fuer Werte, die man woanders
   eintippen muesste (IBAN, Erstpasswort). */
.kopierzeile { display: flex; gap: 8px; align-items: flex-end; }
.kopierzeile > :first-child { flex: 1; min-width: 0; }

/* Nur das Symbol, kein Wort: der Knopf steht neben einem Feld und soll
   ihm keine Breite wegnehmen. Was er tut, sagt das title-Attribut und
   die Rueckmeldung nach dem Klick. */
.btn-kopieren {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border-strong);
  border-radius: 5px;
  background: #fff;
  color: var(--text-2);
  cursor: pointer;
}

.btn-kopieren svg { width: 15px; height: 15px; display: block; }
.btn-kopieren:hover { background: var(--bg); color: var(--text); }
.btn-kopieren:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }

/* Nach dem Klick kurz gruen - eine Textmeldung wuerde den Knopf wieder
   breit machen. */
.btn-kopieren[data-erfolg] { color: var(--ok-text); border-color: var(--ok-text); }

/* Datumsfeld: eigenes Textfeld statt <input type="date">. Der Kalender
   des Browsers ist bei Geburtsdaten unhandlich, und Safari springt in
   seinem Datumsfeld nicht von Tag zu Monat weiter. Ziffern liegen
   untereinander gleich breit, damit TT.MM.JJJJ nicht wandert. */
.feld-datum,
.feld-zeitpunkt {
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
}

/* Die Leiste "du arbeitest an einer Aufgabe" (app/aufgabe_fuehrung.py).
   Schmal, oben, in Markenblau - sie sagt, warum man hier ist, und aendert
   nichts an der Seite darunter. */
.fuehrung {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  background: var(--primary-soft);
  border: 1px solid var(--primary-rand);
  border-radius: 8px;
  padding: 0.6rem 0.9rem;
  margin: 0 0 1rem;
  font-size: 0.86rem;
}
.fuehrung strong { font-weight: 500; }

/* Die Zahl offener Aufgaben am Menueeintrag "Mein Bereich". Klein und
   ruhig: sie soll auffallen, wenn man hinsieht, und nicht rufen. */
.nav-zahl {
  display: inline-block;
  min-width: 1.15rem;
  padding: 0 0.3rem;
  /* Rechts ausgerichtet, seit der Eintrag ein flex-Kasten ist: sonst
     klebt die Zahl am Wort und wandert mit dessen Laenge. */
  margin-left: auto;
  border-radius: 999px;
  background: var(--primary-soft);
  border: 1px solid var(--primary-rand);
  color: var(--primary);
  font-size: 0.72rem;
  line-height: 1.35;
  text-align: center;
}
.nav-item.active .nav-zahl { background: #fff; }

/* Der Hinweis auf einer Geruestseite (CLAUDE.md, "erst die Struktur
   zeigen"). Deutlich, aber nicht alarmierend: es ist kein Fehler, dass
   die Seite nichts kann - es ist ihr Zweck. */
.geruest {
  border: 1px dashed var(--border-strong);
  background: var(--menu);
  border-radius: 9px;
  padding: 0.7rem 1rem;
  margin: 0 0 1rem;
  font-size: 0.82rem;
  color: var(--text-2);
  max-width: 74ch;
}
.geruest strong { color: var(--text); font-weight: 500; }

/* Kennzeichen am Menueeintrag einer Geruestseite - klein und ruhig, aber
   da: wer den Reiter sieht, soll wissen, dass dahinter noch nichts
   gespeichert wird. */
.tab-geruest {
  /* 0.62rem waren 7,4px - zu klein, auch fuer ein Kennzeichen. Die
     Wurzel der Suite ist 12px, nicht 16 (siehe die Warnung weiter unten
     am Zeitband). */
  font-size: 0.74rem; letter-spacing: .04em; text-transform: uppercase;
  border: 1px dashed var(--border-strong); border-radius: 999px;
  padding: 0 0.35rem; margin-left: 0.3rem; color: var(--text-3);
  vertical-align: 1px;
}

/* ---------------------------------------------------------------------
   Zeitband (Geruest Abwesenheit, 16.09.2026)

   Die alte Belegungsleiste je Woche ist ERSETZT, nicht ergaenzt: sie
   konnte nur fuenf Wochen und keine uebergehenden Zeitraeume.

   ZWEI FLAECHEN, nicht eine: links die Namen (steht), rechts das Band
   (scrollt waagerecht). Der erste Versuch war EIN Gitter mit
   position:sticky auf der Namenszelle. Das kann nicht funktionieren: der
   umschliessende Block eines Gitterfeldes IST das Gitterfeld, und sticky
   darf seinen umschliessenden Block nicht verlassen - also hat es keinen
   Platz zum Stehenbleiben und wandert mit. Der Nachweis hat die Zelle
   dabei erwischt, wie sie 243px mitwanderte.

   Damit die Zeilen beider Flaechen auf einer Linie bleiben, gibt die
   KLASSE die Hoehe vor - dieselbe Klasse links wie rechts. Keine Zeile
   darf ihre Hoehe aus ihrem Inhalt nehmen, sonst laeuft das Band gegen
   die Namen aus dem Takt.
   --------------------------------------------------------------------- */
.band-huelle { display: flex; align-items: flex-start; }
.band-namen {
  flex: 0 0 190px; width: 190px;
  border-right: 1px solid var(--border-strong);
  background: var(--surface);
}
.band-scroll { flex: 1 1 auto; min-width: 0; overflow-x: auto; padding-bottom: 4px; }

/* Die Spalten WACHSEN MIT (Michael, 16.09.2026).
   Vorher waren sie starr `var(--b)` breit. Dadurch endeten die Tagesspalten
   mitten in der Karte, waehrend die Zeilen mit Hintergrund - Gruppenkopf und
   die Spur der Einplanung - bis zum Rand liefen: dieselbe Zeile, zwei
   verschiedene rechte Kanten. Genau das ist ihm aufgefallen.

   Jetzt ist `--b` nur noch die MINDESTbreite. Ist Platz da, verteilen die
   1fr-Anteile ihn auf alle Spalten; ist keiner da, stehen die Spalten auf
   ihrem Mindestmass und das Band scrollt wie vorher.

   Die zwei Zeilen an .band gehoeren zusammen und sind der ganze Trick:
   das Band ist so breit wie der Platz (width:100%), aber nie schmaler als
   die Summe der Mindestbreiten (min-width). Dadurch haben Gitterzeilen und
   Hintergrundzeilen IMMER dieselbe Breite - in beiden Faellen. */
.band {
  width: 100%;
  min-width: calc(var(--n) * var(--b, 58px));
}
.band-reihe {
  display: grid;
  /* --b kommt aus der Vorlage: Tage 28px, Wochen 58, Monate 76. Im CSS
     waere sie eine dritte Wahrheit. */
  grid-template-columns: repeat(var(--n), minmax(var(--b, 58px), 1fr));
  align-items: center;
}

/* Die Hoehen. Links und rechts dieselben Klassen - das ist die ganze
   Ausrichtung. */
.bz {
  height: 32px; box-sizing: border-box;
  border-bottom: 1px solid var(--border);
  /* 0.92rem = 11px bei 12px Wurzel - eine Stufe unter der Tabelle (12px),
     nicht drei. Siehe die Warnung ueber die Wurzel oben. */
  font-size: 0.92rem; line-height: 1.2;
  /* Die Namen standen in --text und lasen sich fast so kraeftig wie die
     Ueberschriften (Michael, 16.09.2026). Jetzt --text-2: gut lesbar
     (5,91:1), aber eine Stufe leiser als die Gruppenzeile, die --text und
     500 behaelt. So entsteht die Rangfolge, die vorher fehlte. */
  color: var(--text-2); font-weight: 400;
  padding: 0 8px 0 2px;
  display: flex; align-items: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* `overflow: visible` gegen das Erbe von `.bz`: dort schneidet
   `overflow: hidden` lange NAMEN ab (mit Auslassungspunkten) - in einer
   BANDZEILE hat es nichts zu suchen und hat das Hinweisfeld am Zeiger
   vollstaendig weggeschnitten, bis auf einen Streifen Schatten. Gemessen
   an der Ahnenkette, nicht geraten. */
.band-reihe.bz { display: grid; padding: 0; overflow: visible; }
/* Die Kopfzeile ist hoeher als die uebrigen: sie tragt bis zu drei
   Zeilen (Monat und Jahr, Tageszahl, Wochentag). Mit 38px presste der
   Text nach unten - von Michael gesehen, 16.09.2026. */
/* Wieder 38px: die Spalte traegt nur noch Zahl und Wochentag. Monat und
   Jahr stehen in der Zeile DARUEBER (.bz-band) - Michaels Loesung, und
   damit ist das "presst nach unten" an der Wurzel weg statt durch mehr
   Hoehe zugedeckt. */
.bz-kopf { height: 38px; font-weight: 500; border-bottom: 1px solid var(--border-strong); }

/* Die obere Achsenzeile: Monat und Jahr ueber der ganzen Leiste. Eine
   Zeitachse hat zwei Ebenen - oben der Zeitraum, unten der Tag -, und
   jede gehoert in ihre eigene Zeile. */
.bz-band { height: 22px; background: var(--surface); border-bottom: none; }
.band-abschnitt {
  height: 100%; display: flex; align-items: center;
  border-left: 1px solid var(--border-strong);
  /* Nicht blau: eine Achsenbeschriftung ist nichts zum Anklicken, und
     Blau gehoert der Bedienung. Derselbe Ton wie das Jahr links davor -
     es sind zwei Stufen EINER Achse und nicht zwei verschiedene Dinge. */
  font-size: 0.86rem; font-weight: 600; color: var(--text-2);
  padding-left: 7px; overflow: hidden; white-space: nowrap;
}
.band-abschnitt:first-child { border-left: none; }
.band-namen .bz-band { border-right: 1px solid var(--border-strong); }
.bz-bereich { height: 26px; background: var(--menu); font-weight: 500;
  font-size: 0.86rem; color: var(--text); }
.bz-leer { height: 30px; background: repeating-linear-gradient(135deg, #fbfcfd 0 6px, #f6f7f8 6px 12px); font-size: 0.86rem; color: var(--text-3); }
.bz-bel { height: 26px; font-size: 0.86rem; font-weight: 500;
  /* Die Zeile ist die SUMME ihrer Gruppe, kein weiterer Mensch. Ohne
     Kennzeichnung sass sie zwischen den Namen und las sich wie eine
     weitere Person - Michael, 17.09.2026: "verschoben zu den anderen
     Linien/Bereichen". Gemessen war die Zeile richtig ausgerichtet
     (links und rechts auf derselben Hoehe, geprueft mit dem Messlauf);
     falsch war ihr RANG. Jetzt beginnt und endet eine Gruppe mit einem
     getoenten Band, die Namen dazwischen stehen eingerueckt auf weiss. */
  background: var(--menu); border-top: 1px solid var(--border-strong); }
/* Die Namen stehen EINGERUECKT: sie gehoeren in die Gruppe. Gruppenzeile
   und Summenzeile bleiben am linken Rand - dieselbe Sprache wie die
   Einrueckung im Gebietsbaum. */
.bz-name { padding-left: 14px; }
.band-namen .bz:last-child { border-bottom: none; }
.band .bz:last-child { border-bottom: none; }
.dez-klein { color: var(--text-3); font-size: 0.78rem; margin-left: 0.3rem; font-weight: 400; }

.band-sp {
  text-align: center; padding: 4px 2px 3px;
  border-left: 1px solid var(--border);
  font-size: 0.86rem; line-height: 1.2;
  /* Die drei Zeilen stehen unten ausgerichtet: dann sitzt die Tageszahl
     auf einer Linie, egal ob ueber ihr ein Monat steht oder nicht. */
  display: flex; flex-direction: column; justify-content: flex-end;
}
.band-sp b { display: block; font-weight: 500; color: var(--text-2);
  font-size: 1.05rem; line-height: 1.25; }
.band-sp i { display: block; font-style: normal; color: var(--text-3);
  font-size: 0.8rem; line-height: 1.1; }
/* Der Jahreswechsel bekommt eine Kante - sonst merkt man beim Scrollen
   nicht, dass man in einem anderen Jahr ist. */
/* Die Kante am Jahreswechsel ist eine Marke und kein Schalter - also
   nicht blau. Der Abschnitt darueber nennt das neue Jahr ohnehin. */
.band-sp.jahr { border-left: 2px solid var(--text-3); }
.band-sp.jahr b { color: var(--text); font-weight: 600; }

.band-weit {
  grid-column: 1 / -1; padding: 0 10px;
  font-size: 0.86rem; color: var(--text-3); white-space: nowrap;
}
/* Der Text bleibt beim Scrollen am linken Rand stehen (Michael,
   16.09.2026). Das geht hier - anders als bei der Namenszelle im ersten
   Versuch -, weil der umschliessende Block die GANZE Zeile ist und
   sticky darin Platz zum Stehenbleiben hat. */
.band-weit .haftend { position: sticky; left: 10px; display: inline-block; }

/* Die Spur: die leere Zeile mit den Spaltenlinien. Sie liegt unter den
   Balken, damit ein Balken keine Linien zeichnen muss. */
.band-spur {
  grid-column: 1 / -1; height: 100%;
  /* Die Linien lagen als repeating-gradient in PIXELN und passten nicht
     mehr, sobald die Spalten mitwachsen. Jetzt ist eine Kachel genau eine
     Spalte breit - in Prozent, also unabhaengig von der Breite. */
  background-image: linear-gradient(to right, var(--border) 0 1px, transparent 1px);
  background-size: calc(100% / var(--n)) 100%;
  background-repeat: repeat-x;
}
.balken {
  height: 22px; margin: 0 1px; border-radius: 5px;
  display: flex; align-items: center; justify-content: center; gap: 2px;
  background: #eef0f2; border: 1px solid var(--border-strong);
  color: var(--text-2); font-size: 0.82rem; text-decoration: none;
  white-space: nowrap; padding: 0 4px;
  /* KEIN overflow:hidden mehr am Balken: das schnitt das Hinweisfeld ab.
     Abgeschnitten wird der TEXT (siehe .balken-text) - das ist die
     Stelle, an der es hingehoert. */
  overflow: visible;
}
.balken { position: relative; }
.balken:hover { border-color: var(--primary); color: var(--primary); }
/* `min-width: 0` ist noetig, damit dieses flex-Kind unter seine
   Textbreite schrumpfen DARF - sonst greift `text-overflow` nie. */
.balken-text { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* Ein Balken, der fuer seinen Text zu schmal ist, tragt ihn DANEBEN:
   rechts in der freien Flaeche, in der Farbe seiner Art. Ein leerer
   Kasten ist ein Raetsel - genau das hat Michael gesehen. Und ein
   Kuerzel im Kasten waere nur ein kleineres Raetsel.
   `overflow: visible` am Balken ist dafuer noetig - das gilt jetzt
   ohnehin fuer alle Balken (siehe oben), die Sonderregel entfaellt. */
/* Steht die Beschriftung NEBEN dem Balken, muss sie sichtbar zu ihm
   gehoeren - sonst liest man sie als Beschriftung der naechsten Spalte.
   Genau das ist passiert: Michael las den Balken vom 15. als den vom 16.,
   weil das Wort ueber dem 16. stand. Eine kurze Fuehrungslinie bindet es
   an den Balken; dieselbe Loesung wie in einem Diagramm mit
   Aussenbeschriftung. */
.balken-text.daneben {
  position: absolute; left: 100%; top: 50%; transform: translateY(-50%);
  margin-left: 7px; overflow: visible; pointer-events: none;
  white-space: nowrap; color: inherit;
}
.balken-text.daneben::before {
  content: ""; position: absolute; left: -6px; top: 50%;
  width: 5px; height: 1px; background: currentColor; opacity: .55;
}
/* Angeschnitten, nicht abgeschnitten: die Ecke bleibt eckig, der Rand
   wird gestrichelt und ein Pfeil sagt, dass es weitergeht. */
.balken.an-links { border-top-left-radius: 0; border-bottom-left-radius: 0; border-left-style: dashed; margin-left: 0; }
.balken.an-rechts { border-top-right-radius: 0; border-bottom-right-radius: 0; border-right-style: dashed; margin-right: 0; }
.an-zeichen { color: var(--text-3); font-size: 0.72rem; flex: none; }

/* ---- OHNE das Recht auf die Art: genau zwei Erscheinungsformen -----
   "weg" ist gefuellt, "offen" ist leer - beide mit DURCHGEZOGENEM Rand.
   Vorher trug der Balken hier zusaetzlich `vorlaeufig` (gestrichelt)
   nach dem Verfahrensstand, und damit war die Art ableitbar: "weg +
   gestrichelt" gibt es nur bei Krankheit (sie wirkt ab der Meldung,
   der Nachweis fehlt noch), "offen + gestrichelt" nur beim Urlaub (er
   wirkt erst ab der Genehmigung). Von Michael gesehen, 16.09.2026.

   Zwei Formen sind erlaubt und noetig, denn beide sagen etwas ueber die
   PLANUNG und nichts ueber den Grund: "weg" heisst, der Mensch steht
   nicht zur Verfuegung; "offen" heisst, es ist noch nichts entschieden. */
/* PETROL, nicht grau (Michael, 16.09.2026: "sollten wir doch nicht
   lieber grau nehmen - welche Farbe, die wir noch nicht benutzen, passt
   gut in dieses Konzept?"). Petrol ist der einzige unbesetzte Platz:
   Blau ist die Bedienung, Gruen/Gelb/Rot die Ampel, Violett und
   Terrakotta die Familien, Sand die Fortbildung, Grau der
   Freizeitausgleich. Und es passt zur Sache: eine Farbe, die etwas
   BENENNT, ohne etwas zu verraten - genau das ist diese Ansicht.

   Der Rand ist der MITTLERE Ton derselben Familie, nicht --border-strong.
   Das war ein Fehler und Michael hat ihn gesehen: #dcdfe3 auf einer
   Fuellung von #e7eaed ist 1,08:1 - der Rand war rechnerisch da und
   unsichtbar. Ein Rand muss sich von SEINER EIGENEN Fuellung abheben. */
.balken.ist-weg { background: #e3eeef; border-color: #8ab4b7; color: #1c5f63; }
.balken.ist-offen { background: #fff; border-color: #8ab4b7; color: #1c5f63; }
.lg-weg { background: #e3eeef; border: 1px solid #8ab4b7; }
.lg-offen2 { background: #fff; border: 1px solid #8ab4b7; }

/* Farbe traegt die Art - und die gibt es nur fuer befaehigte Personen.
   Ohne das Recht sind alle Balken gleich grau; das ist keine Anzeige, die
   man ausgraut, sondern eine, die es nicht gibt.

   BLAU KOMMT HIER NICHT VOR (Michael, 16.09.2026): "der Status Urlaub
   sollte nicht blau sein, blau ist im System vorbehalten". Er hat recht,
   und der Grund ist handfest: Blau ist in dieser Suite die Farbe der
   BEDIENUNG - aktiver Schalter, heute, Verweis, Auslastungssaeule. Waere
   Urlaub auch blau, sahen ein ausgewaehlter Filter und ein Urlaubsbalken
   gleich aus, und man koennte nicht mehr unterscheiden, was der Rechner
   sagt und was die Sache ist.

   Die Zuordnung nach seiner Ansage: Urlaub gruen, Krankheit deutlicher
   rot, Fortbildung lila. Dazu passend: Kind krank bleibt in der
   Rotfamilie (auch ein Gesundheitsdatum, aber unterscheidbar),
   Sonderurlaub ocker, Freizeitausgleich grau.

   Jede Schrift ist auf ihrer Fuellung nachgerechnet - der Balkentext ist
   9,8px und braucht 4,5:1. Gemessen: 5,88 bis 8,66:1. */
/* ---- Die Artfarben ---------------------------------------------------
   Vier Farben fuer sechs Arten, und das mit Absicht. Seit jeder Balken
   BESCHRIFTET ist, muss die Farbe die Art nicht mehr allein
   auseinanderhalten - der Text sagt sie. Damit wird die Farbe frei fuer
   etwas Besseres: die FAMILIE. Wer aufs Band schaut, sieht schon vor dem
   Lesen, ob dort geplante oder eingetretene Abwesenheit steht.

     Violett   geplant, im Voraus entschieden   Urlaub, Sonderurlaub
     Terrakotta eingetreten, nicht planbar      Krankheit, Kind krank
     Sand      arbeitet, nur nicht im Einsatz   Fortbildung
     Grau      Zeit, die dem Menschen gehoert   Freizeitausgleich

   Innerhalb einer Familie unterscheidet die STAERKE - Michaels eigener
   Vorschlag vom 16.09.2026: "jeweils in der gleichen Farbe, vielleicht
   nur unterschiedlich stark".

   Kein Blau (das ist die Bedienung), kein Gruen, Gelb oder Rot (das ist
   die Ampel). Michael, 16.09.2026: "Ein Gruen innerhalb der Zeitleiste
   ist meiner Meinung nach jetzt doch auch nicht mehr sinnvoll, weil Gruen
   fuer genehmigt, fuer gut, okay steht - und Urlaub ist eher ein
   Zustand." Genau: Gruen heisst in diesem Bild "hier ist noch Platz".
   Urlaub ist keine Bewertung, also darf er nicht gruen sein. */
.balken.art-urlaub { background: #f0ebfa; border-color: #b7a4df; color: #4a2f8f; }
.balken.art-sonderurlaub { background: #f8f5fd; border-color: #d7cbf0; color: #6a52a8; }
.balken.art-krank { background: #fbeae6; border-color: #e6b0a3; color: #8f3a25; }
.balken.art-kind_krank { background: #fdf4f1; border-color: #f0cfc4; color: #8a4f3c; }
.balken.art-fortbildung { background: #f5f0e6; border-color: #d5c09c; color: #6b4f22; }
.balken.art-freizeitausgleich { background: #eef1f3; border-color: #c9d0d7; color: #44505c; }

.band-zahl {
  text-align: center; font-size: 0.86rem; color: var(--text-3);
  border-left: 1px solid var(--border); height: 100%;
  display: flex; align-items: center; justify-content: center;
}
/* Drei Bedeutungen, drei Farben - vorher war "ueber der Quote" blau und
   las sich wie "in Ordnung":
   gleich      genau auf der Quote - kein Problem, aber nichts mehr frei
   ueber       darueber, offene Antraege mitgezaehlt - VOR der Genehmigung
   schon-ueber darueber allein mit den entschiedenen - hier hilft kein
               Ablehnen mehr, hier muss jemand zurueckziehen */
/* VIER Lagen, vier Anzeigen (entschieden 16.09.2026). Die Quote ist ein
   Richtwert: ueberschritten werden darf sie, nachdem geprueft oder
   freigegeben wurde. Eine freigegebene Hauptferienwoche als Alarm zu
   zeigen, macht die Warnung wertlos.
     gleich       genau auf der Quote
     ueber        wuerde darueber liegen, wenn die offenen Antraege durchgehen
     freigegeben  darueber, aber bewusst - dokumentierte Ausnahme, ruhig
     schon-ueber  darueber OHNE Entscheidung - der einzige echte Befund */
/* Fuenf Zustaende auf drei Ampelfarben. "Unter der Quote" traegt gar
   keine Farbe - da ist nichts zu melden, und eine Farbe fuer den
   Normalfall stumpft die anderen ab.

   Die FREIGABE ist kein eigener Farbton, sondern eine gruene Kante unter
   dem gelben Grund: es liegt ueber der Quote (gelb), aber es ist
   entschieden (gruener Boden). Eine dokumentierte Ausnahme ist keine
   Warnung - aber auch nicht der Normalfall. */
.band-zahl.gleich { background: var(--ampel-gruen-bg); color: var(--ampel-gruen-text); font-weight: 500; }
.band-zahl.ueber { background: var(--ampel-gelb-bg); color: var(--ampel-gelb-text); font-weight: 600; }
/* Die Freigabe war eine 3px starke gruene Kante UNTEN in der Zelle. Auf
   dem Papier sitzt sie innen; im Bild sah sie aus wie ein Brett, das
   unter zwei Zellen hervorsteht - und damit sahen genau diese zwei
   Zellen VERSCHOBEN aus (Michael, 16.09.2026). Die Zellen selbst standen
   dabei auf den Pixel richtig: alle bei 1087px, alle 25px hoch.

   Jetzt ein RING in der Zelle. Er umschliesst die Zahl, statt unter ihr
   zu liegen, und nichts steht mehr hervor: "ueber der Quote (gelb), aber
   entschieden (gruen umrandet)". */
.band-zahl.freigegeben {
  background: var(--ampel-gelb-bg); color: var(--ampel-gelb-text); font-weight: 600;
  box-shadow: inset 0 0 0 2px #2f8f66;
}
.band-zahl.schon-ueber { background: var(--ampel-rot-bg); color: var(--ampel-rot-text); font-weight: 700; }
/* Der Antragsanteil steht klein hinter der Tatsache: "2+1" heisst zwei
   sind weg, einer hat beantragt. Zwei Zahlen, weil es zwei Zustaende
   sind - eine Summe waere die Luege, die Michael benannt hat. */
.zahl-offen { font-size: 0.74rem; color: var(--text-3); margin-left: 1px; font-weight: 400; }

.plak-extern {
  display: inline-block; font-size: 0.7rem; color: var(--text-3);
  border: 1px dashed var(--border-strong); border-radius: 999px;
  padding: 0 0.35rem; margin-left: 0.25rem;
}
/* Eine Beschriftung sagt, was der Schalter daneben tut - sie ist keine
   Randnotiz. --text-2 statt --text-3 und eine Spur groesser. */
.field-label { font-size: 0.84rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-2); font-weight: 500; }

/* Umschalter aus Verweisen (Raster, Zeitraum). Keine Knoepfe, weil es
   Adressen sind - dann ist eine Ansicht verlinkbar. */
.segment { display: inline-flex; border: 1px solid var(--border-strong); border-radius: 8px; overflow: hidden; }
.segment a {
  font-size: 0.92rem; padding: 5px 12px; text-decoration: none;
  color: var(--text-2); background: var(--surface);
  border-right: 1px solid var(--border-strong);
}
.segment a:last-child { border-right: none; }
.segment a:hover { background: var(--menu); }
.segment a.an { background: var(--primary); color: #fff; border-color: var(--primary); }

/* Umbrechende Auswahl: EINZELNE Plaketten statt eines Kastens mit
   Rahmen. Michael hat es an der Zeile "Art" gefunden - ein `segment` mit
   sechs Eintraegen bricht um, und dann zerreisst der gemeinsame Rahmen
   mitsamt den runden Ecken. Ein Kasten mit Rahmen darf nicht umbrechen;
   was umbrechen muss, braucht eigene Rahmen. */
.chips { display: flex; flex-wrap: wrap; gap: 4px; }
.chips a {
  font-size: 0.92rem; padding: 4px 11px; text-decoration: none;
  color: var(--text-2); background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: 7px;
  white-space: nowrap;
}
.chips a:hover { background: var(--menu); }
.chips a.an { background: var(--primary); color: #fff; border-color: var(--primary); }
/* KEIN Wachsen (Michael, 16.09.2026): mit `flex: 1 1 340px` zog der
   Gruppenblock den ganzen freien Platz an sich und schob "Firma" weit
   nach rechts. Die Blöcke stehen jetzt nebeneinander, und nur das
   Hinweiszeichen sitzt am rechten Rand. */
.leiste-breit { flex: 0 1 auto; max-width: 420px; }

/* Massenverarbeitung in einer Liste (Antraege). Die Auswahlspalte steht
   VOR dem Namen - dort sucht die Hand sie. */
.spalte-wahl { width: 34px; text-align: center; padding-right: 0 !important; }
.massen-leiste {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 9px 14px; border-bottom: 1px solid var(--border);
  background: var(--primary-soft); font-size: 0.92rem; color: #0a4a6e;
}

.th-dez { display: block; font-size: 0.72rem; font-weight: 400; color: var(--text-3);
  text-transform: none; letter-spacing: 0; }

/* Tabelle "was sichtbar ist und was nicht" - zwei Spalten, kein Kopf. */
.sicht-tabelle { width: 100%; border-collapse: collapse; }
.sicht-tabelle td { padding: 9px 10px 9px 0; border-bottom: 1px solid var(--border); vertical-align: top; font-size: 0.95rem; color: var(--text-2); }
.sicht-tabelle tr:last-child td { border-bottom: none; }
.sicht-tabelle td:first-child { width: 180px; color: var(--text); }

/* Statistik je Mensch und Art. */
table.stat th, table.stat td { text-align: left; }
table.stat .stat-zelle { white-space: nowrap; font-size: 0.95rem; }
table.stat .stat-gesund { background: #fffdf8; }
.stat-art9 { font-size: 0.74rem; color: var(--warn-text); letter-spacing: .04em; }

/* Zwei Reste aus dem ersten, verworfenen Versuch mit position:sticky
   standen hier noch: eine Regel auf `.band-zeile` (die Klasse gibt es
   nicht mehr) und ein Ueberschreiben der Spur mit einem Gradienten in
   PIXELN - das haette die neuen prozentualen Linien auf schmalen
   Fenstern wieder kaputt gemacht. Beides entfernt; ein totes CSS ist
   nicht harmlos, es wartet nur. */
@media (max-width: 700px) {
  .band-namen { flex-basis: 120px; width: 120px; }
  .sicht-tabelle td:first-child { width: 120px; }
}

/* ACHTUNG BEI rem IN DIESER DATEI: die Wurzel der Suite ist 12px
   (html { font-size: 1rem } ganz oben), nicht die ueblichen 16px. 0.72rem
   sind hier also 8,6px und nicht 11,5. Genau daran bin ich am 16.09.2026
   gescheitert: das ganze Zeitband war eine Stufe zu klein - Wochentag
   7,7px, Balkentext 8,2px, Name 9,8px - waehrend eine Tabellenzelle in
   der Suite 12px hat. Michael hat gefragt, ob die Bilder die echte
   Groesse zeigen; sie taten es, und das war der Befund.
   Faustregel: eine normale Zeile 0.92-1rem, ein Nebenlabel nicht unter
   0.74rem (8,9px). Wer kleiner will, braucht einen Grund. */

/* ---------------------------------------------------------------------
   Zeitband: Tagesraster, Wochenende, heute, Saeulen (16.09.2026)

   Nachtrag zum Nachtrag: zuerst gab es nur Wochen und Monate, weil im
   Anforderungspapier steht "Wochen genuegen". Das gilt fuer die QUOTE,
   nicht fuer die ANSICHT - gearbeitet wird mit einem frei gewaehlten
   Tagesbereich. Tage sind jetzt das Grundraster.
   --------------------------------------------------------------------- */
/* `.band-jahr` und `.band-sp u` sind ENTFALLEN: Jahr und Monat standen
   als zwei zusaetzliche Zeilen IN der Tagesspalte und drueckten Zahl und
   Wochentag nach unten - und zwar nur in den Spalten mit Monatswechsel,
   sodass die Zahlen nicht mehr auf einer Linie sassen. Zwei Versuche an
   der Groesse haben das nicht behoben, weil es kein Groessenproblem war.
   Jetzt steht beides in .bz-band darueber. */
/* DREI Stufen, nicht zwei (Michael, 16.09.2026): "wir arbeiten auch
   samstags, trotzdem rechnen wir mit einer fuenf Tageswoche". Der Samstag
   ist also weder ein normaler Werktag noch ein Sonntag - er ist der Tag,
   an dem gearbeitet WIRD, wenn eingeteilt ist. Deshalb abgehoben von
   Montag bis Freitag, aber heller als der Sonntag. */
.band-sp.sa { background: #f7f9fa; }
.band-sp.so { background: #eef1f4; }
.band-sp.sa b, .band-sp.so b, .band-sp.sa i, .band-sp.so i { color: var(--text-3); }
/* Heute ist ein Punkt, kein Rahmen: ein Rahmen um eine 26px-Spalte
   verschiebt die Nachbarn optisch. */
.band-sp.heute b {
  background: var(--primary); color: #fff; border-radius: 999px;
  /* Die Pille darf die Spalte nicht sprengen: bei 28px Spaltenbreite und
     2px Polsterung bleiben 24px. Der Nachweis hat die Spalte "16 Mi"
     ueberlaufen gesehen. */
  /* BLOCK bleiben, nur schmal: als inline-block rutschte der Wochentag
     neben die Pille statt darunter ("16 Mi" nebeneinander) und die
     Spalte lief ueber. Das eine Wort, das den Fehler gemacht hat. */
  display: block; box-sizing: border-box;
  width: max-content; min-width: 16px; max-width: 100%;
  margin: 0 auto; padding: 0 1px;
}
/* Das Wochenende auch in den Zeilen, damit die Woche lesbar bleibt -
   mit demselben Unterschied zwischen Samstag und Sonntag. */
.we-feld { height: 100%; pointer-events: none; }
.we-feld.sa { background: #f7f9fa; }
.we-feld.so { background: #eef1f4; }

/* FARBE IST DIE ART, STAERKE IST DAS VERFAHREN (Michael, 16.09.2026):
   "jeweils in der gleichen Farbe, vielleicht nur unterschiedlich stark".

   Vorlaeufig heisst: der Vorgang ist nicht abgeschlossen. Beim Urlaub ist
   das "noch nicht genehmigt", bei Krankheit "noch ohne Nachweis" - zwei
   verschiedene Sachen, aber dieselbe Bedeutung fuer den, der hinsieht:
   noch nicht endgueltig. Deshalb ein Zeichen fuer beide.

   Gemacht mit `opacity` auf der Fuellung und einem gestrichelten Rand -
   so bleibt der Farbton derselbe, nur blasser, und der Unterschied ist
   auch ohne Farbe zu sehen (gestrichelt gegen durchgezogen). Eine zweite
   Farbe je Art waere die doppelte Anzahl Farben fuer dieselbe Aussage. */
.balken.vorlaeufig {
  border-style: dashed;
  /* Die Fuellung blass, Rand und Schrift bleiben kraeftig - sonst wird
     der Balken unlesbar statt vorlaeufig. */
  background-image: linear-gradient(rgba(255, 255, 255, .62), rgba(255, 255, 255, .62));
}
.balken.vorlaeufig .balken-text { opacity: .8; }

.bz-saeulen { height: 92px; align-items: end; }
.band-namen .bz-saeulen { align-items: center; }
.bz-saeulen .band-spur { align-self: stretch; }
.saeule-feld {
  height: 100%; position: relative;
  display: flex; align-items: flex-end; justify-content: center;
}
.saeule {
  position: absolute; bottom: 0; width: 62%; min-height: 2px;
  background: var(--primary); border-radius: 2px 2px 0 0;
}
/* Offene Antraege sitzen HINTER der vollen Saeule und reichen hoeher:
   zusammen ergeben sie, was zu erwarten ist, wenn alles durchgeht. */
.saeule.beantragt { background: var(--primary-soft); border: 1px dashed var(--primary-rand); }
/* Die Saeulen der Auslastung DUERFEN blau bleiben (Michael,
   16.09.2026): sie sind eine Messung und keine Art. Nur die beiden
   Ausnahmen tragen die Ampel - und "freigegeben" ist dabei gelb, nicht
   gruen: Gruen heisst jetzt "auf der Quote, in Ordnung". */
.saeule.zuviel { background: var(--ampel-rot-text); }
.saeule.freigegeben { background: #d9a520; }

/* Die Verbotszone OBERHALB der Quote - blass getoent, mit einer Kante
   nach unten. Vorher war die Quote eine rote Gerade quer durchs Bild;
   Michael hat sie als Fuellstandsanzeige gelesen, und das zu Recht: eine
   Linie mitten im Diagramm sieht aus wie ein Pegel. Als getoente Decke
   mit Kante liest sie sich als Grenze - und weil sie je Spalte gezeichnet
   wird, ist sie eine Treppe und zeigt die hoehere Ferienquote von selbst. */
.verbot {
  position: absolute; top: 0; left: 0; right: 0;
  background: repeating-linear-gradient(135deg,
    rgba(168, 69, 60, .05) 0 3px, rgba(168, 69, 60, .10) 3px 6px);
  border-bottom: 1px dashed rgba(168, 69, 60, .55);
  pointer-events: none;
}
.saeule-feld.sa { background: #f7f9fa; }
.saeule-feld.so { background: #eef1f4; }
.bz-saeulen { position: relative; }
/* `.quotenlinie` ist ENTFALLEN: eine einzelne Gerade quer durchs
   Diagramm konnte die Quote je Zeitraum nicht abbilden und las sich als
   Pegel. Ersetzt durch `.verbot` je Spalte - siehe dort. */

/* Filter- und Zeitleiste. Mehrere Gruppen in einer Karte, die umbrechen
   darf - sonst wird die Leiste auf einem schmalen Bildschirm breiter als
   die Seite. */
/* Oben ausgerichtet, nicht unten: sobald ein Block umbricht (Gruppe mit
   sieben Teams), standen bei `flex-end` die Beschriftungen auf
   verschiedenen Hoehen. Die Beschriftungen sind die Linie, an der man
   liest. */
.leiste { display: flex; flex-wrap: wrap; gap: 16px 20px; align-items: flex-start; }
.leiste-teil { display: flex; flex-direction: column; gap: 5px; }
.leiste-teil .field-label { line-height: 1; }
.segment-wickeln { flex-wrap: wrap; max-width: 520px; }
.blaettern { display: inline-flex; align-items: center; gap: 10px; font-size: 0.98rem; }
.blaettern a {
  text-decoration: none; color: var(--text-2); border: 1px solid var(--border-strong);
  border-radius: 7px; width: 26px; height: 26px; line-height: 24px; text-align: center;
}
.blaettern a:hover { border-color: var(--primary); color: var(--primary); }
.blaettern b { font-weight: 500; white-space: nowrap; }
.dez-zeile { font-size: 0.8rem; color: var(--text-3); }

/* Legende unter dem Band. */
.legende { margin: 10px 0 0; font-size: 0.84rem; color: var(--text-3); display: flex;
  align-items: center; gap: 4px 16px; flex-wrap: wrap; }
/* Farbe und Wort gehoeren zusammen: als getrennte Kinder eines
   umbrechenden flex-Kastens landete sonst ein Kaestchen ohne Wort am
   Zeilenende. */
.lg-paar { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.lg { width: 13px; height: 11px; border-radius: 3px; display: inline-block; flex: none; }
/* Das Kaestchen muss zeigen, was im Band steht: ein Balken ohne die Art
   ist GRAU, nicht blau. Vorher stand hier Blau, und die Legende
   beschrieb damit eine Farbe, die es im Band nicht gab. */
.lg-fest { background: #eef0f2; border: 1px solid var(--border-strong); }
/* Die Auslastung zeigt SAEULEN und die sind blau (eine Messung, keine
   Art). Ihre Legende braucht deshalb ein eigenes Kaestchen - mit dem
   grauen Balkenkaestchen stand dort eine Farbe, die es in dieser
   Ansicht nicht gibt. */
.lg-saeule { background: var(--primary); }
.lg-saeule-offen { background: var(--primary-soft); border: 1px dashed var(--primary-rand); }
/* Die Familien der Artfarben - zwei Woerter erklaeren alle sechs Arten. */
.lg-fam-plan { background: #f0ebfa; border: 1px solid #b7a4df; }
.lg-fam-ein { background: #fbeae6; border: 1px solid #e6b0a3; }
.lg-offen { background: transparent; border: 1px dashed var(--border-strong); }
.lg-sa { background: #f7f9fa; border: 1px solid var(--border-strong); }
.lg-so { background: #eef1f4; border: 1px solid var(--border-strong); }
.lg-heute { background: var(--primary); }
.lg-vorl { background: #eef4f8; border: 1px dashed var(--border-strong); }
.lg-verbot { background: repeating-linear-gradient(135deg, rgba(168,69,60,.06) 0 3px, rgba(168,69,60,.12) 3px 6px); border: 1px solid rgba(168,69,60,.4); }
.lg-gleich { background: var(--ampel-gruen-bg); border: 1px solid var(--ampel-gruen-text); }
.lg-ueber { background: var(--ampel-gelb-bg); border: 1px solid var(--ampel-gelb-text); }
.lg-freigegeben { background: var(--ampel-gelb-bg); border: 1px solid var(--ampel-gelb-text);
  box-shadow: inset 0 0 0 2px #2f8f66; }
.lg-schon { background: var(--ampel-rot-bg); border: 1px solid var(--ampel-rot-text); }

/* Entscheiden in der Zeile (Antragsliste). */
.entscheiden {
  display: inline-flex; width: 26px; height: 26px; align-items: center;
  justify-content: center; border-radius: 999px; border: 1px solid var(--border-strong);
  font-size: 0.8rem; margin-left: 4px; cursor: default;
}
.entscheiden.ja { color: var(--ok-text); border-color: var(--ok-rand); background: var(--ok-bg); }
.entscheiden.nein { color: var(--danger); border-color: var(--danger-rand); background: var(--danger-bg); }

/* Der Befund zum Informationsfeld. */
table.befund { width: 100%; border-collapse: collapse; font-size: 0.95rem; }
table.befund th, table.befund td { text-align: left; padding: 9px 12px 9px 0;
  border-bottom: 1px solid var(--border); vertical-align: top; }
table.befund th { font-size: 0.8rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-3); font-weight: 500; }
table.befund tr:last-child td { border-bottom: none; }
table.befund code { background: var(--menu); padding: 1px 6px; border-radius: 5px;
  font-size: 0.9rem; }
table.befund .muted { display: block; margin-top: 3px; font-size: 0.88rem; }

/* Eine Zahl, die nicht stimmen kann, wird nicht still angezeigt. */
.stat-falsch { background: var(--danger-bg); color: var(--danger); }

/* Unternavigation eines Abschnitts (Abwesenheit). Nicht in der Kopfzeile:
   dort stehen Handlungen, nicht Ansichten - und .topbar ist 52px hoch und
   bricht nicht um, vier Knoepfe liefen bei 760px aus der Seite. */
.unternav { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 14px; }
.unternav a {
  font-size: 0.98rem; padding: 6px 13px; border-radius: 8px;
  text-decoration: none; color: var(--text-2);
}
.unternav a:hover { background: var(--menu); }
.unternav a.an { background: var(--primary-soft); color: #0a4a6e; font-weight: 500; }

/* Der Vorfuehrschalter am Geruesthinweis. Er steht bewusst NICHT bei den
   Filtern: wer die Art sieht, entscheidet ein Recht und kein Schalter
   (Michael, 16.09.2026). Gestrichelt wie der Geruesthinweis, damit man
   sieht, dass er mit dem Bau verschwindet. */
.geruest-schalter {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  margin: -0.5rem 0 1rem; padding: 0.5rem 1rem;
  border: 1px dashed var(--border-strong); border-radius: 9px;
  background: var(--menu); max-width: 74ch;
  font-size: 0.86rem; color: var(--text-3);
}

/* Der Konflikt an der Antragszeile: mehr Wuensche als Plaetze. Steht
   unter dem Antrag und nicht in einer Fussnote - wer entscheidet, soll
   die Mitbewerber sehen, ohne sie sich aus der Zeitleiste
   zusammenzusuchen. */
.konflikt-zeile td { background: var(--warn-bg); font-size: 0.92rem; color: #6f4a0d; }
.konflikt-zeile strong { color: #5c3d0b; }
ul.mitbewerber { list-style: none; margin: 7px 0; padding: 0; }
ul.mitbewerber li { padding: 3px 0; font-size: 0.92rem; }
.mb-zeit { display: inline-block; min-width: 128px; font-variant-numeric: tabular-nums;
  color: #5c3d0b; font-weight: 500; }
/* Der Rang in der Antragsliste - klein, aber vor dem Zeitpunkt: er sagt,
   dass die Reihenfolge eine Bedeutung hat. */
.rang { color: var(--text-3); font-size: 0.82rem; margin-right: 3px; }

/* Engstellen: ein Zeitraum, in dem mehr Menschen weg waeren als die
   Planungsquote zulaesst. EINMAL je Zeitraum - vorher stand die Liste der
   Mitbewerber an jeder Antragszeile und damit dreimal untereinander.

   Zwei Sorten, und der Unterschied ist wesentlich:
     eng-entscheiden  offene Antraege dabei - hier kann der Entscheider was tun
     eng-tatsache     alle sind schon weg (Krankheitswelle) - hier bleibt
                      nur pruefen und festhalten */
.engstelle { border: 1px solid var(--border); border-radius: 9px; padding: 11px 13px; }
.engstelle + .engstelle { margin-top: 9px; }
.engstelle.eng-entscheiden { border-color: var(--warn-rand, #e8cea0); background: var(--warn-bg); }
.engstelle.eng-tatsache { background: var(--menu); }
.eng-kopf { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; font-size: 0.95rem; }
.eng-art { font-size: 0.86rem; color: var(--text-3); }
.eng-satz { margin: 8px 0 0; font-size: 0.92rem; color: var(--text-2); }
/* Die Marke an der Antragszeile zeigt nur hin - der Inhalt steht unten. */
.marke-eng {
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: .05em;
  text-decoration: none; color: var(--warn-text); background: var(--warn-bg);
  border: 1px solid #e8cea0; border-radius: 999px; padding: 0 0.4rem; margin-left: 0.3rem;
}

/* ---------------------------------------------------------------------
   HINWEIS HINTER EINEM ZEICHEN (Michael, 16.09.2026)

   "Kann man diese langen Texte nicht hinter einem Hinweis-Button
   verstecken? Wuerde die Uebersichtlichkeit verbessern."

   Ja - und zwar als globales Mittel, das auf jeder Seite gleich
   funktioniert. Gebaut mit <details>/<summary> und OHNE JavaScript.
   Warum nicht nur beim Ueberfahren mit der Maus, wie er es kennt:
     - auf dem Handy und am Tablett gibt es kein Ueberfahren,
     - mit der Tastatur gibt es keins,
     - und ein Text, der beim Wegziehen der Maus verschwindet, laesst
       sich nicht lesen, wenn er laenger als zwei Zeilen ist.
   Ein Zeichen, das man ANKLICKT, kann all das. Der Mauszeiger zeigt
   zusaetzlich den Titel, damit klar ist, was der Klick tut.

   Und eine Regel dazu: der erste Satz bleibt SICHTBAR, wenn er die
   Handlung traegt. Eine Seite voller "?" sagt nichts; versteckt wird die
   Begruendung, nicht die Anweisung.
   --------------------------------------------------------------------- */
.hinweis-vorsatz { font-size: 0.92rem; color: var(--text-2); }
/* `inline` und nicht `inline-block`: als inline-block wurde beim
   Aufklappen der GANZE Kasten - Zeichen samt Text - ein Block neben dem
   Satz, und der Satz rutschte mittig daneben. Als reines `inline` bleibt
   das Zeichen in der Zeile, und der Textblock darin bricht die Zeile auf
   und stellt sich darunter. Genau das soll passieren. */
details.hinweis { display: inline; }
/* Ein rundes "i" fuer Information, nicht ein Fragezeichen - "das ist
   fuer mich der logische Button" (Michael, 16.09.2026). Trifft es auch
   besser: ein "?" fragt, ein "i" erklaert. Die Schrift etwas grosser und
   kursiv gesetzt, damit das i in einem 17px-Kreis nicht wie ein Strich
   aussieht. */
details.hinweis > summary {
  display: inline-flex; align-items: center; justify-content: center;
  width: 17px; height: 17px; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--surface);
  color: var(--text-2); font-size: 0.9rem; font-weight: 600;
  font-family: Georgia, "Times New Roman", serif; font-style: italic;
  line-height: 1; padding-right: 1px;
  cursor: pointer; list-style: none; user-select: none;
}
details.hinweis > summary::-webkit-details-marker { display: none; }
details.hinweis > summary::marker { content: ""; }
details.hinweis > summary:hover { border-color: var(--primary); color: var(--primary); }
details.hinweis > summary:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
details.hinweis[open] > summary { background: var(--primary); border-color: var(--primary); color: #fff; }
/* Der Text selbst steht als eigener Block UNTER der Zeile, nicht als
   schwebender Kasten: ein Kasten, der ueber dem Inhalt liegt, verdeckt
   genau das, wozu er etwas erklaert. */
details.hinweis > .hinweis-text {
  display: block; margin: 7px 0 4px; clear: both; padding: 0.7rem 0.9rem;
  border-left: 3px solid var(--primary-rand); background: var(--primary-soft);
  border-radius: 0 8px 8px 0;
  font-size: 0.92rem; line-height: 1.5; color: #0a4a6e;
  max-width: 88ch; font-weight: 400;
}
details.hinweis > .hinweis-text p { margin: 0 0 0.5rem; color: inherit; }
details.hinweis > .hinweis-text p:last-child { margin-bottom: 0; }
details.hinweis > .hinweis-text code { background: rgba(255,255,255,.65); }
/* In einer Ueberschrift sitzt das Zeichen hinter dem Text und traegt
   nicht deren Schriftgroesse. */
h2 > details.hinweis > summary { font-size: 0.82rem; width: 16px; height: 16px; }

/* Eine Zeile mit kurzem Satz und Hinweiszeichen dahinter. Ersetzt die
   langen .field-help-Absaetze: der Satz, der die Handlung traegt, bleibt
   sichtbar, die Begruendung steht hinter dem Zeichen. */
/* Absichtlich ein <div> und kein <p>: der Hinweis dahinter enthaelt
   selbst <p>, und ein <p> darf kein <p> enthalten - der Browser schliesst
   das aeussere dann still, und das Hinweiszeichen landet als Geschwister
   der Karte statt in der Zeile. Genau das hat der Nachweis gemessen
   (parentElement war DIV.card statt P.zeile-hinweis). */
.zeile-hinweis { margin: 0 0 12px; font-size: 0.92rem; color: var(--text-2); }
/* Der Hinweis in der Filterleiste: NICHT `.leiste-teil`, denn das ist ein
   flex-Kasten mit Spaltenrichtung - dort wuerde das Zeichen unter dem
   Vorsatz landen statt daneben. */
.leiste-hinweis { display: flex; align-items: center; gap: 7px; margin-left: auto;
  align-self: center; }
.zeile-hinweis strong { color: var(--text); font-weight: 500; }
/* Eine Tabelle INNERHALB eines Hinweises traegt nicht die Schriftgroesse
   der Ueberschrift, in der das Zeichen sitzt. */
.sicht-innen td { font-weight: 400; font-size: 0.95rem; color: #0a4a6e; }
.sicht-innen td:first-child { color: #073b58; }
.sicht-innen td, .sicht-innen tr:last-child td { border-color: var(--primary-rand); }

/* Ein Kasten mit GERUESTINHALT: Festlegungen zum Beurteilen, keine
   Bedienhilfe - und er verschwindet mit dem Bau. Vorher waren diese
   Saetze ueber die Seite verteilt und steckten hinter Hinweiszeichen;
   Michael hat gefragt, ob sie ueberhaupt noetig sind, und fuer die
   Bedienung sind sie es nicht.
   Gestrichelt wie der Geruesthinweis, damit man am Rahmen sieht, dass
   der Kasten nicht zum Bau gehoert. */
.geruest-kasten {
  background: var(--surface); border: 1px dashed var(--border-strong);
  border-radius: 10px; padding: 16px 18px; margin-top: 14px;
}
.geruest-kasten > h2 { display: flex; align-items: center; gap: 6px; }

/* Auswahlfeld in einer Filterleiste. Mit GET-Formular, damit es ohne
   JavaScript funktioniert und die Ansicht verlinkbar bleibt. */
/* Mehrfachauswahl ohne JavaScript: das Auswahlfeld legt eine Gruppe
   dazu, die gewaehlten stehen daneben als Plaketten mit einem Kreuz.
   Die Leiste waechst nur um das, was wirklich gewaehlt ist. */
.wahl-zeile { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.chips-wahl a.an b { font-weight: 400; opacity: 0.7; margin-left: 3px; }
.chips a.chip-leer { border-style: dashed; color: var(--text-3); }
.chips a.chip-leer:hover { border-style: solid; color: var(--text-2); }

/* Das Jahr: einmal, links vor der Leiste, in der Zeile der Monate. Es
   steht damit "fest am Anfang der Zeitleiste" (Michael, 16.09.2026),
   kostet keine zusaetzliche Zeile und bleibt beim Scrollen stehen -
   die Namensspalte scrollt ja nicht mit. */
.band-namen .bz-band {
  display: flex; align-items: center; justify-content: flex-end;
  padding: 0 8px 0 10px;
}
.leitjahr { font-size: 0.86rem; font-weight: 600; color: var(--text-2); }

.wahl-form { display: flex; align-items: center; gap: 6px; margin: 0; }
.wahl-form select {
  font: inherit; font-size: 0.92rem; padding: 4px 8px;
  border: 1px solid var(--border-strong); border-radius: 7px;
  background: var(--surface); color: var(--text); min-width: 148px;
}
.wahl-form select:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }

/* ==========================================================================
   Das Hinweisfeld am Zeiger (statt des Browserfelds)
   ==========================================================================
   Michael, 16.09.2026: "Das Feld, welches erscheint, wenn man mit der Maus
   ueber einen Block faehrt, sieht sehr unschoen aus, nicht nach
   Systemvorgabe."

   Er hat recht: `title=""` zeichnet der Browser selbst - gelblicher Kasten,
   fremde Schrift, eigene Verzoegerung. In einer Suite mit eigenem Hinweis-
   Zeichen ist das ein Fremdkoerper. Das Feld traegt jetzt dieselbe Handschrift
   wie der Hinweis hinter dem "i": blasses Blau, blauer Rand, dieselbe Schrift.

   Gebaut mit `content: attr(data-feld)` - kein JavaScript, keine zweite
   Quelle fuer den Text.

   ZWEI Dinge, die gemessen werden mussten:
   1. `.band-scroll` rollt waagerecht und schneidet damit auch oben und
      unten ab. Das Feld klappt deshalb NACH OBEN auf: ueber jedem Balken
      liegen die Achsen- und Kopfzeilen (mindestens 86px), unter der
      letzten Zeile waere kein Platz.
   2. Am rechten Rand wuerde ein nach rechts aufklappendes Feld abgeschnitten.
      Die letzten Spalten tragen deshalb `data-feld-links` - serverseitig
      gerechnet (siehe `feld_kippen`), nicht per Skript. */
.balken[data-feld], .band-zahl[data-feld], .saeule-feld[data-feld] { position: relative; }

.balken[data-feld]:hover::after,
.balken[data-feld]:focus-visible::after,
.band-zahl[data-feld]:hover::after,
.saeule-feld[data-feld]:hover::after {
  content: attr(data-feld);
  position: absolute;
  left: var(--feld-x, 0px); right: auto;
  bottom: calc(100% + 6px);
  z-index: 9;
  /* `width: max-content` ist noetig: ein absolut gesetzter Kasten ohne
     Breite schrumpft auf den PLATZ SEINES ELTERNKASTENS - bei einem
     82px breiten Balken wurde das Feld 60px breit und vierzeilig hoch.
     Gemessen, nicht vermutet. */
  width: max-content;
  max-width: 220px;
  padding: 5px 9px;
  border: 1px solid var(--primary-rand);
  border-radius: 7px;
  background: var(--primary-soft);
  color: #0a4a6e;
  font-size: 0.84rem;
  font-weight: 400;
  line-height: 1.35;
  white-space: normal;
  text-align: left;
  box-shadow: 0 2px 8px rgba(16, 32, 48, .14);
  pointer-events: none;
}
.balken[data-feld-links]:hover::after,
.band-zahl[data-feld-links]:hover::after,
.saeule-feld[data-feld-links]:hover::after { left: auto; right: 0; }

/* --- Gebietsbaum ------------------------------------------------------
   Eine Liste, die eine Ebene zeigt: die Einrueckung traegt die Tiefe.
   Kein eigenes Baum-Widget - eine Tabellenzeile mit einem Abstandhalter
   davor, damit Sortierung, Zeilenlink und Chevron gleich bleiben wie in
   jeder anderen Liste. */
.baum-ein { display: inline-block; vertical-align: middle; position: relative; }
/* Eine feine Fuehrungslinie am linken Rand der Einrueckung: sie zeigt die
   Ebene ohne ein Baum-Widget und ohne Klickfolgen. Bei den Wurzeln ist die
   Einrueckung 0 breit, dort erscheint sie deshalb nicht. */
.baum-ein::before {
  content: ""; position: absolute; left: 6px; top: -14px; bottom: -14px;
  border-left: 1px solid var(--border);
}
.baum-ein + a { vertical-align: middle; }
/* Geschlossene Gebiete bleiben lesbar - sie sind Geschichte, kein Fehler. */
tr.zeile-geschlossen td { color: var(--text-3); }
tr.zeile-geschlossen td a { color: var(--text-2); }
