/* app.css -- nur, was Tabler nicht mitbringt.
 *
 * KEIN `<style>`-Block und KEIN `style="..."`-Attribut im Markup, auch nicht in
 * JS-erzeugtem: das Attribut ist Attribut-Parsing und verlangte in der CSP
 * `style-src-attr 'unsafe-inline'`. Laufzeitwerte werden per
 * `element.style.x = v` gesetzt - das ist CSSOM und braucht die Ausnahme nicht.
 */

/* Sichtbarkeit von Ansichten. Eine Klasse statt hidden-Attribut, damit
 * Tabler-Klassen (`page`, `page-center`) daneben bestehen bleiben. */
.ze-hidden {
  display: none;
}

/* ------------------------------------------------------- Kopfzeile ------- */

/* Randloser Icon-Button. Kein Hintergrund, kein Rahmen - die Flaeche entsteht
 * erst beim Ueberfahren.
 *
 * Tablers `.btn` setzt `min-width: 40px` und `min-height: 40px`. Ohne die
 * beiden Nullen hier ist das Padding wirkungslos: 20px Glyph plus 2x6,4px
 * waeren 32,8px, angezeigt wurden trotzdem 40px.
 *
 * 2px Padding sind Absicht und die Untergrenze: der Knopf misst damit
 * 24x24px - genau die Mindestgroesse fuer Zielflaechen nach WCAG 2.2 AA
 * (2.5.8). Weiter herunter geht es nicht, ohne die Regel zu verletzen, und
 * bei 0 klebte die Hover-Flaeche am Glyph. Die Klasse haengt an rund zwanzig
 * Knoepfen quer durch die Anwendung - Kopfzeile, Zeitraum-Leisten,
 * Zuklapp-Knoepfe, Inline-Bearbeiten -, eine Aenderung hier trifft alle. */
.btn-icon2 {
  /* Die Polsterung steht als eigene Eigenschaft, weil eine ZWEITE Regel sie
   * gegenrechnen muss (Kopfzeile, s. u.). Als blosse Zahl driftete das: beide
   * Werte standen als woertliche Gegenstuecke da, und beim Verkleinern der
   * Polsterung zog der Rand ploetzlich zu weit. */
  --icon2-pad: .125rem;

  background: none;
  border: 0;
  min-width: 0;
  min-height: 0;
  padding: var(--icon2-pad);
  line-height: 1;
  color: var(--tblr-secondary);
  cursor: pointer;
  border-radius: var(--tblr-border-radius);
}

.btn-icon2:hover {
  background: var(--tblr-active-bg);
  color: var(--tblr-body-color);
}

/* Deaktiviert: sichtbar inaktiv UND ohne Hover-Wirkung. Beide Deklarationen im
 * zweiten Block sind noetig - `.btn-icon2:hover` setzt auch die FARBE, und ohne
 * das Zuruecksetzen hellt ein toter Knopf beim Ueberfahren trotzdem auf und
 * sieht anklickbar aus. */
.btn-icon2:disabled {
  opacity: .35;
  cursor: default;
}

.btn-icon2:disabled:hover {
  background: none;
  color: var(--tblr-secondary);
}

.btn-icon2.active {
  color: var(--tblr-primary);
}

/* ============================================================================
 * DER FOKUSRING - TABLER SCHALTET IHN AB UND SETZT NICHTS AN SEINE STELLE
 * ============================================================================
 * Wer mit TAB navigiert, sah nicht, auf welchem Knopf er steht. Das ist kein
 * Nebeneffekt der randlosen Icon-Knoepfe, sondern trifft JEDEN `.btn` dieser
 * Anwendung. Gemessen am 2026-08-06 in tabler.min.css (536.141 B):
 *
 *     .btn:focus-visible { ... outline: 0;
 *         box-shadow: var(--tblr-btn-box-shadow), var(--tblr-btn-focus-box-shadow) }
 *     .btn { --tblr-btn-focus-box-shadow: 0 0 0 .25rem
 *                rgba(var(--tblr-btn-focus-shadow-rgb), .5) }
 *
 * und `--tblr-btn-focus-shadow-rgb` wird in der ganzen Datei an GENAU EINER
 * Stelle definiert: im Block `.btn-link`. Ein Knopf ohne diese Variante hat sie
 * nicht. Damit ist `rgba(var(--...), .5)` eine Referenz ohne Rueckfallwert auf
 * etwas Undefiniertes - die Deklaration wird `invalid at computed-value time`,
 * die ganze `box-shadow`-Zeile faellt auf `unset`, also auf `none`.
 *
 * Das `outline: 0` daneben ist eine eigenstaendige, gueltige Deklaration und
 * bleibt stehen. Ergebnis: kein Rahmen vom Browser UND kein Ersatz vom Theme.
 * Genau dieselbe Fehlerklasse wie bei Tabulator weiter unten - nur dort faerbt
 * sie Flaechen transparent, hier kostet sie die Tastaturbedienung (WCAG 2.4.7).
 *
 * Warum es an den Icon-Knoepfen zuerst auffiel: `.btn-icon2` ohne `.btn` (im
 * Zuklapp-Knopf und im Inline-Bearbeiten) wird von `.btn:focus-visible` gar
 * nicht getroffen und behaelt den Rahmen des Browsers. Die beiden Schreibweisen
 * derselben Klasse verhalten sich beim Fokus also VERSCHIEDEN - ein Befund zu
 * der offenen Frage in docs/todo/TODO.md, Abschnitt 6.
 *
 * ----------------------------------------------------------------------------
 * DIE FORM: KERN IN DER AKZENTFARBE, WEICHER HOF DARUM
 * ----------------------------------------------------------------------------
 * Hier stand bis zum 2026-08-06 ein zweiter Ring in `--tblr-body-color` als
 * KONTRASTGARANTIE. Er ist auf Ansage des Autors raus - im Hellmodus war er ein
 * schwarzer Rand um jeden Knopf, und das sah nach Fehler aus statt nach Fokus.
 *
 * An seine Stelle tritt Tablers eigenes Fokusmuster: ein 0.25rem breiter Hof aus
 * `rgba(var(--tblr-primary-rgb), .25)`. Genau das benutzt das Theme bei
 * `.form-control:focus`, `.form-select:focus` und `.form-check-input:focus` -
 * also am Schiebeschalter, den der Autor als stimmig bezeichnet hat. Der
 * Fokusring der Knoepfe spricht damit dieselbe Sprache wie der der
 * Formularfelder. `--tblr-primary-rgb` steht am `:root` und wird von
 * tabler-themes.min.css je Akzentfarbe ueberschrieben - also KEINE undefinierte
 * Kette wie bei der kaputten Variablen oben; das wurde nachgesehen, nicht
 * angenommen.
 *
 * WAS DAS KOSTET, und es ist dieselbe Abwaegung wie bei der Kartenueberschrift
 * weiter unten: ein Fokusindikator braucht nach WCAG 1.4.11 3:1 gegen seine
 * Flaeche. Der halbdurchsichtige Hof traegt dazu nichts bei, es zaehlt allein
 * der 2px-Kern. Gerechnet gegen die Navbar-Flaeche (`--tblr-bg-surface`, weiss
 * bzw. gray-800) reicht der bei fuenf der zwoelf Farben nicht:
 *
 *                    hell   dunkel                      hell   dunkel
 *     gelb           2,13     6,88       blau           5,00     2,94
 *     limette        2,44     6,02       indigo         4,98     2,95
 *     gruen          2,74     5,35       azur/cyan/orange ~3,05  ~4,8
 *
 * Jede Farbe faellt in genau EINEM Modus durch, nie in beiden. Wer die Anwendung
 * barrierefrei betreiben muss, waehlt den Akzent passend zum Farbmodus; die Wahl
 * bleibt dem Benutzer und wird nicht eingeschraenkt.
 *
 * `box-shadow` statt `outline` fuer die Ringe, weil `outline` nur EINE Farbe
 * kann und keinen zweiten Ring zulaesst. Das durchsichtige `outline` daneben ist
 * trotzdem noetig: im Windows-Kontrastmodus (`forced-colors: active`) entfernt
 * das System jeden `box-shadow` - der Fokus waere dort wieder unsichtbar. Ein
 * transparentes Outline wird vom System mit einer Systemfarbe uebermalt und
 * traegt dann allein.
 *
 * `[role="button"]` ist fuer den Benutzernamen in der Kopfzeile: der
 * Popover-Anker ist ein `span` mit `tabindex`, kein `button` -
 * `.btn:focus-visible` trifft ihn also nicht, und er behielt den blauen Rahmen
 * des Browsers. Als Attribut-Selektor statt als ID, damit der naechste Anker
 * derselben Bauart nichts nachzutragen hat. */
.btn:focus-visible,
.btn-icon2:focus-visible,
[role="button"]:focus-visible {
  outline: 2px solid transparent;
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--tblr-primary),
              0 0 0 .25rem rgba(var(--tblr-primary-rgb), .25);
  /* Der RAND bleibt, wie er ohne Fokus ist. Ohne diese Zeile faerbt ihn
   * `.btn:focus-visible` mit `var(--tblr-btn-hover-border-color)` um, und der
   * `.btn`-Block setzt diese Variable in seiner ZWEITEN Definition auf
   * `--tblr-border-active-color` = rgb(169.16, 173.22, 181.34). Auf einem
   * hellen Knopf liest sich dieser 1px-Rand als schwarze Umrandung neben dem
   * farbigen Ring - zwei Rahmen, von denen einer nichts aussagt. */
  border-color: var(--tblr-btn-border-color);
}

/* -------------------------------------------- Der Schiebeschalter im Fokus --
 * Tabler faerbt ihn beim Fokus BLAU, und zwar an zwei Stellen mit derselben
 * fest verdrahteten Zahl `rgb(130.5, 183, 232)` (nachgesehen in
 * tabler.min.css):
 *
 *     .form-check-input:focus { border-color: rgb(130.5, 183, 232) }
 *     .form-check-input:focus { --tblr-form-switch-bg: url("data:...
 *                                   circle ... fill='rgb(130.5, 183, 232)'") }
 *
 * Die zweite ist der KNAUF als SVG-Daten-URI. Sichtbar wird das nur im
 * Aus-Zustand: `:checked` ueberschreibt den Knauf danach mit Weiss. Im
 * Dunkelmodus ist es sogar ausdruecklich so gebaut - die graue Knauf-Regel dort
 * traegt `:not(:focus)`, laesst dem Blau also absichtlich den Vortritt.
 *
 * Der Rand folgt jetzt der Akzentfarbe. Der Knauf dagegen wird auf seinen
 * NORMALWERT zurueckgeholt, nicht eingefaerbt: er zeigt den ZUSTAND an (links
 * aus, rechts ein), nicht den Fokus. Den Fokus tragen Rand und Hof - eine
 * Aussage je Merkmal.
 *
 * Warum nicht in der Akzentfarbe: eine `var()` laesst sich in einer
 * `url("data:...")` nicht aufloesen, die Farbe steht dort als Zeichenkette.
 * Ein `radial-gradient` koennte die Variable zwar lesen, hat aber keine
 * intrinsische Groesse - unter dem `background-size` des Schalters saehe der
 * Knauf anders aus. Deshalb die beiden Daten-URIs wortgleich aus Tabler.
 *
 * `:not(:checked)` ist Pflicht: `.form-switch .form-check-input:checked` steht
 * in tabler.min.css NACH der Fokusregel (Byte 47.169 gegen 46.958), eine Regel
 * von hier steht aber hinter beiden und wuerde sonst auch den eingeschalteten
 * Knauf grau faerben. */
/* Dieselbe fest verdrahtete Zahl steckt in `.form-control:focus` und
 * `.form-select:focus` - der HOF folgt dort schon dem Akzent
 * (`rgba(var(--tblr-primary-rgb), .25)`), nur der Rand blieb blau. Alle drei
 * Feldarten deshalb in einem Selektor. */
.form-control:focus,
.form-select:focus,
.form-check-input:focus {
  border-color: var(--tblr-primary);
}

.form-switch .form-check-input:focus:not(:checked) {
  --tblr-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23e5e7eb'/%3e%3c/svg%3e");
}

[data-bs-theme="dark"] .form-switch .form-check-input:focus:not(:checked) {
  --tblr-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e");
}

/* Die Menueeintraege haben denselben Defekt, nur eine Stufe frueher: Tabler
 * definiert fuer `.dropdown-item` ueberhaupt kein `:focus`, sondern NUR
 * `:hover` (nachgesehen in tabler.min.css). Mit der Tastatur bekam ein Eintrag
 * also gar keine Flaeche - nur den blauen Rahmen des Browsers.
 *
 * Hier ein `inset`-Ring statt eines Hofes: der Eintrag ist so breit wie das
 * Menue, ein aeusserer Ring raendert aus dem Menuekasten heraus. Dazu dieselbe
 * Flaeche wie beim Ueberfahren - Maus und Tastatur sollen denselben Zustand
 * gleich anzeigen. */
.dropdown-item:focus-visible {
  outline: 2px solid transparent;
  outline-offset: -2px;
  background-color: var(--tblr-dropdown-link-hover-bg);
  box-shadow: inset 0 0 0 2px var(--tblr-primary);
}

/* Der fokussierte Icon-Knopf bekommt zusaetzlich die Flaeche des Ueberfahrens.
 * Ohne das ist der Unterschied zwischen "die Maus ist hier" und "die Tastatur
 * ist hier" groesser als noetig - und `.btn:focus-visible` setzt zwar seinerseits
 * `background-color: var(--tblr-btn-hover-bg)`, aber das laeuft ueber dieselbe
 * undefinierte Kette wie oben und landet auf durchsichtig.
 *
 * DIE FARBE DES SYMBOLS BLEIBT, WIE SIE IST. Hier stand bis zum 2026-08-06
 * `color: var(--tblr-body-color)` - aus der Idee, der fokussierte Knopf solle
 * aussehen wie der ueberfahrene. Das war ein Fehler, und er sah nicht aus wie
 * einer: im Browser gemessen (echter #themeBtn, 6-fach vergroessert) sprang das
 * Zeichen beim Fokus von rgb(107, 114, 128) auf rgb(55, 65, 81), also von Grau
 * auf beinahe Schwarz, waehrend alle Nachbarsymbole grau blieben. Bei 24px
 * Knopfgroesse liest sich dieses dunkle Zeichen im farbigen Ring nicht als
 * "eingefaerbt", sondern als schwarzer Rand - so wurde es auch gemeldet.
 *
 * Der Ruhewert wird ausdruecklich WIEDERHOLT statt weggelassen: Tablers
 * `.btn:focus-visible` setzt `color: var(--tblr-btn-hover-color)`, und dieses
 * Token ist am Element gar nicht definiert (nachgemessen). Die Deklaration wird
 * damit ungueltig und faellt auf `unset` - bei einer vererbten Eigenschaft heisst
 * das `inherit`, also die Farbe des Elternteils statt der von `.btn-icon2`. Da
 * `.btn:focus-visible` (0,2,0) staerker ist als `.btn-icon2` (0,1,0), gewaenne
 * das Erben. Ohne diese Zeile waere die Farbe also nicht "unveraendert", sondern
 * zufaellig die der Kopfzeile.
 *
 * Dieselbe Regel wie beim Schiebeschalter-Knauf weiter oben: eine Aussage je
 * Merkmal. Den Fokus tragen Ring und Flaeche, nicht der Inhalt. */
.btn-icon2:focus-visible {
  background: var(--tblr-active-bg);
  color: var(--tblr-secondary);
}

/* Ein gesperrter Knopf ist per TAB nicht erreichbar - falls er es ueber ein
 * Framework doch wird, soll er nicht wie ein bedienbarer aussehen. */
.btn-icon2:disabled:focus-visible {
  background: none;
  color: var(--tblr-secondary);
}

/* Der Abstands-Trick - die Stelle, die man beim Kopieren uebersieht:
 *
 * Die Polsterung der Icon-Buttons addiert sich zum `gap-3` der Kopfzeile. Ohne
 * Gegenrechnung staende neben einem Icon mehr Abstand als zwischen den
 * Textelementen. Die Polsterung bleibt (sie IST die Hover-Flaeche) und wird per
 * negativem Rand herausgerechnet - Ergebnis: ueberall 1rem von Glyphe zu Glyphe.
 *
 * Der Rand ist aus `--icon2-pad` GERECHNET, nicht abgeschrieben. Hier stand
 * `-.4rem`, das woertliche Gegenstueck zur damaligen Polsterung; als die am
 * 2026-08-05 auf 2px sank, zog der Rand zu weit. Dieselbe Kopplung gab es ein
 * zweites Mal in der Zeitraum-Leiste, dort ueberlappten sich die Icons sogar.
 *
 * Die beiden Sonderregeln halten die AEUSSEREN Raender unangetastet - sonst
 * haengt das erste und das letzte Icon aus dem Container heraus.
 * Nicht "aufraeumen": ohne sie sind die Abstaende in der Leiste ungleich. */
.navbar .btn-icon2       { margin-inline: calc(-1 * var(--icon2-pad)); }
.navbar #homeBtn         { margin-inline-start: 0; }
.navbar #btnLogout       { margin-inline-end: 0; }

/* Die Farbe kommt NICHT von hier, sondern zur Laufzeit aus js/app.js - eine
 * Testumgebung wird gelb markiert, weil dort gespiegelte Echtdaten liegen. */
.env-badge {
  text-transform: uppercase;
  letter-spacing: .04em;
}

/* Sonst sieht der Popover-Anker aus wie gewoehnlicher Text. */
#userBadge {
  cursor: pointer;
}

/* Tabler zeichnet .dropdown-header schon als graue Versalien; die Toenung kommt
 * aus Utilities am Element selbst. Eigenes CSS braucht nur der Fall, dass ein
 * Titel ohne Trenner direkt auf einen Eintrag folgt. */
.dropdown-menu .dropdown-item + .dropdown-header {
  margin-top: .5rem;
}

#sessExp,
#sessMlt {
  font-variant-numeric: tabular-nums;
}

/* Popover mit den Benutzerdaten: enger als die Vorgabe, Kopfspalte fett. */
.user-profile-popover .popover-body { padding: .5rem .75rem; }
.user-profile-popover table         { margin-bottom: 0; }
.user-profile-popover th            { font-weight: 600; white-space: nowrap; padding-right: .75rem; }

/* --------------------------------------------- Fuellende Ansichten -------
 * Eine Ansicht, die den Schirm fuellen soll, braucht ZWEI Dinge - eines allein
 * wirkt nicht:
 *
 *   1. eine durchgehende Flex-KETTE vom Container bis zum Tabellen-Host,
 *   2. einen DECKEL, der die Hoehe ueberhaupt erst begrenzt.
 *
 * Die Kette VERTEILT nur eine Hoehe, die es schon gibt. Solange ein Vorfahre
 * mit dem Inhalt waechst, bleibt nichts zu verteilen - die Tabelle wird so hoch
 * wie ihre Zeilen, und ein `height: 100%` an ihr verhaelt sich wie `auto`.
 *
 * Gemessen am 2026-08-05 bei 2000x1180: die Tabelle stand auf 543px inline,
 * darunter blieben 482px leer. In der Kette fehlte an vier Stufen `min-height: 0`
 * oder `display: flex`, und Tablers `.page` traegt `min-height: 100%` - also
 * eine Untergrenze, keine Obergrenze. Genau das ist der fehlende Deckel.
 *
 * Beides haengt an Klassen, nicht an View-IDs: sonst steht derselbe Block je
 * Tabelle da und verliert beim Kopieren eine Zeile.
 *
 * `min-height: 0` ist nirgends ueberfluessig, auch wo es so aussieht - ein
 * Flex-Item hat implizit `min-height: auto`, und das haelt es auf Inhaltshoehe,
 * trotz `flex: 1 1 auto`. */

.page-body > .container-fluid.fill {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* `:not(.ze-hidden)` ist Pflicht, keine Zierde: `.ze-hidden` setzt
 * `display: none` und ist gleich stark (0,1,0). Eine Regel, die hier
 * `display: flex` setzt, stuende SPAETER in der Datei und gewaenne - die
 * gerade ausgeblendete Nachbaransicht waere wieder sichtbar. */
.page-body > .container-fluid.fill > .fill-view:not(.ze-hidden) {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.fill-view > .card,
.fill-view > .card > .card-body {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.fill-table {
  flex: 1 1 auto;
  min-height: 0;
}

/* Der Deckel. Haengt am body und NUR waehrend einer fuellenden Ansicht - sonst
 * verloere jede andere Seite (Stundenauswertung, Hilfe) ihr normales Scrollen.
 * `height`, nicht `min-height`: das zweite erlaubt weiterhin das Wachsen. */
body.page-lock {
  height: 100vh;
  overflow: hidden;
}

body.page-lock .page {
  height: 100%;
}

body.page-lock .page-body {
  min-height: 0;
}

/* ------------------------------------------------------------ Tabellen ----
 * Kompakt-Optik fuer Tabulator, uebernommen aus
 * .claude/skills/tabulator-js/references/compact-table.css - NICHT je Tabelle
 * neu abgeleitet. Die Klasse sitzt am HOST-Element (`.tbl-compact`), nicht an
 * einer ID: per ID driftet der Block, sobald ihn die zweite Tabelle kopiert.
 *
 * Die Groessenleiter ist Absicht: Zellentext (.85rem) > Spaltentitel (.8rem) >
 * Filtereingabe (.7rem). Die Filterzeile ist Werkzeug, kein Inhalt - wenn sie
 * mit dem Text konkurriert, sieht die Tabelle aus wie ein Formular.
 */
.tbl-compact .tabulator-row { min-height: 24px; }
.tbl-compact .tabulator-cell { padding: 2px 6px; font-size: .85rem; }

/* Die strukturellen Klassen stehen hier mit, nicht aus Versehen: die
 * Theme-Regel ist (0,4,0) bzw. (0,4,1) stark. Eine kurze Regel mit nur der
 * Host-Klasse VERLIERT - der Kopf behielte seine 12px Polsterung und die
 * Filterzeile ihre 1rem Schrift. Kein !important noetig, nur dieselbe Tiefe. */
.tbl-compact .tabulator-header .tabulator-col .tabulator-col-content { padding: 2px 6px; }
.tbl-compact .tabulator-col-title { font-size: .8rem; line-height: 1.2; }
.tbl-compact .tabulator-header .tabulator-col .tabulator-header-filter input:not([type="checkbox"]),
.tbl-compact .tabulator-header .tabulator-col .tabulator-header-filter select {
  padding: 1px 4px; font-size: .7rem; height: 22px; line-height: 1.2;
}

/* Zwei Achsen, ZWEI verschiedene Werte - das ist keine Schlamperei:
 *   y: scroll  reserviert den Balken dauerhaft. Mit `auto` erschiene er erst
 *              beim Nachladen von Zeilen, die Inhaltsbreite aenderte sich in
 *              dem Moment, und die Spalten spraengen.
 *   x: auto    weil die Breite feststeht, sobald die Spalten stehen. Hier
 *              stand `scroll` und zeigte deshalb dauerhaft einen waagerechten
 *              Balken, auch wenn nichts zu rollen war. */
.tbl-compact .tabulator-tableholder { overflow-x: auto; overflow-y: scroll; }

/* Die Summenzeile am Fuss von "Summen je Sachbearbeiter" (js/views/rechnung.js).
 *
 * Sie ist eine DATENZEILE, keine Tabulator-Fussleiste - Begruendung dort. Damit
 * sie trotzdem als Abschluss zu lesen ist, bekommt sie eine Oberlinie und
 * Fettschrift. `color-mix` gegen die Flaechenfarbe statt eines festen Grautons:
 * so traegt sie im Dunkelmodus dieselbe Absicht (etwas abgesetzt) statt eines
 * hellen Balkens.
 *
 * `html` vorn und `.tbl-compact` dazu, aus demselben Grund wie bei der
 * ausgewaehlten Zeile weiter oben: die Zebrastreifen-Regel des Themes ist
 * spezifischer als eine nackte Klassenregel und gewaenne sonst. */
html .tabulator.tbl-compact .tabulator-row.ze-summenzeile {
  font-weight: 600;
  border-top: 2px solid var(--tblr-border-color);
  background-color: color-mix(in oklab, var(--tblr-secondary) 10%, var(--tblr-bg-surface));
}

/* Eine Auslagenzeile in der Summenkarte (seit 2026-09-05): gedaempft, damit
 * sie sich von den Sachbearbeiter-Zeilen absetzt, ohne wie eine Summe zu
 * wirken. Derselbe Selektor-Aufbau wie darueber, aus demselben Grund. */
html .tabulator.tbl-compact .tabulator-row.ze-auslagezeile {
  color: var(--tblr-secondary);
}

/* Der Tooltip haengt am body, nicht am Tabellen-Host - deshalb UNGESCOPED.
 * Das bs5-Theme laesst ihn fast unsichtbar und setzt im Dunkelmodus eine
 * Bootstrap-Variable, die es unter Tabler nicht gibt (Ergebnis: durchsichtig).
 * Beide Selektoren sind noetig, die Theme-Regel ist die spezifischere. */
.tabulator-tooltip,
html[data-bs-theme="dark"] .tabulator-tooltip {
  background: color-mix(in oklab, var(--tblr-primary) 10%, var(--tblr-bg-surface));
  color: var(--tblr-body-color);
  border: 1px solid var(--tblr-primary);
  border-radius: var(--tblr-border-radius);
  max-width: 320px;
  padding: .25rem .5rem;
  box-shadow: var(--tblr-box-shadow);
}

/* ------------------------------------------------- Tabulator folgt dem Thema --
 * Tabulators bs5-Theme ist fuer Hell/Dunkel UND fuer eine Akzentfarbe gebaut -
 * es spricht nur die falsche Variablensprache. Gemessen am 2026-08-06 in
 * tabulator_bootstrap5.min.css (53.063 B, das ist die Datei aus index.html):
 *
 *     var(--bs-...)             75 Aufrufe, 9 Namen, davon 0 mit Rueckfallwert
 *     var(--tblr-...)            0
 *     [data-bs-theme=dark]      64 Selektoren  -> der Dunkelmodus IST da
 *
 * Tabler definiert von diesen neun Namen KEINEN (in tabler.min.css steht genau
 * ein `--bs-*`, naemlich `--bs-position`) - wohl aber zu jedem den
 * `--tblr-`-Zwilling. Die 64 Dunkelregeln greifen also, ihre Werte kommen aber
 * aus undefinierten Eigenschaften: eine `var()`-Referenz OHNE Rueckfallwert auf
 * etwas Undefiniertes macht die Deklaration `invalid at computed-value time`,
 * die Eigenschaft faellt auf `unset` - bei `background-color` also auf
 * TRANSPARENT. Die Tabelle zeigt im Dunkelmodus den Seitenhintergrund durch,
 * statt eigene Flaechen zu setzen. Derselbe Befund wie beim Tooltip oben.
 *
 * Neun Zeilen Bruecke, und das Theme folgt von selbst. Am `:root`, nicht am
 * Tabellen-Host: Tabulator haengt Tooltip, Menue und Editier-Popup an den
 * `body`, ausserhalb der Tabelle. Gefahrlos, weil Tabler `--bs-*` sonst nicht
 * benutzt. Und die Werte sind selbst dunkelmodusfaehig, weil sie erst bei der
 * Benutzung aufgeloest werden - Tabler definiert die `--tblr-`-Seite ebenfalls
 * am `:root` (bzw. an `[data-bs-theme=dark]`, was dasselbe Element ist). */
:root {
  --bs-body-bg:               var(--tblr-body-bg);
  --bs-body-color:            var(--tblr-body-color);
  --bs-border-color:          var(--tblr-border-color);
  --bs-secondary-bg:          var(--tblr-secondary-bg);
  --bs-tertiary-bg:           var(--tblr-tertiary-bg);
  --bs-emphasis-color:        var(--tblr-emphasis-color);
  --bs-secondary-color:       var(--tblr-secondary-color);
  --bs-tertiary-color:        var(--tblr-tertiary-color);
  --bs-primary-border-subtle: var(--tblr-primary-border-subtle);
}

/* Zwei Stellen erreicht die Bruecke NICHT, weil dort gar keine Variable steht:
 *
 *   gewaehlte Zeile      #9abcea (5 Regeln), Hover darauf #769bcc
 *   ueberfahrene Zeile   #ced4da
 *
 * Das ist Bootstrap-Blau und ein helles Grau, fest verdrahtet. Es trifft diese
 * Anwendung unmittelbar: beide Tabellen der Zeiterfassung laufen mit
 * `selectableRows: 1` (js/views/timerec.js), die Auswahl ist dort der Zeiger
 * auf die Ebene darunter. Sie war damit immer blau - auch bei gruenem Thema -
 * und im Dunkelmodus hellgrau auf dunklem Grund.
 *
 * Gemischt statt gesetzt: `color-mix` mit der Flaechenfarbe haelt den Kontrast
 * zum Text in BEIDEN Modi, waehrend ein voller `--tblr-primary` als Flaeche den
 * Text schlucken wuerde. Gleiche Machart wie beim Tooltip oben.
 *
 * Zur Spezifitaet: die staerkste Theme-Regel fuer die Auswahl ist
 * `html[data-bs-theme=dark] .tabulator .tabulator-row.tabulator-selected`
 * mit (0,4,1). Die Regel hier hat mit der Host-Klasse dieselbe Staerke -
 * entschieden wird ueber die Reihenfolge der Stylesheets, und app.css steht in
 * index.html hinter dem Tabulator-CSS. Kein !important noetig.
 *
 * `[data-bs-theme]` taugt hier NICHT als Aufhaenger: Tablers Bootskript
 * ENTFERNT das Attribut beim Standardwert, im Hellmodus gibt es also keines. */
html .tabulator.tbl-compact .tabulator-row.tabulator-selected {
  background-color: color-mix(in oklab, var(--tblr-primary) 26%, var(--tblr-bg-surface));
}

html .tabulator.tbl-compact .tabulator-row.tabulator-selected:hover {
  background-color: color-mix(in oklab, var(--tblr-primary) 34%, var(--tblr-bg-surface));
}

/* Zeilenstreifung im DUNKELMODUS - hell gibt es sie laengst.
 *
 * `.tabulator-row.tabulator-row-even { background-color: #e9ecef }` steht im
 * Theme UNBEDINGT und faerbt jede zweite Zeile grau. Im Dunkelmodus ueberschreibt
 * `html[data-bs-theme=dark] .tabulator .tabulator-row` sie mit der Flaechenfarbe -
 * dort waren also ALLE Zeilen gleich (gemessen im Browser 2026-08-06: hell
 * abwechselnd rgb(255,255,255) und rgb(233,236,239), dunkel durchgaengig
 * rgb(28,25,23)). Dieselbe Tabelle sah in den beiden Modi verschieden aus.
 *
 * Die Streifenfarbe ist `--tblr-bg-surface` (die Kartenfarbe, gray-800) gegen die
 * Zeilenfarbe `--tblr-body-bg` (gray-900) - im Dunkelmodus ist der Streifen also
 * HELLER als die Grundzeile, hell ist er dunkler. Beide Male rund 15 bis 20 von
 * 255 Unterschied.
 *
 * Die Spezifitaet ist auf (0,4,0) AUSGERECHNET, nicht geraten - sie muss in einem
 * schmalen Fenster liegen:
 *
 *   schlaegt   html[data-bs-theme=dark] .tabulator .tabulator-row      (0,3,1)
 *   verliert   gegen die Auswahlregel oben                             (0,4,1)
 *   verliert   gegen die Hover-Regel des Themes                        (0,4,1)
 *
 * Deshalb steht hier weder `html` davor noch die Host-Klasse dahinter: jedes
 * zusaetzliche Glied kippt die Rechnung, und die gewaehlte Zeile waere auf jeder
 * zweiten Position wieder unsichtbar. */
[data-bs-theme="dark"] .tabulator .tabulator-row.tabulator-row-even {
  background-color: var(--tblr-bg-surface);
}

/* Die nicht gewaehlte Zeile beim Ueberfahren - derselbe Ton, den auch die
 * randlosen Icon-Knoepfe benutzen, damit "hier bin ich gerade" ueberall gleich
 * aussieht.
 *
 * HAENGT NICHT AN `.tabulator-selectable`, und das ist der Punkt: diese Klasse
 * vergibt Tabulator nur, wenn die Zeilenauswahl EINGESCHALTET ist (im Bundle:
 * `classList.toggle("tabulator-selectable", i)`). Und `selectableRows` steht
 * nur in js/views/timerec.js. In den drei anderen Tabellen - Uebersicht,
 * Stammdaten, Aktenauswahl - fehlt die Klasse also, und damit griff weder
 * Tabulators eigene Regel (`#ced4da`, fest) noch diese hier: beim Ueberfahren
 * passierte dort GAR NICHTS, waehrend die Zeiterfassung mitfaerbte. Genau so
 * wurde es gemeldet.
 *
 * Die Spezifitaet ist (0,4,1) und muss es sein: mit nur `.tabulator-row:hover`
 * waere sie (0,3,1) und verloere im Dunkelmodus gegen die Streifenregel
 * weiter unten (0,4,0) - jede zweite Zeile bliebe dann ohne Hover.
 *
 * Der ZEIGER bleibt trotzdem den zwei Zeiterfassungstabellen vorbehalten
 * (`.ze-table-*`, weiter unten): ein Ton sagt "diese Zeile liest du gerade",
 * ein Zeiger verspricht "ein Klick tut etwas". Das zweite stimmt nur dort. */
html .tabulator.tbl-compact .tabulator-row:hover {
  background-color: var(--tblr-active-bg);
}

/* --------------------------------------- Akzentfarbe, wo sie etwas SAGT -----
 * Vier Stellen, an denen die gewaehlte Akzentfarbe einen Zustand sichtbar macht
 * statt nur zu schmuecken. Die Bedeutungsfarben der Statusspalte (offen,
 * abgerechnet, storniert) bleiben ausdruecklich AUSSEN VOR - die duerfen sich
 * nicht mit einer Geschmackseinstellung aendern.
 *
 * ZUR SPEZIFITAET, einmal fuer alle Regeln hier: das Theme faerbt Kopf, Spalte
 * und Sortierpfeil mit langen Ketten und hart kodierten Farben. Gemessen:
 *
 *     .tabulator .tabulator-header .tabulator-col                       (0,3,0)
 *     html[data-bs-theme=dark] … .tabulator-header .tabulator-col       (0,5,1)
 *     .tabulator … [aria-sort=ascending] … .tabulator-arrow             (0,8,0)
 *
 * Die Regeln hier tragen deshalb `html` und dieselbe Kettenlaenge: gleich stark
 * wie die Dunkelregel, entschieden ueber die Reihenfolge der Stylesheets
 * (app.css steht in index.html hinter dem Tabulator-CSS), und staerker als die
 * Hellregel. Kein !important. Wer eine Kette kuerzt, schaltet die Regel im
 * Dunkelmodus still ab. */

/* Hier stand am 2026-08-06 kurz eine durchgehende Toenung des Tabellenkopfes
 * (7 Prozent Akzent). Sie ist auf Ansage des Autors wieder raus: die Toenung
 * liegt zwangslaeufig auch hinter der FILTERZEILE, und dort stoert sie - ein
 * Werkzeugbereich soll ruhig bleiben. Sie liesse sich nicht sauber auf die
 * Titelzeile beschraenken, weil die Polsterung der Spalte (`.tabulator-col-content`)
 * zur Spalte gehoert und nicht zur Zeile darin; eine Teil-Toenung wuerde als
 * fleckiger Rand um die Eingabefelder erscheinen.
 *
 * Was BLEIBT, ist die Toenung der sortierten Spalte weiter unten - die sagt
 * etwas (wonach ist sortiert) und steht nicht dauerhaft da. */

/* Die SORTIERTE Spalte - `aria-sort` setzt Tabulator selbst, es
 * braucht also keine Zeile JavaScript. Bis hier war nur ein winziger Pfeil in
 * #666 der Hinweis darauf, wonach die Tabelle gerade sortiert ist. */
html .tabulator.tbl-compact .tabulator-header .tabulator-col[aria-sort="ascending"],
html .tabulator.tbl-compact .tabulator-header .tabulator-col[aria-sort="descending"] {
  background-color: color-mix(in oklab, var(--tblr-primary) 16%, var(--tblr-bg-surface));
}

/* Der Pfeil dazu. Er ist kein Zeichen, sondern ein CSS-Dreieck aus
 * `border-bottom`/`border-top` - deshalb wird die KANTENFARBE gesetzt und nicht
 * `color`. Nur die jeweils sichtbare Kante, sonst entsteht ein zweites Dreieck. */
html .tabulator .tabulator-header .tabulator-col.tabulator-sortable[aria-sort="ascending"] .tabulator-col-content .tabulator-col-sorter .tabulator-arrow {
  border-bottom-color: var(--tblr-primary);
}

html .tabulator .tabulator-header .tabulator-col.tabulator-sortable[aria-sort="descending"] .tabulator-col-content .tabulator-col-sorter .tabulator-arrow {
  border-top-color: var(--tblr-primary);
}

/* Ein Filterfeld MIT Inhalt. Die Klasse setzt js/core/table-defaults.js
 * (markiereGefuellteFilter) - CSS kann "hat einen Wert" bei einem `input` nicht
 * ausdruecken. Der innere Schatten statt einer dickeren Umrandung: eine echte
 * Rahmenbreite wuerde das Feld groesser machen und die 22px-Filterzeile der
 * Kompakt-Optik sprengen. */
html .tbl-compact .tabulator-header .tabulator-col .tabulator-header-filter input.ze-filter-aktiv,
html .tbl-compact .tabulator-header .tabulator-col .tabulator-header-filter select.ze-filter-aktiv {
  border-color: var(--tblr-primary);
  box-shadow: inset 0 0 0 1px var(--tblr-primary);
}

/* Der Kopf des Fensters "Abrechnung pruefen" in ZWEI Zeilen (Autor,
 * 2026-09-21): oben Akte und Positionen, darunter Nettobetrag, Umsatzsteuer,
 * E-Rechnung und USt-IdNr/Land. Tablers `.datagrid` ist ein Grid mit
 * `auto-fit` - es verteilt nach Platz, und die sechs Felder standen in einer
 * Reihe. Hier vier feste Spalten; die Akte nimmt drei, damit ein langer
 * Mandantenname nicht umbricht und die Positionen rechts ueber der vierten
 * Spalte stehen. Schmal (unter 768px) werden es zwei Spalten, die Akte dann
 * ueber beide. */
.datagrid.ze-vorb-kopf {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.datagrid.ze-vorb-kopf > .ze-vorb-akte {
  grid-column: span 3;
}
@media (max-width: 767.98px) {
  .datagrid.ze-vorb-kopf {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .datagrid.ze-vorb-kopf > .ze-vorb-akte {
    grid-column: span 2;
  }
}

/* Die Kurzangabe im Kopf der zuklappbaren Abschnitte von "Abrechnung pruefen"
 * (seit 2026-09-21): sie nimmt den Platz zwischen Ueberschrift und Knopf und
 * wird abgeschnitten statt umzubrechen. `min-width: 0` ist der Teil, ohne den
 * `text-truncate` in einer Flex-Zeile nichts bewirkt - das Element wuerde so
 * breit wie sein Text und schoebe den Knopf aus der Karte. */
.ze-vorb-kurz {
  flex: 1 1 0;
  min-width: 0;
  font-size: .8125rem;
}

/* DER FOKUS IM KOPFZEILENFILTER (seit 2026-09-21). Tabulators Stylesheet hat
 * genau EINE `focus`-Regel, mit drei festen Farben und ohne Ersatz fuer das
 * abgeschaltete Outline: `.tabulator-header-filter input:focus {
 * background-color:#fff; border-color:#86b7fe; color:#212529; outline:0 }`.
 * Im Dunkelmodus wurde das Feld beim Fokus WEISS, und dem Akzent folgte es nie
 * (gemessen 2026-08-06). Diese Kette (0,3,2 mit `html`) schlaegt sie ohne
 * `!important`. Der Hof ist 2px statt .25rem: die Filterzeile der Kompakt-Optik
 * ist 22px hoch, ein 4px-Hof liefe in die Nachbarspalte.
 * NICHT im Browser nachgemessen - die Werte stammen aus dem Befund. */
html .tabulator .tabulator-header-filter input:focus,
html .tabulator .tabulator-header-filter select:focus {
  background-color: var(--tblr-bg-forms);
  color: var(--tblr-body-color);
  border-color: var(--tblr-primary);
  box-shadow: 0 0 0 2px rgba(var(--tblr-primary-rgb), .25);
}

/* Tastaturbedienung (js/core/table-a11y.js): der Rollbereich ist der EINE
 * Tabstopp einer Tabelle, sortierbare Spaltenkoepfe sind weitere. Beide
 * brauchen einen sichtbaren Fokus - nach innen versetzt, damit der Rahmen der
 * Karte ihn nicht abschneidet. `:focus-visible`, nicht `:focus`: ein Mausklick
 * in die Tabelle soll keinen Rahmen zeichnen. */
html .tabulator .tabulator-tableholder:focus-visible,
html .tabulator .tabulator-col.tabulator-sortable:focus-visible {
  outline: 2px solid var(--tblr-primary);
  outline-offset: -2px;
}

/* Hier stand am 2026-08-06 kurz eine 2px-Akzentlinie oben an jedem Kartenkopf
 * (`box-shadow: inset 0 2px 0 0 var(--tblr-primary)`). Sie ist auf Ansage des
 * Autors wieder raus. An ihre Stelle tritt die Ueberschrift der Karte:
 *
 * ============================================================================
 * DIE AKZENTFARBE SELBST - UND WAS DAS BEIM KONTRAST KOSTET
 * ============================================================================
 * Entscheidung des Autors: die Ueberschrift traegt die GEWAEHLTE Farbe, nicht
 * eine abgedunkelte Fassung davon. Eine Mischung (hier stand kurz `color-mix`
 * mit 45 Prozent) haelt zwar jeden Kontrastwert ein, ist aber sichtbar nicht
 * mehr die Farbe, die im Panel angeklickt wurde - und genau die soll man
 * wiedererkennen.
 *
 * Der Preis ist gemessen und bekannt. Tablers `.card-title` ist 16px bei
 * Gewicht 500, nach WCAG also NORMALER Text - die Schwelle liegt bei 4,5:1,
 * nicht bei 3:1 ("gross" beginnt erst bei 24px oder 18,66px fett). Auf weisser
 * Karte gemessen (2026-08-06, alle zwoelf Farben):
 *
 *     bestehen    Blau 5,00, dazu Indigo, Violett, Pink, Rot
 *     darunter    Petrol/Cyan/Azur/Orange knapp, Gruen 2,74,
 *                 Limette 2,44, Gelb 2,13
 *
 * Im DUNKELMODUS dreht sich das um: dort sind die hellen Toene die guten.
 *
 * Das ist eine Ueberschrift, kein Fliesstext, und der Text daneben ("50 von 210
 * Akten") bleibt in der Koerperfarbe - der Inhalt der Karte ist also nicht
 * betroffen. Wer die Anwendung barrierefrei betreiben muss, waehlt einen der
 * dunklen Akzenttoene; die Wahl steht dem Benutzer frei und wird nicht
 * eingeschraenkt.
 *
 * `--tblr-primary-text-emphasis` ist KEIN Ausweg: der Wert ist mit rgb(2,44,84)
 * fest und folgt der Akzentfarbe nicht (bei allen vier geprueften Farben
 * derselbe Wert). */
.card-header .card-title {
  color: var(--tblr-primary);
}

/* Der Zusatz HINTER dem Gedankenstrich - die gerade gewaehlte Akte - bleibt in
 * der Koerperfarbe. Farbig ist, was die KARTE benennt ("Buchungen"), nicht was
 * gerade darin steht: ein Mandantenname in der Akzentfarbe waere eine Aussage
 * ueber ihn. Nebenbei entschaerft das den Kontrast dort, wo der Text lang ist
 * und wirklich gelesen wird. Gesetzt wird die Klasse in js/views/timerec.js. */
.card-header .card-title .ze-titel-zusatz {
  color: var(--tblr-body-color);
}

/* PER TABELLE, nicht geteilt: der Zeiger verspricht "ein Klick tut etwas".
 * Das stimmt hier - beide Tabellen steuern die Ebene darunter. In einer
 * Tabelle, die an Ort und Stelle bearbeitet wird, waere es falsch. */
.ze-table-akten .tabulator-row,
.ze-table-buchungen .tabulator-row { cursor: pointer; }

/* HIER STEHT ABSICHTLICH KEINE HOEHE fuer die beiden Tabellen.
 *
 * Tabulator schreibt die Hoehe als INLINE-STYLE auf das Host-Element
 * (gemessen 2026-08-02: style="height: 100%"). Eine Regel an dieser Stelle -
 * gleich welcher Spezifitaet, gleich in welchem Layer - verliert dagegen, weil
 * eine normale Inline-Deklaration ueber jeder Autorenregel steht. Der Versuch
 * hat genau das produziert: korrekt aussehendes CSS und eine Tabelle mit
 * Hoehe 0.
 *
 * Die Hoehe wird deshalb an Tabulator uebergeben und in Zeilen gerechnet:
 * js/core/table-defaults.js (tableHeight) und die Zeilenzahlen in
 * js/views/timerec.js. Wer sie aendern will, aendert sie DORT.
 */

/* Zugeklappte Karte: der Kopf soll nicht unten abgeschnitten wirken, wenn der
 * Rumpf per d-none verschwindet. */
.card-is-collapsed .card-header { border-bottom: 0; }

/* ----------------------------------------------------------- Diagramme ----
 * Chart.js misst den ELTERN-Container, nicht das Canvas. Mit
 * `maintainAspectRatio: false` (setzt die Registry) braucht dieser Container
 * eine echte Hoehe und `position: relative` - ohne beides wird die Flaeche 0
 * oder waechst bei jedem Resize weiter.
 *
 * Dieselbe Falle wie bei Tabulator, aber mit umgekehrtem Vorzeichen: dort
 * schreibt die Bibliothek die Hoehe inline und CSS verliert, hier liest sie das
 * CSS und ohne Angabe steht nichts da.
 */
.ze-chart-wrap {
  position: relative;
  height: 320px;
}

/* Die Zeitraum-Leiste: Pfeile und Kalenderknoepfe in einer Reihe.
 *
 * Hier stand `margin-inline: -.4rem` an den Knoepfen - der Wert war die
 * woertliche Gegenrechnung zur damaligen Polsterung von `.4rem`, damit der
 * Abstand von Glyphe zu Glyphe 1rem blieb statt 1.4rem. Diese Kopplung war
 * unsichtbar: als die Polsterung am 2026-08-05 auf 2px sank, zog derselbe
 * Rand 12,8px zu weit und die Icons ueberlappten sich (im Browser gesehen).
 *
 * Jetzt gibt es keinen negativen Rand mehr. Bei 2px Polsterung braucht es ihn
 * nicht: der Abstand kommt aus `gap`, und der steht hier als eine Zahl statt
 * verteilt auf zwei gegenlaeufige Werte. Wer die Polsterung von `.btn-icon2`
 * aendert, muss diese Leiste nicht mehr anfassen. */
.ze-rangebar {
  display: flex;
  align-items: center;
  gap: .5rem;
}

/* ============================================================================
 * EINE GROESSE FUER ALLE ICONS: fs-2, wie in der Kopfzeile
 * ============================================================================
 * Hier stand kurzzeitig eine Sonderregel, die die Pfeile auf 1.6rem hochsetzte.
 * Der Anlass war messbar, die Antwort trotzdem falsch - festgehalten, damit sie
 * niemand ein zweites Mal einbaut.
 *
 * Gemessen (Canvas, actualBoundingBox, alle bei 20px): Tabler-Icons teilen sich
 * das 24er-Raster, nicht die Menge Tinte darin.
 *
 *     ti-home             18 x 18     Kopfzeile
 *     ti-logout           18 x 16     Kopfzeile
 *     ti-calendar*        16 x 18     diese Leiste
 *     ti-arrow-left/right 14 x 12     diese Leiste - weniger Tinte
 *
 * Ein Pfeil ist also ein schlankeres Zeichen als ein Haus. Das auszugleichen
 * heisst aber, die SCHRIFTGROESSE zwischen benachbarten Knoepfen derselben
 * Leiste auseinanderlaufen zu lassen - 25.6px neben 20px. Die Entscheidung des
 * Autors: eine Groesse, ueberall `fs-2`, so wie in der Kopfzeile. Dass ein
 * Pfeil dann schlanker wirkt, ist eine Eigenschaft des Symbols, kein Fehler.
 *
 * Wer die Pfeile praesenter haben will, waehlt ein ANDERES Symbol - nicht eine
 * andere Groesse. */

/* Eine Zelle, deren Klick etwas TUT - hier die Zuordnungsspalte der
 * Aktenauswahl. Ohne den Zeiger sieht die Spalte aus wie jede andere Anzeige,
 * und ein Schalter, den niemand fuer einen Schalter haelt, wird nicht bedient.
 *
 * Als Spaltenklasse (`cssClass` in der Spaltendefinition) und nicht ueber die
 * Tabellen-ID: die naechste Tabelle mit einer schaltbaren Spalte nimmt dieselbe
 * Klasse, statt den Block zu kopieren. */
.tabulator .tabulator-cell.ze-klickbar { cursor: pointer; }

/* Datumsfeld in einer Kartenkopfzeile.
 *
 * Tablers `.form-control` ist `width: 100%` - in einem Flex-Kasten heisst das:
 * das Feld nimmt die ganze Zeile, die Beschriftung rutscht darueber und die
 * Schaltflaechen darunter. Gemessen im Browser, sah aus wie ein Umbruchfehler
 * und ist die Vorgabe des Frameworks.
 *
 * 9.5rem statt einer Pixelzahl: der Inhalt ist "31.12.2026" plus das
 * Kalendersymbol des Browsers, und beides skaliert mit der Schriftgroesse. */
.ze-datum {
  width: 9.5rem;
  flex: 0 0 auto;
}

/* Der Farbpunkt der Legende. Die FARBE kommt zur Laufzeit aus dem Datensatz
 * (element.style.background in js/views/stundenauswertung.js) - hier steht nur die
 * Form, denn ein style-Attribut im Markup verbietet die CSP. */
.ze-legend-dot {
  width: .75rem;
  height: .75rem;
  /* Folgt dem Eckenradius aus dem Themenpanel. Der schiebt NUR den Faktor
   * `--tblr-border-radius-scale` (0 … 2), multipliziert wird in tabler.min.css -
   * eine feste Pixelzahl bliebe deshalb stehen, waehrend rundherum alles
   * eckiger oder runder wird. Der Entwurfswert 2px bleibt die Grundlage, der
   * Faktor 1 ist die Notfalldefinition, falls das Themen-Stylesheet fehlt. */
  border-radius: calc(2px * var(--tblr-border-radius-scale, 1));
  display: inline-block;
  flex: 0 0 auto;
}

/* Die Legende ist bedienbar: ein Klick blendet den Abrechnungsstatus aus. Sie
 * besteht deshalb aus Knoepfen, nicht aus Text - und muss auch so aussehen,
 * sonst probiert es niemand. */
.ze-legend-btn {
  background: none;
  border: 0;
  padding: 0;
  color: var(--tblr-secondary);
  cursor: pointer;
}

.ze-legend-btn:hover {
  color: var(--tblr-body-color);
}

/* Ausgeblendet: durchgestrichen UND blass. Zwei Merkmale, nicht eines - allein
 * ueber die Deckkraft waere der Zustand fuer jemanden mit Farbsehschwaeche oder
 * auf einem schlechten Schirm kaum zu erkennen. */
.ze-legend-btn.ze-legend-aus {
  opacity: .45;
  text-decoration: line-through;
}

/* -------------------------------------------------- Hilfe und Lizenzen ----
 * Gerendertes Markdown. Tabler formatiert Ueberschriften und Absaetze bereits;
 * hier steht nur, was im Fliesstext sonst zu eng oder zu breit waere.
 */
.ze-markdown {
  max-width: 62rem;          /* Lesbarkeit: eine Zeile ueber die volle Breite
                                eines grossen Schirms verliert man beim
                                Zeilenwechsel */
  font-size: .9rem;          /* Hilfetext wird GELESEN, nicht bedient - er darf
                                dichter stehen als die Oberflaeche */
}

.ze-markdown li { font-size: .9rem; }
/* Eine Hilfetabelle ist ein Nachschlagewerk, kein Datengitter. */
.ze-markdown table { font-size: .85rem; }
/* `em`, nicht `rem`: Code im Fliesstext und Code in der Tabelle sollen jeweils
 * zu IHRER Umgebung passen. */
.ze-markdown code { font-size: .85em; }

/* Symbole IM Hilfetext. Ohne eine ausdrueckliche Groesse erben sie die
 * Schriftgroesse des Fliesstextes und werden winzig - der Leser soll aber
 * dasselbe Zeichen wiedererkennen, das er auf dem Bildschirm sucht.
 *
 * Der Wert steht in `em` und nicht in `px`: dieselbe Regel gilt im Absatz
 * (.9rem) UND in der Tabelle (.85rem). Ein fester Pixelwert passt immer nur an
 * einer der beiden Stellen und ragt an der anderen aus der Zeile.
 *
 * `vertical-align: -.18em` dazu: eine Glyphe fuellt ihre Zeilenbox anders aus
 * als Buchstaben und saesse sonst sichtbar zu hoch. */
.ze-markdown .ti {
  font-size: 1.3em;
  vertical-align: -.18em;
  line-height: 1;
}

/* Der Haus-Knopf ist ein BEDIENELEMENT, kein Text - deshalb `rem` mit Absicht:
 * er darf mit dem kleineren Hilfetext nicht mitschrumpfen. Der untere Knopf
 * liegt im gerenderten Markdown und bekaeme sonst die 1.3em von oben. */
.ze-hilfe-home .ti,
/* ==========================================================================
   Diagramme in der Hilfe (Pikchr)
   ==========================================================================
   Die Farben setzt das Modul js/core/pikchr.js: es uebertraegt Pikchrs
   `style`-Attribute per CSSOM (die CSP verwirft ihre Anwendung im Markup) und
   ersetzt dabei Schwarz durch `currentColor`, damit das Bild dem Thema folgt.

   Die drei Formregeln hier sind der RUECKFALL fuer den Fall, dass auch die
   CSSOM-Zuweisung eines Tages blockiert wird. Sie tragen bewusst KEIN
   `!important`: eine Inline-Angabe gewinnt gegen sie, ein fehlendes Attribut
   nicht. Sie wirken also genau dann, wenn die Uebertragung nicht ankam - und
   verhindern die SVG-Vorgabe (`fill` schwarz, kein `stroke`), aus der sonst
   schwarze Klumpen statt Kaesten wuerden. */
.ze-markdown .pikchr-rendered {
  margin: 1.2rem 0;
}

.ze-markdown .pikchr-rendered svg {
  max-width: 70%;
  height: auto;
}

.ze-markdown .pikchr-rendered svg path { fill: none; stroke: currentColor; }
.ze-markdown .pikchr-rendered svg polygon { fill: currentColor; }
.ze-markdown .pikchr-rendered svg text { fill: currentColor; }

/* Ein Diagramm, das sich nicht uebersetzen laesst, faellt LOKAL aus - die
   Seite bleibt lesbar, und die Meldung steht dort, wo das Bild waere. */
.ze-markdown .pikchr-fehler {
  margin: 1.2rem 0;
  padding: .5rem .75rem;
  border-left: 3px solid var(--tblr-danger, #d63939);
  font-size: .85rem;
  color: var(--tblr-secondary, #667382);
}

.ze-markdown .ze-hilfe-home .ti {
  font-size: 1.6rem;
  vertical-align: middle;
}

/* Ein Anker springt die Ueberschrift an - und die landete GENAU unter der
 * klebenden Kopfzeile (gemessen: Oberkante bei 0, Kopfzeile 56 px hoch), also
 * unsichtbar. Der Leser sieht dann mitten in den Text und sucht die
 * Ueberschrift, die er gerade angeklickt hat. 4.5rem = die 56 px plus Luft. */
.ze-markdown :is(h1, h2, h3, h4) { scroll-margin-top: 4.5rem; }

.ze-markdown h1 { font-size: 1.5rem; margin-bottom: 1rem; }
.ze-markdown h2 { font-size: 1.25rem; margin-top: 1.75rem; margin-bottom: .5rem; }
.ze-markdown h3 { font-size: 1.1rem; margin-top: 1.25rem; margin-bottom: .5rem; }
.ze-markdown h4 { font-size: 1rem; font-weight: 600; margin-top: 1rem; margin-bottom: .35rem; }
/* Tabellen im Hilfetext. `marked` erzeugt ein NACKTES <table> ohne die
 * Tabler-Klassen - ohne diese Regeln stehen die Spalten ohne Abstand
 * aneinander ("SymbolElement") und ohne Linien, und eine Tabelle mit drei
 * Spalten liest sich als Fliesstext. Die Klasse laesst sich in Markdown nicht
 * setzen, also muss das Stylesheet es tun. */
.ze-markdown table {
  width: 100%;
  margin-bottom: 1rem;
  border-collapse: collapse;
}

.ze-markdown th,
.ze-markdown td {
  border: 1px solid var(--tblr-border-color);
  padding: .35rem .6rem;
  vertical-align: top;
  text-align: left;
}

.ze-markdown thead th {
  background: var(--tblr-bg-surface-secondary);
  white-space: nowrap;
}

/* Die Symbolspalte bleibt schmal und mittig - sie traegt ein Zeichen oder
 * einen Gedankenstrich, keinen Text.
 *
 * NUR ueber die Zellen mit Symbol, NICHT ueber `th:first-child`: die Regel
 * stand hier zuerst und quetschte die erste Spalte JEDER Hilfetabelle - auch
 * "Kachel", "Status" oder "Stufe", wo laufender Text drinsteht (gemessen: 79 px
 * fuer "Ø je Tag bzw. Ø je Monat", also mehrfach umgebrochen). Die Spaltenbreite
 * ergibt sich aus der breitesten Zelle; steht dort ein Symbol, ist das genau ein
 * Zeichen, und die Spalte wird von selbst schmal. */
/* Die Bedingung haengt an der TABELLE, nicht an der einzelnen Zelle. Vorher
 * stand hier `td:has(> .ti)` - das traf nur Zellen MIT Symbol, und die Zeilen
 * ohne (die mit einem Gedankenstrich) blieben linksbuendig stehen. In derselben
 * Spalte sassen dann manche Zeichen mittig und manche links.
 *
 * `table:has(.ti)` heisst: in dieser Tabelle kommen Symbole vor, also ist die
 * erste Spalte eine Symbolspalte - und dann gilt die Ausrichtung fuer ALLE
 * ihre Zellen, auch fuer den Strich. */
.ze-markdown table:has(.ti) td:first-child,
.ze-markdown .ze-symboltabelle td:first-child {
  width: 1%;
  text-align: center;
  white-space: nowrap;
}

/* Die Ueberschrift der Symbolspalte mittig dazu - sonst steht "Symbol" links
 * und alles darunter mittig, und die schmale Spalte wirkt verrutscht. */
.ze-markdown table:has(.ti) thead th:first-child,
.ze-markdown .ze-symboltabelle thead th:first-child { text-align: center; }
.ze-markdown blockquote {
  border-inline-start: 3px solid var(--tblr-border-color);
  padding-inline-start: .75rem;
  color: var(--tblr-secondary);
}

/* Lizenztabellen: gleiche Spaltenbreiten in beiden Tabellen. Ohne
 * `table-layout: fixed` richtet der Browser jede Tabelle nach ihrem eigenen
 * Inhalt aus, und die zwei stehen sichtbar versetzt untereinander. */
.lic-table { table-layout: fixed; }
.lic-table col.lic-c1 { width: 40%; }
.lic-table col.lic-c2 { width: 10%; }
.lic-table col.lic-c3 { width: 25%; }
.lic-table col.lic-c4 { width: 25%; }
.lic-table th, .lic-table td { overflow-wrap: anywhere; }

/* ------------------------------------------------------------ Formulare ---
 * Ein gesperrtes Feld muss man SEHEN. Weder Bootstrap noch Tabler faerben
 * `readonly` ein (gemessen 2026-08-02: readonly und normal beide #ffffff) -
 * nur `disabled` bekommt einen Hintergrund. Ohne diese Regel unterscheidet
 * sich ein Feld, in das man schreiben kann, in nichts von einem, in das man
 * nicht schreiben kann; man merkt es erst beim Tippen.
 *
 * Warum readonly und nicht disabled: der Inhalt bleibt markierbar und
 * kopierbar, er ist per Tastatur erreichbar und der Screenreader liest ihn.
 * Ein disabled-Feld ist aus der Tabreihenfolge heraus und damit fuer die
 * Bedienung ohne Maus unsichtbar.
 *
 * `--tblr-secondary-bg` statt `--tblr-bg-surface-secondary`: das zweite ist in
 * diesem Build mit #f9fafb praktisch weiss und waere kein sichtbarer
 * Unterschied (beide nachgesehen, nicht geraten). */
.form-control[readonly] {
  background-color: var(--tblr-secondary-bg);
  box-shadow: none;
}

/* Ein gesperrtes Feld ist trotzdem TABBAR - `readonly` nimmt es nicht aus der
 * Tabreihenfolge (anders als `disabled`, und genau darum steht oben `readonly`).
 * Bis zum 2026-08-06 galt `box-shadow: none` auch im Fokus und loeschte damit
 * den Fokusring: der Rahmen wurde farbig, der Hof fehlte. Der Ring gehoert hier
 * hin, der Schatten des Ruhezustands nicht. */
.form-control[readonly]:focus {
  box-shadow: 0 0 0 .25rem rgba(var(--tblr-primary-rgb), .25);
}

/* --------------------------------------------------------- Sperr-Spinner ---
 * Das Modul busy-indicator setzt `is-busy` + `aria-busy` am Root (body).
 * Gezeichnet wird der Sperr-Schleier von `loading.css` (`body.is-busy::before`
 * und `::after`) - ebenfalls uebernommener Modulcode, deshalb wird dort nichts
 * geaendert. Was hier steht, sind nur die zwei Anschluesse ans Thema.
 *
 * Bis zum 2026-08-05 stand daneben ein EIGENER Schleier (`.ze-busy` samt einem
 * `#busy`-Kasten in index.html). Beide reagierten auf `is-busy`, also lagen
 * zwei Schleier und zwei Spinner uebereinander - der weisse des Moduls auf
 * z 2000 ueber dem dunklen des Eigenbaus auf z 1080. Der Eigenbau ist raus.
 */

/* Das Modul zeichnet seinen Ring mit `var(--busy-spinner, #6c757d)` und laesst
 * das Token ausdruecklich dem Projekt. Ohne diese Zeile bliebe er auf dem
 * Notfallgrau stehen und waere das einzige Bedienelement der Oberflaeche, das
 * der gewaehlten Akzentfarbe NICHT folgt. */
:root {
  --busy-spinner: var(--tblr-primary);
}

/* Der dunkle Schleier des Moduls ist ein fester Blaugrauton (#182433) und
 * kaeme mit den Grundtoenen Stein, Zink oder Neutral aus der Reihe.
 * `--tblr-backdrop-bg` ist `var(--tblr-gray-800)`, und genau diese Graustufen
 * tauscht das Themenpanel aus - damit folgt der Schleier dem Grundton.
 *
 * Gleiche Spezifitaet wie die Regel im Modul; entschieden wird ueber die
 * Reihenfolge der Stylesheets, und app.css steht in index.html hinter
 * loading.css. Die helle Variante bleibt unangetastet: Weiss passt zu jedem
 * Grundton. */
[data-bs-theme="dark"] body.is-busy::before {
  background: var(--tblr-backdrop-bg, #1f2937); /* = --tblr-gray-800, nachgesehen */
  /* Die Deckkraft steckte im `rgba(24,36,51,.6)` des Moduls. Ein Farb-Token
   * hat keine, und ohne diese Zeile deckt der Schleier die Seite VOLLSTAENDIG
   * ab - im Browser gesehen, nicht ueberlegt. `opacity` am ::before ist hier
   * gefahrlos: der Spinner ist das ::after, ein eigenes Pseudoelement. */
  opacity: .6;
}

/* Solange gesperrt wird, nimmt die Seite keine Klicks mehr an. Ohne das
 * klickt der Benutzer waehrend des Ladens weiter und loest denselben Vorgang
 * mehrfach aus. */
body.is-busy {
  cursor: progress;
}

body.is-busy .page {
  pointer-events: none;
}
