/**
 * sections/einstellungen/einstellungen.css — SettingsShell (Settings-Framework §4).
 *
 * Self-scoped `.einst-*`/`.setx-*` unter `.einst-wrap` bzw. im Settings-Drawer-Body.
 * NUR Layout/Formsprache der Settings-Fläche — die Bausteine kommen aus den globalen
 * SSOTs (`.app-switch`, `.app-drawer-input`, CustomSelect, `.lod-surface`, `.app-cta-btn`,
 * `.lod-info-banner`). Akzent durchgängig Darkblue/Brand — nie der orange Tertiär-Accent.
 * Formsprache (Spec 2026-07-26): Satz-Formulare, Gruppen-Header, Katalog-Zeilen mit
 * Icon-Chip in Art-Farbe, Kennzahlen-Karten, Drawer-Editor (.setx-*). Vier Breakpoints.
 */

/* Links Navigations-KARTE, rechts die Sektions-KARTEN auf dem grauen Hintergrund.
   Bis 2026-07-29 lag dort EINE große weiße Pane und die Sektionen als weiße Karten
   DARIN — weiß auf weiß mit einer Kante dazwischen. Diese Hülle war der Grund,
   warum der leere Platz nicht wegzubekommen war: eine Pane über die volle
   Bildschirmbreite verspricht 1844px Inhalt, und ein Formular hat nun einmal ein
   Lesemaß. Im Browser bei 2248px gemessen standen 676px Weiß INNERHALB der
   Sektionskarte. Wer die Karte deckelt, verschiebt das Loch nur eine Ebene nach
   oben in die Pane; wer die Pane deckelt, nimmt den Tabellen-Sektionen ihre
   Breite (5 von 16 Bereichen mischen Formular- und Tabellen-Sektionen). Also:
   keine Hülle. Die Karte ist die Fläche, und sie ist so breit wie ihr Inhalt. */
/* ── Wurzel der Fläche: hier stehen die Maße ──────────────────────────────────
   Die Tokens hängen an der SECTION-Wurzel und nicht an `.einst-wrap`, weil die
   Toolbar (Suchfeld + Treffer-Panel) ein Geschwister der Inhalts-Pane ist und
   dasselbe Maß braucht. Läge `--einst-karte` weiter unten, könnte `--einst-flaeche`
   es nicht ableiten — und eine zweite, handgepflegte Zahl ist genau das, was hier
   schon zweimal auseinandergelaufen ist. */
.einst-root {
  /* ── EINE BREITE FÜR DIE GANZE FLÄCHE ────────────────────────────────────────
     `--einst-karte` gilt für JEDE Sektionskarte, die Kopfzeile und das Skeleton —
     ohne Ausnahme, egal ob Feldzeilen, Tabelle, Karten-Raster, Rich-Text-Editor
     oder Panel darin liegen. Es gibt keine zweite Zahl.

     WARUM KEINE INHALTS-ABHÄNGIGEN MASSE (zwei Anläufe, beide verworfen):
     Erst bekam jede Karte das Maß ihres eigenen Inhalts (Formular 800 · Editor
     1140 · Tabelle volle Breite), dann eines je Bereich. Pro Karte ist das
     begründbar, in der SPALTE ist es eine Treppe: in „Allgemein" endeten die
     Karten bei 823 / 2130 / 2130 / 2130px, in „Anfragen & SLA" wechselte es
     zwischen Formular und Antwort-Vorlagen hin und her. ZUGEKLAPPT bleiben davon
     nur verschieden lange Köpfe ohne jeden sichtbaren Grund. Kyle 29.07.:
     „EINE BREITE FÜR DIE GESAMTE SETTINGS STRUKTUR."
     Der Preis ist bewusst bezahlt: ein Panel (Rechtevergabe, Artikel-Preise) hat
     hier weniger Platz als über die volle Bildschirmbreite. Einheitlichkeit der
     Fläche wiegt mehr als das Optimum einer einzelnen Sektion.

     1116px = 1082px Zeilenmaß (`--set-mass`, settings-row.css) + 2×16px Innenluft
     + 2px Rahmen. Die Zeile FÜLLT diese Breite, es bleibt also kein Weiß in der
     Karte. Tabellen tragen es ohne Not: derselbe Wochenplan rendert im
     Standort-Drawer auf 590px einwandfrei.

     ── WARUM 1116 UND NICHT 800 (2026-07-29, 2) ────────────────────────────────
     Kyle-Vorgabe: „Den Settings bereich so groß machen wie er jetzt grade +
     Menüleiste links an der Seite ist" — 800 (alte Karte) + 16 (Spalten-Abstand)
     + 300 (Menüleiste) = 1116. Die Menüleiste bleibt LINKS DANEBEN (Muster
     Projektaufnahme: `nav | main`, beide im selben Grid, Nav sticky).

     ★ DIE ZEILE WÄCHST MIT. Das ist keine Nebenwirkung, sondern die Bedingung:
     eine breitere Karte über einem unveränderten Zeilenmaß hätte 340px Weiß INNEN
     — derselbe Fehler, den die 800px behoben haben, nur eine Ebene tiefer.
     Die Beziehung der beiden Zahlen ist deshalb gate-geprüft (siehe dort). */
  --einst-karte: 1116px;
  --einst-nav: 300px;
  /* ── DER DECKEL DER FLÄCHE — ABGELEITET, NICHT GEWÄHLT ───────────────────────
     Bis 2026-07-29 hatte die Fläche KEIN Maximum. Das war kein falscher Wert,
     sondern ein fehlender: jeder andere Tab (Board, Firmen-Tabelle, Dashboards)
     will die volle Breite, `lod-section-panel` ist deshalb ungedeckelt — und die
     Einstellungen haben das geerbt, obwohl ihr Inhalt ein natürliches Lesemaximum
     hat. Folge, im Browser über alle 16 Bereiche gemessen: Nav + Karte sind konstant
     1116px, jeder weitere Pixel Fensterbreite wurde zu Weiß NEBEN der Karte —
     76px bei 1280, 626px bei 1830, 1356px bei 2560 (63% der Inhaltsspalte).
     Unter ~1400px ist davon nichts zu sehen; deshalb haben drei Anläufe an der
     Kartenbreite das Problem nie berührt.

     `calc()` statt einer Zahl, damit es keine zweite Wahrheit gibt: der Deckel IST
     Nav + Spalten-Abstand + Karte. Rest-Weiß in der Inhaltsspalte ist dadurch 0 by
     construction, nicht „klein gehalten" — und wer `--einst-karte` ändert, ändert
     den Deckel automatisch mit. Geprüft wird beides: statisch, dass der Deckel
     abgeleitet bleibt (settings-breiten-vertrag.js), und live, dass kein Weiß
     entsteht (check:settings-live).

     Preis, bewusst bezahlt: die Einstellungen sind der einzige Bereich mit
     Seitenrändern. Vertretbar, weil Konfiguration Lesen und Formular ist und kein
     Arbeitswerkzeug — aber es ist eine sichtbare Ausnahme. */
  /* Spalten-Abstand als EIGENES Token, und die Flaechen-Rechnung liest genau dieses.
     Vorher stand `--space-4` an beiden Stellen: wer den Abstand aendert und die
     Rechnung vergisst, bekommt Rest-Weiss in der Inhaltsspalte — die Drift ist im
     Browser sichtbar, im Quelltext nicht.
     20px statt 16px (Kyle 30.07.: „berührt seine Seitenleiste"): gemessen berührte
     nichts (16px Luecke ueber fuenf Breiten), aber zwei grosse WEISSE Flaechen auf Grau
     brauchen mehr Luft als zwei Elemente innerhalb einer Karte — und genau `--space-4`
     ist der Abstand, den die Karte INNEN verwendet. Gleicher Abstand innen und aussen
     laesst die Trennung verschwinden. */
  --einst-spalten-luecke: var(--space-5);
  --einst-flaeche: calc(var(--einst-nav) + var(--einst-spalten-luecke) + var(--einst-karte));
}
.einst-wrap {
  max-width: none;
  margin: 0;
  padding: 0 0 var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  min-height: 100%;
}

/* ── Such-Treffer-Panel (unter der Section-Toolbar, links verankert) ───────────
   Anker ist die ZONE, nicht die Toolbar: die Toolbar trägt jetzt (konventionsgemäß)
   `lod-section-toolbar app-page-toolbar` auf einem Element, und PageToolbar schreibt
   deren `innerHTML` — ein Kind darin würde beim Aufbau überschrieben. */
.einst-toolbarzone { position: relative; flex-shrink: 0; }
/* Lade-Skeleton in der Form der Fläche (Nav + Pane), damit beim Erscheinen der
   Daten nichts springt. Vorher: 3s leere Fläche (gemessen). */
.einst-sk { display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: var(--space-4); align-items: start; }
.einst-sk-nav { padding: var(--space-4); }
/* Bahnen und Deckel wie die echte Karte (240 / 412, Deckel `--einst-karte`) —
   sonst springt beim Erscheinen der Daten genau das, was das Skeleton verhindern
   soll: eine bildschirmbreite Platzhalter-Fläche, die auf 740px zusammenfällt. */
.einst-sk-pane { padding: var(--space-4); min-height: 60vh; max-width: var(--einst-karte); }
.einst-sk-kopf { padding-bottom: var(--space-4); border-bottom: 1px solid var(--lod-gray-100); margin-bottom: var(--space-3); }
.einst-sk-row { display: grid; grid-template-columns: 240px minmax(0, 412px); gap: var(--space-3); padding: var(--space-3) 0; }
/* 999, nicht 1199: das ECHTE Layout kollabiert bei ≤999 auf eine Spalte (unten).
   Mit 1199 zeigte das Skeleton im Band 1000–1199 eine Spalte, die Daten kamen
   zweispaltig an — genau der Sprung, den das Skeleton verhindern soll. */
@media (max-width: 999px) {
  .einst-sk { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 599px) {
  .einst-sk-row { grid-template-columns: minmax(0, 1fr); }
}
.einst-search-panel {
  /* Folgt der ZENTRIERTEN Toolbar, nicht dem Fensterrand: `max()` klammert von
     selbst — sobald die Toolbar breiter ist als der Deckel, wird der calc-Term
     kleiner als die Innenluft und die Innenluft gewinnt. Ohne das öffnete das
     Treffer-Panel am linken Bildschirmrand, während das Suchfeld mittig steht. */
  position: absolute; top: 100%; z-index: 40;
  left: max(var(--space-4), calc((100% - var(--einst-flaeche)) / 2 + var(--space-4)));
  min-width: min(380px, 88vw); max-width: min(520px, 92vw); max-height: 360px; overflow-y: auto;
  background: var(--color-surface); border: 1px solid var(--lod-border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-8);
  padding: var(--space-1);
}
.einst-search-panel[hidden] { display: none; }
.einst-search-hit {
  display: flex; flex-direction: column; gap: 2px; width: 100%; text-align: left;
  padding: var(--space-2) var(--space-2-5); border: none; background: none; cursor: pointer;
  border-radius: var(--radius-sm);
}
.einst-search-hit:hover { background: var(--lod-gray-50); }
.einst-search-pfad { font-size: var(--fs-badge, 11px); color: var(--lod-gray-500); }
.einst-search-label { font-size: var(--fs-body, 14px); font-weight: var(--fw-medium); color: var(--color-text); }
.einst-search-leer { padding: var(--space-3); font-size: var(--fs-meta, 12px); color: var(--color-text-muted); }

.einst-banner-box { display: flex; align-items: flex-start; gap: var(--space-2); margin-top: 0; }
.einst-banner-box .ui-ico { flex-shrink: 0; margin-top: 1px; }

/* ── Zwei-Spalten-IA ─────────────────────────────────────────────────────────── */
.einst-layout {
  display: grid;
  grid-template-columns: var(--einst-nav) minmax(0, 1fr);
  gap: var(--einst-spalten-luecke);
  align-items: start;
  flex: 1;
  /* Zentriert im Deckel — nicht linksbündig. Linksbündig steht der ganze Block im
     linken Drittel eines breiten Fensters und der Rest ist ein graues Feld: das
     liest sich als kaputtes Layout, nicht als Rand. */
  width: 100%; max-width: var(--einst-flaeche); margin-inline: auto;
}
/* Die Toolbar bleibt die STANDARD-Toolbar: volle Breite, linksbündig, Trennlinie über
   den ganzen Bereich — wie in jedem anderen Tab. Ihren Inhalt auf `--einst-flaeche` zu
   deckeln wurde versucht und verworfen: `PageToolbar` schreibt den Host-`innerHTML` und
   baut darin eigene Cluster, ein Deckel auf `> *` traf damit nicht das Suchfeld (im
   Browser gemessen: Feld bei x=107, Inhaltsspalte bei x=701). An den Interna eines
   SSOT-Moduls vorbeizustylen wäre der falsche Hebel — die gemeinsame linke Kante von
   Suchfeld und Inhalt gehört an das LAYOUT, nicht an die Toolbar. */

/* Navigations-KARTE (weiße Fläche wie der Projektaufnahme-Stepper). */
.einst-nav {
  display: flex; flex-direction: column; gap: var(--space-1);
  /* `top: 0`, NICHT --space-2: der Scroll-Container beginnt oben bündig, die Karte ist
     also schon im Ruhezustand „geklebt" — ein Sticky-Offset schob sie dauerhaft 8px
     unter die Oberkante der Inhalts-Pane (im Browser gemessen: Nav 170px, Pane 162px).
     Sichtbar war das als schiefe Kante zwischen den beiden Spalten. */
  position: sticky; top: 0;
  padding: var(--space-4) var(--space-3) var(--space-5);
}
/* Raster-Navigation (Tablet/Mobile, ≤999): Gruppen-Kapitälchen sind für die
   vertikale Liste gemacht — im Raster stehen sie mitten zwischen den Einträgen
   (und „MODULE" trug dort sogar eine Trennlinie über sich).
   ★ 999, nicht 1199: die Nav ist bis 1000px die VERTIKALE Spalte (das Layout
   kollabiert erst bei ≤999). Mit 1199 verlor die vertikale Liste im Band
   1000–1199 grundlos ihre Kapitel — 19 Bereiche als flache Liste, genau auf
   Notebook-Breite, während die Begründung dieser Regel nur fürs Raster trägt. */
@media (max-width: 999px) {
  .einst-nav-group { display: none; }
}
.einst-nav-group {
  font-size: var(--fs-badge, 11px); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps, .08em); text-transform: uppercase;
  color: var(--lod-gray-500);
  padding: var(--space-2) var(--space-4) var(--space-1);
}
.einst-nav-group:not(:first-child) { margin-top: var(--space-4); border-top: 1px solid var(--lod-gray-100); padding-top: var(--space-4); }
.einst-nav-item { min-height: 40px; }
.einst-nav-item {
  display: flex; align-items: center; gap: var(--space-3);
  width: 100%; text-align: left; cursor: pointer;
  padding: var(--space-2-5) var(--space-4);
  background: transparent;
  border: none; border-left: 3px solid transparent;
  border-radius: var(--radius-md);
  font-size: var(--fs-body, 14px); font-weight: var(--fw-medium);
  color: var(--lod-gray-700);
  transition: background var(--duration-fast) var(--ease-soft), color var(--duration-fast) var(--ease-soft);
}
.einst-nav-ico { display: inline-flex; width: 22px; height: 22px; align-items: center; justify-content: center; flex-shrink: 0; }
.einst-nav-ico img { width: 20px; height: 20px; opacity: .7; }
.einst-nav-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.einst-nav-dirty {
  flex-shrink: 0; width: 6px; height: 6px; border-radius: var(--radius-circular);
  background: var(--brand-default);
}
/* „Hier fehlt noch eine Pflichtangabe" — bewusst eine ZAHL und kein zweiter Punkt:
   neben dem 6px-Punkt daneben waere ein zweiter Punkt nicht unterscheidbar, und beide
   Marken verloeren ihre Aussage. Ton ist WARNUNG, nicht Fehler: ein frisch
   bereitgestellter Mandant ist kein Ausfall, er ist neu (dieselbe Abwaegung wie beim
   `.set-row-fehlt` an der Zeile, das bewusst ohne Kasten und ohne Symbol auskommt). */
.einst-nav-fehlt {
  flex-shrink: 0;
  min-width: 16px; height: 16px; padding: 0 var(--space-1);
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-circular);
  background: var(--status-warning-bg); color: var(--status-warning-fg);
  font-size: var(--fs-caption); font-weight: 600; line-height: 1;
}
/* Auf dem gefuellten aktiven Eintrag traegt der Warnton zu wenig Kontrast — dort
   dieselbe Umkehrung wie beim Punkt daneben. */
.einst-nav-item.is-active .einst-nav-fehlt { background: #fff; color: var(--lod-darkblue); }
.einst-nav-item:hover { background: var(--lod-gray-50); color: var(--lod-darkblue); }
.einst-nav-item:hover .einst-nav-ico img { opacity: .9; }
.einst-nav-item:focus-visible { outline: none; box-shadow: var(--lod-shadow-focus); }
/* Aktiver Bereich = Darkblue gefüllt mit weißer Schrift (App-Konvention, wie der
   aktive ViewSwitcher-Tab) — kein blasser Tint. */
.einst-nav-item.is-active {
  background: var(--lod-darkblue);
  border-left-color: var(--lod-darkblue);
  color: #fff;
  font-weight: var(--fw-semibold);
  box-shadow: 0 1px 2px rgba(15, 46, 72, 0.18);
}
.einst-nav-item.is-active:hover { background: var(--lod-darkblue); color: #fff; filter: brightness(1.1); }
.einst-nav-item.is-active .einst-nav-ico img { opacity: 1; filter: brightness(0) invert(1); }
.einst-nav-item.is-active .einst-nav-dirty { background: #fff; }

.einst-content { min-width: 0; display: flex; flex-direction: column; gap: var(--space-4); }

/* ── Breadcrumbs + Intro + Sub-Tabs ──────────────────────────────────────────── */
.einst-crumbs { display: flex; align-items: center; gap: var(--space-1-5); font-size: var(--fs-meta, 12px); color: var(--lod-gray-500); }
.einst-crumbs a { color: var(--lod-gray-500); text-decoration: none; }
.einst-crumbs a:hover { color: var(--lod-darkblue); text-decoration: underline; }
.einst-crumb-sep { color: var(--lod-gray-300); }
.einst-crumb-cur { color: var(--color-text); font-weight: var(--fw-medium); }

/* OBEN ausgerichtet, nicht mittig. Mittig hing das Bereichs-Symbol an der Mitte des
   TEXTBLOCKS: sobald der Untertitel zweizeilig wurde, rutschte es nach unten und
   sprang beim Wechsel auf einen Bereich mit kürzerem Untertitel wieder hoch (Kyle
   29.07.: „springt hier einfach das Icon hin und her"). Oben ausgerichtet steht es
   auf der Höhe der Überschrift — unabhängig davon, wie viele Zeilen darunter folgen.
   Das kleine Offset bringt es auf die Mittellinie der ERSTEN Zeile. */
/* ── Der Seitenkopf ist eine KARTE, keine Beschriftung des Hintergrunds ────────
   Titel, Untertitel und „Änderungsverlauf" standen bis 2026-07-29 (5. Meldung!)
   direkt auf dem grauen Seitengrund — ohne Fläche, ohne Kante: „das steht einfach
   auf dem grauen Hintergrund". Vier Reparatur-Anläufe davor haben jeweils die
   SEKTIONS-Köpfe angefasst und diesen Kopf nie. Er trägt jetzt dieselbe Fläche wie
   jede Sektionskarte (Surface-Primitive-Tokens) und dieselbe Breite (`--einst-karte`,
   Regel weiter unten) — die Fläche beginnt damit oben mit einer Karte, nicht mit
   loser Schrift. */
.einst-intro {
  display: flex; align-items: flex-start; gap: var(--space-3);
  background: var(--surface-bg); border: var(--surface-border);
  border-radius: var(--surface-radius); box-shadow: var(--surface-shadow);
  padding: var(--space-4);
}
.einst-intro > .einst-card-icon { margin-top: 1px; }
.einst-intro .einst-verlauf-btn { margin-top: 2px; }
.einst-card-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; flex-shrink: 0;
  border-radius: var(--radius-md);
  background: var(--lod-darkblue-50);
}
.einst-card-icon img { width: 22px; height: 22px; }
.einst-card-titles { min-width: 0; }
.einst-card-title { margin: 0; font-size: var(--fs-section, 16px); font-weight: var(--fw-semibold); color: var(--color-text); line-height: 1.25; }
/* Untertitel auf DERSELBEN Stufe wie die Erklärung (13/400): zwei Größen für
   „erklärender Text" waren eine Stufe zu viel. */
.einst-card-thema { margin: 2px 0 0; font-size: var(--fs-body, 14px); font-weight: var(--fw-regular, 400); color: var(--color-text-muted); }

/* ── Die Reiter-Zeile einer Settings-Seite ──────────────────────────────────
   Sie gehoert zur KOPF-KARTE, nicht zum Inhalt: „Erscheinungsbild" ist eine Sicht auf
   dieselbe Seite, kein eigener Gegenstand. Deshalb sitzt sie auf derselben Flaeche und
   schliesst oben an die Karte an (dort kein Radius, kein doppelter Rahmen) — statt als
   dritte Insel zwischen zwei Karten auf dem grauen Grund zu schweben.

   ★ Gemeldet 2026-07-30 („Toolbar / Bereichswechsler sind einfach auf dem grauen
   Hintergrund"). Die Zeile trug nur `display:flex` — als es die Reiter noch nicht gab,
   war das folgenlos; mit ihnen fehlte der Flaeche jede Zugehoerigkeit. Ein Reiter, der
   auf nichts sitzt, sieht aus wie ein vergessenes Element. */
.einst-subtabs {
  display: flex; align-items: center;
  background: var(--surface-bg); border: var(--surface-border); border-top: 0;
  border-radius: 0 0 var(--surface-radius) var(--surface-radius);
  box-shadow: var(--surface-shadow);
  padding: var(--space-2) var(--space-4);
  /* Der negative Rand zieht sie an die Karte darueber; deren Radius unten faellt weg,
     sonst blitzt der graue Grund in der Fuge durch. */
  /* Nimmt den Stapel-Abstand des Pane EXAKT zurueck — dasselbe Token, keine zweite Zahl.
     Vorher `--space-3` gegen einen `--space-4`-Stapel: 4px Fuge (im Browser gemessen). */
  margin-top: calc(-1 * var(--einst-stapel));
  max-width: var(--einst-karte);
  overflow-x: auto;
}
/* Die Kopf-Karte gibt ihren unteren Radius ab, wenn Reiter folgen — sonst waeren es
   zwei gerundete Kanten uebereinander mit einer sichtbaren Naht. */
.einst-intro:has(+ .einst-subtabs) { border-radius: var(--surface-radius) var(--surface-radius) 0 0; }

/* ── SUB-REITER: Scrollen ist hier RICHTIG, der 10px-Anschnitt war es nicht ────
   Anders als die Bereichs-Navigation darüber ist das ein SEGMENTED CONTROL
   (`ViewSwitcher`, ein 36px-Track mit gemeinsamer Fläche). Umbrechen zerstört seine
   Gestalt — zwei Zeilen mit geteiltem Track lesen sich als kaputt. Er darf also
   scrollen, und die Andeutung ist die angeschnittene Pille (Header-Vertrag: ein Fade
   über Pills löscht genau diesen Hinweis).

   ★ Gemessen 2026-08-01 war der Anschnitt aber im TABLET-Band unbrauchbar: 680px
   Inhalt in 670px sichtbarer Breite — **10px verdeckt**. Das ist keine erkennbare
   Scroll-Kante, das liest sich als Rendering-Fehler (genau das zeigt Kyles
   Screenshot bei ~760px: die letzte Pille „Themen" hängt angeschnitten am Rand).
   Bei 600px sind es 170px und der Anschnitt trägt wieder.

   Die Innenluft der Mobil-Regel greift deshalb schon ab 999px: 16px je Seite weniger
   lassen die Leiste im 760px-Band vollständig hineinpassen (680 → 664 < 670), und
   darunter scrollt sie mit einem Anschnitt, den man als solchen erkennt. Das ist
   bewusst KEIN fester Deckel auf die Anzahl der Reiter — bei sieben Reitern scrollt
   sie wieder, und dann ist es richtig so. */
@media (max-width: 999px) {
  .einst-subtabs { padding: var(--space-2); }
}

/* ── Die Pane ist nur noch Anordnung, keine Fläche ──────────────────────────
   Kein Hintergrund, kein Rahmen, keine Polsterung: die Sektionskarten liegen
   direkt auf dem grauen App-Hintergrund (Klassen `lod-surface lod-surface--raised`
   stehen deshalb an der Sektion, nicht mehr hier). */
.einst-pane {
  display: flex; flex-direction: column;
  /* Eigenes Token, weil der negative Rand der Sub-Reiter GENAU diesen Wert zuruecknehmen
     muss (siehe `.einst-subtabs`). Als zwei Literale liefen sie auseinander — und genau
     das war der Fall: Stapel 16px gegen Rueckzug 12px liess 4px grauen Grund in der Fuge
     zwischen Kopf-Karte und Reitern stehen, obwohl beide EINE Flaeche sein sollen. */
  --einst-stapel: var(--space-4);
  gap: var(--einst-stapel);
  min-height: 70vh;
}
/* Kopfzeile des Bereichs: KEINE Trennlinie mehr — sie trennte innerhalb der
   weißen Pane, und der graue Zwischenraum tut das jetzt selbst. Dieselbe Breite wie
   jede Karte, damit der „Änderungsverlauf"-Knopf auf der Kante sitzt, die auch alles
   darunter hat (vorher stand er rechtsbündig am Bildschirmrand, bis zu 900px neben
   allem Sichtbaren). */
.einst-pane .einst-intro { max-width: var(--einst-karte); }
.einst-cards { display: flex; flex-direction: column; gap: var(--space-3); }
.einst-card-sec-title { margin: 0 0 var(--space-2); font-size: var(--fs-section, 16px); font-weight: var(--fw-semibold); color: var(--color-text); }
.einst-fields { display: flex; flex-direction: column; }

/* ── Setting-Zeile: NICHT hier ──────────────────────────────────────────────
   Zeile, Gruppen-Überschrift und die Erklärung am ⓘ gehören dem SSOT-Modul
   `LoD.SettingsRow` (web/js/components/settings/settings-row.js +
   web/styles/components/settings/settings-row.css). Vorher stand das Zeilen-Layout
   hier — und ein zweites Mal für den Drawer (`.setx-row`) weiter unten. Beide
   Kopien sind gewachsen und auseinandergelaufen (zwei Definitionen von
   `.einst-row--stapel`, zwei Hilfe-Optiken, zwei Control-Kanten). Wer die Zeile
   ändern will, ändert das Modul; hier stehen nur noch Dinge, die es NICHT kennt:
   der „Gespeichert"-Haken, die Feld-Fehlerzeile und die Flächen-Hülle. */
.einst-saved { display: inline-flex; }
.einst-saved .ui-ico img { width: 16px; height: 16px; }
/* Feld-Fehler unter der Zeile (Paar-Validierung Erinnerung/Eskalation). Läuft über
   den `unten`-Slot der Zeile und darf deshalb beide Bahnen überspannen. */
.einst-row-error {
  grid-column: 1 / -1; font-size: var(--fs-meta, 12px);
  color: var(--status-danger-fg); padding-top: var(--space-1);
}
/* Mehrzeiler brauchen Höhe — sonst öffnet ein OOF-Fließtext in drei Zeilen. */
.app-scope .set-row--stapel .einst-textarea { min-height: 132px; }

/* ── Feldtyp `farbe`: Tupfer + Hex-Feld ─────────────────────────────────────
   Der Tupfer ist ein HELFER, nicht der Wert (ein `<input type="color">` kann
   „nicht gesetzt" nicht darstellen und würde still Schwarz behaupten). Er steht
   deshalb VOR dem Feld und nimmt keine eigene Bahn ein — die rechte Feldkante
   bleibt die der übrigen Zeilen (Breiten-Vertrag). */
/* Die Farbe ist EIN Feld aus zwei Teilen und nimmt deshalb die Feld-Bahn ihrer Karte
   ein (`--set-feld`, settings-row.css § Kurzfeld-Stufen) — vorher stand der Wrapper
   ausserhalb der Bahn und das Hexfeld behielt sein eigenes Maass, egal was die Karte
   sagte. `max-width: 100%` haelt ihn im Drawer, wo die Bahn schmaler ist als die Stufe. */
.einst-farbe {
  display: flex; align-items: center; gap: var(--space-2); min-width: 0;
  grid-column: 1; width: var(--set-feld, 100%); max-width: 100%;
}
.einst-farbe-tupfer {
  flex: 0 0 auto; width: 32px; height: 32px; padding: 0;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: none; cursor: pointer;
}
.einst-farbe-tupfer:disabled { cursor: default; opacity: .6; }
/* Chromium/WebKit malen den Farbklecks in einen eigenen Kasten mit Innenluft —
   ohne diese zwei Regeln bleibt ein weißer Rand und der Tupfer sieht kaputt aus. */
.einst-farbe-tupfer::-webkit-color-swatch-wrapper { padding: 2px; }
.einst-farbe-tupfer::-webkit-color-swatch { border: none; border-radius: 3px; }
/* Hex ist ein technischer Wert: gleiche Zeichenbreite, damit die Spalte nicht
   zappelt, während getippt wird. Die Bahn ist schmal — sieben Zeichen brauchen
   keine 240px, aber der Mindestwert des Zeilen-Vertrags bleibt gewahrt. */
.einst-farbe-hex {
  flex: 1 1 auto; min-width: 0; max-width: 132px;
  font-family: var(--font-mono, ui-monospace, monospace);
}

/* ── Feldtyp `bild`: Vorschau + zwei Knöpfe ─────────────────────────────────
   Die Vorschau steht LINKS und in fester Höhe: ein Logo kommt in jedem
   Seitenverhältnis, und ohne Deckel schiebt ein hohes Bild die ganze Zeile
   auseinander. Karo-Grund, weil ein transparentes PNG sonst auf Weiß unsichtbar
   ist und man nicht sieht, ob der Freistellungs-Rand stimmt. */
.einst-bild { display: flex; align-items: center; gap: var(--space-2); min-width: 0; flex-wrap: wrap; }
.einst-bild-vorschau {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
  /* 200×72 statt 88×40 (2026-07-30): das Logo geht auf JEDES Angebot, in jede
     Mail-Fußzeile und auf jeden Vertrag — in 88px war nicht zu erkennen, ob es das
     richtige ist, geschweige denn ob der Freistellungs-Rand stimmt. Die Höhe bleibt
     gedeckelt (ein hohes Bild würde sonst die Zeile auseinanderschieben), und weil die
     Marke-Karte jetzt kurze Feld-Bahnen hat, kostet die Breite hier nichts. */
  width: 200px; height: 72px; padding: var(--space-1-5);
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background-color: var(--color-surface);
  background-image:
    linear-gradient(45deg, var(--lod-gray-100) 25%, transparent 25%, transparent 75%, var(--lod-gray-100) 75%),
    linear-gradient(45deg, var(--lod-gray-100) 25%, transparent 25%, transparent 75%, var(--lod-gray-100) 75%);
  background-size: 10px 10px;
  background-position: 0 0, 5px 5px;
}
.einst-bild-vorschau img { max-width: 100%; max-height: 100%; object-fit: contain; }

/* ── Gesperrte Zeile: der GRUND steht da, nicht nur ein graues Feld ──────────
   Ein `title` am gesperrten Control wäre stumm (`pointer-events` bei disabled) —
   deshalb eine echte Zeile im `unten`-Slot, wie der Feld-Fehler darüber. */
.einst-row-gesperrt {
  grid-column: 1 / -1; display: flex; align-items: center; gap: var(--space-1);
  font-size: var(--fs-meta, 12px); color: var(--color-text-muted);
  padding-top: var(--space-1);
}
.einst-row-gesperrt .ui-ico img { width: 14px; height: 14px; opacity: .7; }

/* ── Rich-Text OHNE Schreibrecht: Lese-Ansicht statt Editor ──────────────────
   Kein montierter Editor (er lädt zum Tippen ein und verwirft die Arbeit still),
   sondern der gerenderte Inhalt in einem ruhigen Rahmen. Höhe wächst mit dem
   Inhalt, deckelt aber — eine 4500-Zeichen-Signatur soll die Seite nicht sprengen. */
.einst-html-lesen {
  max-height: 320px; overflow-y: auto;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--lod-gray-100); border-radius: var(--radius-md);
  background: var(--lod-gray-50, #f6f7f9);
  font-size: var(--fs-body, 14px); color: var(--color-text);
}
.einst-html-lesen.is-leer { color: var(--color-text-muted); font-style: italic; }
.einst-html-lesen img { max-width: 100%; height: auto; }

/* ── Änderungsverlauf (Nachweis-Drawer) ─────────────────────────────────────
   Ein Block je Ereignis (Zeitpunkt + Person), darin eine Zeile je geändertem
   Schlüssel mit Vorher → Nachher. Kein Grid: die Wertlängen sind sehr
   unterschiedlich (Schalter „an" neben einer gekürzten Signatur), starre Spalten
   hätten überall Löcher oder Abschnitte. */
.einst-verlauf { display: flex; flex-direction: column; gap: var(--space-3); }
.einst-verlauf-block { padding: var(--space-3); border-radius: var(--radius-md); }
.einst-verlauf-kopf {
  display: flex; align-items: baseline; gap: var(--space-2);
  padding-bottom: var(--space-2); margin-bottom: var(--space-2);
  border-bottom: 1px solid var(--lod-gray-100);
}
.einst-verlauf-wann { font-size: var(--fs-meta, 12px); color: var(--color-text-muted); }
.einst-verlauf-wer { font-size: var(--fs-body, 14px); font-weight: var(--fw-semibold); color: var(--color-text); }
/* Betroffene Person/Rolle (nur Rechte-Protokoll) — Meta-Ton, damit der Handelnde die Zeile anführt. */
.einst-verlauf-betrifft { font-size: var(--fs-meta, 12px); color: var(--color-text-muted); }
.einst-verlauf-liste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.einst-verlauf-zeile {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-1) var(--space-2);
  font-size: var(--fs-body, 14px);
}
.einst-verlauf-zeile .ui-ico img { width: 14px; height: 14px; opacity: .55; }
.einst-verlauf-feld { flex: 1 1 100%; font-weight: var(--fw-medium, 500); color: var(--color-text); }
.einst-verlauf-wert {
  max-width: 100%; overflow-wrap: anywhere;
  padding: 2px var(--space-1); border-radius: var(--radius-sm);
  background: var(--lod-gray-50, #f6f7f9); color: var(--color-text-muted);
}
.einst-verlauf-nach { color: var(--color-text); }
/* Kritische Schlüssel (Außenwirkung, Genehmigung) tragen im Verlauf eine Kante —
   beim Durchsehen soll auffallen, WELCHE Änderung Gewicht hatte. */
.einst-verlauf-zeile.is-kritisch .einst-verlauf-feld { border-left: 2px solid var(--status-warning-fg); padding-left: var(--space-2); }

/* Katalog-Detail: WELCHE Zeile, WELCHES Feld. Eigene Bahn unter der Wert-Zeile
   (`flex: 1 1 100%` in der umgebenden `flex-wrap`-Zeile), damit „2 Einträge → 2 Einträge"
   nicht mehr die ganze Auskunft ist. Bewusst leiser als die Wertfelder — es ist die
   Begründung der Zeile, nicht ihr Kopf. */
.einst-verlauf-detail { flex: 1 1 100%; display: flex; flex-direction: column; gap: 2px; margin-top: var(--space-1); }
.einst-verlauf-detail-zeile {
  font-size: var(--fs-meta, 12px); color: var(--color-text-muted);
  overflow-wrap: anywhere; padding-left: var(--space-2);
  border-left: 2px solid var(--lod-gray-200, #e5e7eb);
}
.einst-verlauf-detail-art { font-weight: var(--fw-semibold); }
.einst-verlauf-detail-namen { color: var(--color-text); }
/* Die Feldnamen sind die eigentliche Auskunft und stehen abgesetzt hinter dem Zeilennamen. */
.einst-verlauf-detail-felder { margin-left: var(--space-1); font-family: var(--font-mono, ui-monospace, monospace); }
/* Token-Namen aus tokens.css, nicht erfunden: `--status-ok-fg`/`--status-err-fg` gibt es
   nicht — der erste Entwurf hatte sie, und `check:css-tokens` hat beide als neues
   Fremd-Vokabular gemeldet. Die Familie heisst `success`/`danger` (im Bestand 63× bzw. 65×). */
.einst-verlauf-detail-zeile.is-neu { border-left-color: var(--status-success-fg); }
.einst-verlauf-detail-zeile.is-weg { border-left-color: var(--status-danger-fg); }
.einst-verlauf-detail-zeile.is-mehr { border-left-color: transparent; font-style: italic; }
/* Verlauf-Knopf im Intro: rechts, außerhalb der Titel-Spalte. */
.einst-intro .einst-verlauf-btn { margin-left: auto; flex-shrink: 0; }

/* Tablet/Mobile: der Knopf verliert seine Beschriftung nicht (er ist die einzige
   Tür zum Nachweis), rutscht aber unter den Titel, sobald die Zeile zu eng wird. */
@media (max-width: 999px) {
  .einst-intro { flex-wrap: wrap; }
  .einst-intro .einst-verlauf-btn { margin-left: 52px; }
}
@media (max-width: 599px) {
  .einst-intro .einst-verlauf-btn { margin-left: 0; }
  .einst-verlauf-block { padding: var(--space-2); }
}

/* ── Katalog: Zeilen (Abwesenheitsarten) ─────────────────────────────────────── */
.einst-liste { display: flex; flex-direction: column; gap: var(--space-2); }
.einst-liste-actions { flex-shrink: 0; }
.einst-liste-loading, .einst-liste-empty { font-size: var(--fs-meta, 12px); color: var(--color-text-muted); padding: var(--space-2) 0; }
.einst-liste-rows { display: flex; flex-direction: column; }

/* ── MATRIX: Kreuztabelle über bestehende Feld-Schlüssel ──────────────────────
   Die zugesagten Reaktionszeiten sind eine 3×2-Tabelle und standen als zwei Sektionen
   mit je drei Formularzeilen da. Bahnen: Zeilen-Beschriftung fest (wie `--set-label`,
   damit sie mit den Formularzeilen der Nachbarsektionen fluchtet), danach eine gleich
   breite Spur je Spalte. `--einst-matrix-cols` setzt der Renderer aus der Spaltenzahl —
   eine dritte Spalte braucht damit keine CSS-Änderung. */
.einst-matrix { display: flex; flex-direction: column; padding: var(--space-1) 0 var(--space-2); }
.einst-matrix-zeile {
  display: grid;
  /* Erste Spur = ⓘ-Bahn, exakt wie in jeder Formularzeile (`--set-info`). Die
     Label-Spur schrumpft um Bahn + Gap, damit die ZELLEN an derselben x-Position
     bleiben wie vorher — und die Zeilen-Labels an derselben wie die der set-rows. */
  grid-template-columns:
    var(--set-info, 20px)
    minmax(0, calc(var(--set-label, 240px) - var(--set-info, 20px) - var(--space-3, 12px)))
    repeat(var(--einst-matrix-cols, 2), minmax(0, 1fr));
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-2) 0;
}
.einst-matrix-info { display: flex; align-items: center; justify-content: center; min-width: 0; }
.einst-matrix-zeile + .einst-matrix-zeile { border-top: 1px solid var(--color-border-light); }
/* Kopfzeile im selben Stil wie die Katalog-Spaltenköpfe — EIN Uppercase-Stil auf der
   Fläche, nicht ein zweiter (derselbe Grund wie bei `.einst-kat-head`). */
.einst-matrix-kopf {
  padding-bottom: var(--space-1-5);
  border-bottom: 1px solid var(--lod-gray-200);
  font-size: var(--fs-badge, 11px); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps, .08em); text-transform: uppercase; color: var(--lod-gray-500);
}
.einst-matrix-kopf .einst-matrix-sp { display: flex; align-items: center; gap: var(--space-1); }
.einst-matrix-zl {
  display: flex; align-items: center; gap: var(--space-1); min-width: 0;
  font-size: var(--fs-meta, 12px); font-weight: var(--fw-medium); color: var(--color-text);
}
.einst-matrix-zelle { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
/* Das Zahlenfeld füllt seine Spur — dieselbe Regel wie `--set-feld: 100%` in der
   Formularzeile, damit die rechten Feldkanten einer Spalte auf einer Linie liegen. */
.einst-matrix-zelle .einst-input { flex: 1; min-width: 0; }
.einst-matrix-einheit { flex-shrink: 0; font-size: var(--fs-meta, 12px); color: var(--color-text-muted); }
/* Fehlendes Feld: sichtbar, nicht leer. Eine leere Zelle sähe wie „nicht gesetzt" aus
   und die Zeile wäre still um eine Angabe kürzer. Die eigentliche Absicherung ist der
   Gate-Block (`check:settings`) — das hier ist die zweite Naht. */
.einst-matrix-zelle.is-fehlt { color: var(--status-danger-fg); font-weight: var(--fw-semibold); }
@media (max-width: 599px) {
  /* Mobil ist eine Kreuztabelle nicht bedienbar: gestapelt je Spalte, Beschriftung oben.
     Die ⓘ-Bahn entfällt mit — als eigene Grid-Zeile wäre sie ein 20px-Waisenkind
     über dem Label; die Erklärung der Dringlichkeiten bleibt über das Sektions-ⓘ. */
  .einst-matrix-zeile { grid-template-columns: minmax(0, 1fr); gap: var(--space-1-5); }
  .einst-matrix-kopf, .einst-matrix-info { display: none; }
}

/* ── Skalierung der Zeilen-Liste: Suche · Gruppen · Fenstern ──────────────────
   Anlass: `allgemein.mail.texte` rendert 65 Zeilen als eine flache, alphabetisch
   sortierte Liste — im Browser gemessen 3475px hohe Sektionskarte, ohne Suche, ohne
   Gruppierung, ohne Fenstern. Breite hätte das nicht behoben (1180px statt 800px
   kaufen eine Spalte, aber dieselben 65 Zeilen); Gruppieren macht daraus 12
   Überschriften mit Zähler. Schwellen und Begründung: `SUCHE_AB`/`FENSTER` in
   sections/einstellungen-katalog.js. */
.einst-kat-werkzeug {
  display: flex; align-items: center; gap: var(--space-3);
  padding: 0 0 var(--space-2-5);
}
.einst-kat-suche {
  display: flex; align-items: center; gap: var(--space-2); flex: 1; min-width: 0;
  padding: 0 var(--space-2-5); height: 32px;
  background: #fff; border: 1px solid var(--lod-gray-200, #dfe3e8); border-radius: var(--radius-md);
}
.einst-kat-suche:focus-within { border-color: var(--brand-default); box-shadow: var(--lod-shadow-focus); }
.einst-kat-suche .ui-ico img { opacity: .5; }
/* Das Eingabefeld selbst trägt KEINEN Rahmen — der sitzt am Label, damit Symbol und
   Feld eine Fläche bilden. `.app-scope input` setzt sonst eigene Kanten. */
.app-scope .einst-kat-sucheingabe {
  flex: 1; min-width: 0; height: 100%;
  border: none; background: none; outline: none; padding: 0;
  font-size: var(--fs-body, 14px); color: var(--color-text);
}
.einst-kat-treffer { flex-shrink: 0; font-size: var(--fs-meta, 12px); color: var(--color-text-muted); }
.einst-kat-keintreffer {
  margin: 0; padding: var(--space-4) 0; text-align: center;
  font-size: var(--fs-body, 14px); color: var(--color-text-muted);
}
.einst-kat-mehr { margin-top: var(--space-2); align-self: flex-start; }

.einst-kat-gruppen { display: flex; flex-direction: column; }
.einst-kat-gruppe:not(:first-child) { margin-top: var(--space-2); }
/* Gruppen-Kopf ist bewusst LEISER als ein Sektionskopf (12px/600 gegen 14px/600):
   er ordnet innerhalb einer Karte und darf nicht mit deren Überschrift konkurrieren. */
/* Gruppen-Zeile als ECHTE Listenzeile, nicht als Mikro-Text mit Chip daneben:
   40px hoch, Name in Zeilen-Größe (13px), der Zähler an der RECHTEN Kante — bei
   „> Anfrage 5" mit einem Kilometer Leere dahinter wirkte die Liste unfertig
   (Kyle: „sehr billig, wie die E-Mail-Texte-Darstellung"). Name und Zähler
   spannen die Zeile auf, der Rest ist bewusst Klickfläche. */
.einst-kat-gruppe-kopf {
  display: flex; align-items: center; gap: var(--space-2-5); width: 100%;
  min-height: 40px; padding: var(--space-2) var(--space-2-5);
  background: none; border: 0;
  /* `--color-border-light`, NICHT `--lod-gray-150`: letzteres existiert nicht (es steht
     in dieser Datei fünfmal als Altbestand mit Fallback und ist deshalb in
     `check:css-tokens` gepinnt). Ein sechstes Vorkommen hätte die Zahl erhöht und das
     Gate rot gefärbt — zu Recht: die Regel läuft am Design-System vorbei und bleibt bei
     jeder Token-Änderung stumm zurück. */
  border-bottom: 1px solid var(--color-border-light);
  cursor: pointer; text-align: left; color: inherit; font: inherit;
}
.einst-kat-gruppe-kopf:hover { background: var(--lod-gray-50, #f7f8fa); }
.einst-kat-gruppe-kopf:focus-visible { outline: none; box-shadow: var(--lod-shadow-focus); border-radius: var(--radius-sm); }
.einst-kat-gruppe-chev { flex-shrink: 0; width: 16px; height: 16px; transition: transform var(--duration-fast, .15s) var(--ease-soft, ease); }
.einst-kat-gruppe-chev img { width: 14px; height: 14px; opacity: .55; }
.einst-kat-gruppe.is-zu .einst-kat-gruppe-chev { transform: rotate(-90deg); }
.einst-kat-gruppe-name { font-size: var(--fs-body, 13px); font-weight: var(--fw-semibold); color: var(--color-text); }
.einst-kat-gruppe-zahl {
  margin-left: auto; flex-shrink: 0;
  min-width: 22px; padding: 1px var(--space-1-5);
  border-radius: var(--radius-pill, 999px);
  background: var(--lod-gray-100, #eef0f3); color: var(--color-text-muted);
  font-size: var(--fs-badge, 11px); font-weight: var(--fw-semibold); text-align: center;
}
.einst-kat-gruppe.is-zu .einst-kat-gruppe-rows { display: none; }

/* Katalog-Tabelle: Kopfzeile + Zeilen teilen EIN Spaltenraster, damit Name,
   Konto, Regeln und Aktionen untereinander stehen (vorher freies Flex-Fließen —
   wirkte unsortiert). Die Konto-Spalte existiert nur bei Katalogen mit
   Konto-Zuordnung (.has-konto), sonst fällt sie ganz weg. */
/* ── DIE LETZTEN ZWEI SPUREN SIND FEST, NICHT `auto` ─────────────────────────
   `.einst-kat-head` und `.einst-kat-row` sind GETRENNTE Grid-Container (kein
   `display: table`, kein Subgrid) — ein `auto`-Track bemisst sich also je Container
   an dessen EIGENEM Inhalt. Gemessen am 30.07.: im Kopf trug die Schalter-Spalte das
   Wort „Aktiv" (45px) und die Aktions-Spalte war LEER (0px), in der Zeile ein 52px
   breiter Schalter und ein 32px-Stift. Ergebnis: die Überschrift „AKTIV" stand 52px
   neben ihrem Schalter und dafür 6px über dem STIFT — sie beschriftete die falsche
   Spalte. Kein Fehler, den CSS meldet, und in JEDER Katalog-Tabelle derselbe.
   52px = Schalter 44 + `padding-right: var(--space-2)`; 32px = Icon-Knopf `btn-sm`. */
.einst-kat-table {
  display: flex; flex-direction: column;
  --einst-kat-sw: 52px; --einst-kat-akt: 32px;
  --einst-kat-cols: minmax(0, 1fr) var(--einst-kat-sw) var(--einst-kat-akt);
}
.einst-kat-table.has-regeln { --einst-kat-cols: minmax(0, 1fr) minmax(0, 1.4fr) var(--einst-kat-sw) var(--einst-kat-akt); }
.einst-kat-table.has-konto { --einst-kat-cols: minmax(0, 1fr) 150px var(--einst-kat-sw) var(--einst-kat-akt); }
.einst-kat-table.has-konto.has-regeln { --einst-kat-cols: minmax(0, 1fr) 150px minmax(0, 1.2fr) var(--einst-kat-sw) var(--einst-kat-akt); }
/* Kopf und Zeile brauchen NICHT NUR dieselben Spuren, sondern auch dieselbe Luecke.
   Die Zeile trug `gap: var(--space-3)`, der Kopf keine — bei vier Spalten schob das
   die Zeilen-Spuren um 12px gegen die Kopf-Spuren, und die Ueberschrift stand neben
   ihrer Spalte (gemessen: Kopf-Schalter 1548-1600, Zeilen-Schalter 1536-1588, gleiche
   rechte Aussenkante). Der `gap` gehoert deshalb in die GETEILTE Regel, nicht in eine
   der beiden. Dasselbe gilt fuer die waagerechte Innenluft. */
.einst-kat-head, .einst-kat-row {
  display: grid; grid-template-columns: var(--einst-kat-cols);
  align-items: center; gap: var(--space-3);
}

/* Tabellenkopf-Stil: EINE Definition für Katalog- UND Wochenplan-Tabelle.
   Vorher 11px/600 mit .04em hier und 11px/700 mit --ls-caps dort — zwei
   Uppercase-Stile auf derselben Fläche. */
.einst-kat-head {
  padding: 0 var(--space-2-5) var(--space-1-5);
  font-size: var(--fs-badge, 11px); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps, .08em); text-transform: uppercase; color: var(--lod-gray-500);
  border-bottom: 1px solid var(--lod-gray-200);
}
.einst-kat-c-art { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.einst-kat-c-konto, .einst-kat-c-regeln { min-width: 0; display: flex; align-items: center; gap: var(--space-1-5); }
/* Schalter-Spalte ZENTRIERT, Aktions-Spalte rechts. Rechtsbuendig waren Kopf und
   Zeile um 16px versetzt: ein 45px-Wort und eine 44px-Pille haben in einer 52px-Spur
   verschiedene Mitten, sobald beide an derselben Kante kleben. Zentriert stimmt es
   per Konstruktion — unabhaengig davon, wie lang die Ueberschrift ist. */
.einst-kat-c-sw { display: flex; align-items: center; justify-content: center; }
.einst-kat-c-akt { display: flex; align-items: center; justify-content: flex-end; }
.einst-kat-leer { font-size: var(--fs-body, 14px); font-weight: var(--fw-regular, 400); color: var(--lod-gray-400); }

.einst-kat-row {
  min-height: 52px; padding: var(--space-2) var(--space-2-5);
  cursor: pointer; border-radius: var(--radius-md);
}
.einst-kat-row + .einst-kat-row { border-top: 1px solid var(--lod-gray-100); }
.einst-kat-row:hover { background: var(--lod-gray-50); }
.einst-kat-row:focus-visible { outline: none; box-shadow: var(--lod-shadow-focus); }
.einst-kat-row.is-inaktiv { opacity: .6; }
.einst-kat-row.is-inaktiv .einst-kat-name { color: var(--lod-gray-500); }

/* Nur-Lesen-Zeile (Übersichten): zeigt einen abgeleiteten Zustand, den man hier nicht
   bearbeiten kann — deshalb kein Zeiger-Cursor und kein Hover-Echo, die beide eine
   Klickfläche versprechen würden. */
.einst-kat-row.is-nurlesen { cursor: default; }
.einst-kat-row.is-nurlesen:hover { background: transparent; }

/* Icon-Chip: Fläche = Art-Farbe @12%, Symbol via mask in der Art-Farbe. */
.einst-kat-chip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; flex-shrink: 0;
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--art-farbe, var(--lod-gray-400)) 14%, transparent);
}
.einst-kat-ico {
  display: inline-block; width: 18px; height: 18px;
  background-color: var(--art-farbe, var(--lod-gray-500));
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
}
.einst-kat-chip--preview { width: 40px; height: 40px; }
.einst-kat-chip--preview .einst-kat-ico { width: 22px; height: 22px; }
.einst-kat-chip--drawer { width: 28px; height: 28px; }

.einst-kat-name {
  /* 500, nicht 600: die Feld-Labels der Fläche sind 500. Zwei Gewichte auf
     derselben Größe nimmt niemand bewusst wahr, sie erzeugen aber Unruhe. */
  font-size: var(--fs-body, 14px); font-weight: var(--fw-medium, 500); color: var(--color-text);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.einst-kat-badges { display: flex; align-items: center; gap: var(--space-1-5); min-width: 0; overflow: hidden; }
.einst-kat-schnell { flex-shrink: 0; }
.einst-kat-edit { flex-shrink: 0; }

.einst-row-badge {
  display: inline-flex; align-items: center; height: 20px; padding: 0 var(--space-2);
  /* 12/600 wie der Knopf — die frühere 11/600-Stufe unterschied sich nur um 1px
     von der Untertitel-Stufe und las sich nicht als eigene Ebene. */
  font-size: var(--fs-meta, 12px); font-weight: var(--fw-semibold);
  background: var(--lod-gray-100); color: var(--lod-gray-700);
  border-radius: var(--radius-pill-sm); white-space: nowrap;
}
.einst-row-badge--konto { background: var(--lod-darkblue-50); color: var(--lod-darkblue); }
.einst-row-badge--off { background: var(--status-danger-soft, #fdecea); color: var(--lod-danger); }
.einst-row-badge[style*="--typ-farbe"] { background: color-mix(in srgb, var(--typ-farbe) 14%, #fff); color: var(--typ-farbe); }

/* ── Katalog: Kennzahlen-Karten (Anspruchskonten) ────────────────────────────── */
/* `auto-fit`, NICHT `auto-fill`: der Unterschied ist genau der Fall „weniger Karten als
   Spalten". `auto-fill` legt drei 350px-Spuren an, egal wie viele Karten es gibt — mit
   EINER Karte (Standorte: nur der Firmensitz; Anspruchskonten: nur „Urlaub", beides am
   30.07. gemessen) steht sie in der ersten Spur und rechts daneben bleiben 732px leer.
   `auto-fit` klappt die leeren Spuren zusammen, die Karte füllt die Reihe. Ab drei
   Karten verhalten sich beide identisch. */
.einst-konto-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--space-4);
}
.einst-konto-card { padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-3); text-align: left; }
.einst-konto-card.is-inaktiv { opacity: .65; }
.einst-konto-head { display: flex; align-items: center; gap: var(--space-2); }
/* 14px, nicht 16px: 16px ist die Ebene des SEITENTITELS („Allgemein"). Ein
   Kartentitel darf nicht genauso laut sein wie die Seite, in der er steht. */
.einst-konto-name { font-size: var(--fs-card-title, 14px); font-weight: var(--fw-semibold); color: var(--color-text); flex: 1; min-width: 0; }
.einst-konto-kpis { display: flex; gap: var(--space-5); }
.einst-konto-kpi { display: flex; flex-direction: column; gap: 2px; }
.einst-konto-kpi-wert { font-size: 22px; font-weight: var(--fw-semibold); color: var(--color-text); font-variant-numeric: tabular-nums; }
/* ── STAMMDATEN-ZEILEN (Label → Wert) ────────────────────────────────────────
   Die Gegenform zur Kachel: eine Kachel BETONT eine Zahl, ein kategorialer Wert
   („Bayern") und eine Lücke („—") haben nichts zu betonen. Vorher war auch das eine
   Kachel und nur die Schriftgröße wurde zurückgenommen — der Kommentar dazu sagte
   selbst, ein Textwert in einer Zahlen-Kachel sehe „wie ein Fehler" aus. Genau so war
   die Standort-Karte gebaut: „Bayern" groß über der Beschriftung „FEIERTAGE".
   Das Label steht LINKS in fester Bahn, damit mehrere Zeilen eine Kante haben; der
   Wert folgt, statt darunter zu stehen — eine Karte mit drei Angaben soll drei Zeilen
   hoch sein, nicht sechs. `data-text` ist damit weg (die Form ersetzt den Behelf). */
.einst-konto-zeilen { display: flex; flex-direction: column; gap: var(--space-1-5); }
.einst-konto-zeile { display: flex; align-items: baseline; gap: var(--space-3); min-width: 0; }
.einst-konto-zeile-label {
  flex: 0 0 auto; min-width: 148px;
  font-size: var(--fs-badge, 11px); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps, .08em); text-transform: uppercase;
  color: var(--lod-gray-500);
}
.einst-konto-zeile-wert {
  flex: 1 1 auto; min-width: 0;
  font-size: var(--fs-card-title, 14px); color: var(--color-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.einst-konto-kpi-label {
  font-size: var(--fs-badge, 11px); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps, .08em); text-transform: uppercase;
  color: var(--lod-gray-500);
}
.einst-konto-foot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  border-top: 1px solid var(--lod-gray-100); padding-top: var(--space-3); margin-top: auto;
}
/* Trennlinie und `margin-top: auto` gehören zum Fuß, der LINKS etwas trägt — bei den
   Anspruchskonten die „bucht hierauf"-Chips. Eine Standort-Karte hat dort nichts: der
   Fuß bestand aus einer Linie, einem leeren Drittel und dem Stift rechts (im Bild
   gesehen). `:has(:empty)` ist die Bedingung, weil genau dieser Span die Chips trägt —
   eine Klasse vom Renderer wäre eine zweite Stelle, an der man es vergessen kann. */
.einst-konto-foot:has(.einst-konto-arten:empty) {
  border-top: 0; padding-top: 0; margin-top: var(--space-1);
}
.einst-konto-arten { display: flex; flex-wrap: wrap; gap: var(--space-1-5); min-width: 0; }
.einst-konto-arten-leer { font-size: var(--fs-meta, 12px); color: var(--color-text-muted); }

/* ── Drawer-Editor (.setx) ───────────────────────────────────────────────────── */
.setx { display: flex; flex-direction: column; padding: var(--space-1) var(--space-1) var(--space-3); }
/* Zeilen im Drawer baut `LoD.SettingsRow` in der `drawer`-Variante — inklusive
   Container-Query an der Drawer-Breite (dort stand sie vorher). Hier bleiben nur
   die Dinge, die die Zeile nicht kennt: Feld-Fehler und die Sonder-Controls. */
.setx-row-fehler {
  grid-column: 1 / -1; padding-top: 2px;
  font-size: var(--fs-meta, 12px); line-height: 1.4; color: var(--status-danger-fg, #b42318);
}
.app-scope .setx-textarea { width: 100%; min-height: 92px; resize: vertical; font-size: var(--fs-body, 14px); line-height: 1.55; }
.einst-cell-label { font-size: var(--fs-body, 14px); font-weight: var(--fw-medium, 500); color: var(--color-text); }
.setx-swatch--custom { font-size: var(--fs-body, 14px); font-weight: var(--fw-semibold); }

.setx-konto-hint { grid-column: 1 / -1; padding: var(--space-1) 0 var(--space-2); }
/* Hinweis unter einem Feld, dessen mitgelieferter Wert NUR aus Platzhaltern besteht.
   Bewusst neutral getönt und nicht als Warnung: es ist kein Fehler, dort etwas
   einzutragen — es hat nur eine Folge, die man kennen muss (fester Betreff für alle
   Mails der Vorlage statt eines je Mail gebildeten). */
.setx-ph-hinweis {
  grid-column: 1 / -1; padding-top: 2px;
  font-size: var(--fs-meta, 12px); line-height: 1.45; color: var(--color-text-muted);
}
/* Verweis statt Editor im Firmensitz-Drawer (die Woche gehört der Sektion darüber).
   Bewusst ein ruhiger Satz und KEIN Warn-Banner: es ist kein Fehlerzustand, sondern
   die normale Ordnung — nur die Alt-Zeile darunter ist ein Hinweis, weil dort etwas
   Gespeichertes wirkungslos geworden ist. */
.setx-firmensitz-woche {
  margin: 0; font-size: var(--fs-meta, 12px); line-height: 1.5; color: var(--color-text-muted);
}
.setx-firmensitz-woche-alt { display: block; margin-top: var(--space-1); color: var(--status-warning-fg); }

.setx-footer {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  margin-top: var(--space-5); padding-top: var(--space-4);
  border-top: 1px solid var(--lod-border);
}
.setx-footer-actions { display: inline-flex; gap: var(--space-2); }

/* Erscheinung: Live-Preview + beschriftete Farb-/Symbol-Blöcke. */
.setx-appearance { display: flex; align-items: flex-start; gap: var(--space-5); padding: var(--space-3) 0; }
.setx-appearance-preview { display: flex; flex-direction: column; align-items: center; gap: var(--space-1-5); flex-shrink: 0; }
.setx-appearance-hint { font-size: var(--fs-badge, 11px); color: var(--lod-gray-500); }
.setx-appearance-ctl { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; flex: 1; }
.setx-appearance-symlabel { margin-top: var(--space-2); }
.setx-satz-hint { display: block; line-height: 1.5; margin-top: 2px; }
.setx-swatches { display: flex; flex-wrap: wrap; gap: var(--space-1-5); align-items: center; }
.setx-swatch img { pointer-events: none; filter: brightness(0) invert(1); }
.setx-swatch--custom img { filter: none; opacity: .75; }
.setx-swatch {
  width: 24px; height: 24px; border-radius: var(--radius-circular);
  border: 2px solid transparent; cursor: pointer; padding: 0; flex-shrink: 0;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
}
.setx-swatch:hover { transform: scale(1.1); }
.setx-swatch.is-sel { border-color: var(--brand-default); box-shadow: 0 0 0 2px var(--brand-light); }
.setx-swatch--custom {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--lod-gray-100); color: var(--lod-gray-600); font-weight: var(--fw-bold);
  position: relative; overflow: hidden;
}
.setx-swatch--custom .einst-color { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%; padding: 0; border: none; }

.einst-icon-grid {
  display: grid; grid-template-columns: repeat(auto-fill, 34px); gap: var(--space-1);
  padding: var(--space-2);
  background: var(--lod-gray-50); border: 1px solid var(--lod-border); border-radius: var(--radius-md);
}
.einst-icon-grid[hidden] { display: none; }
.einst-icon-opt {
  width: 34px; height: 34px; display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid transparent; border-radius: var(--radius-sm); cursor: pointer;
}
.einst-icon-opt:hover { background: var(--color-surface); border-color: var(--lod-border); }
.einst-icon-opt.is-sel {
  background: var(--lod-darkblue); border-color: var(--lod-darkblue);
  box-shadow: 0 0 0 2px var(--brand-light);
}
.einst-icon-opt.is-sel img { filter: brightness(0) invert(1); }

/* Nativer Farb-Input (Fallback „eigene Farbe"). */
.einst-color {
  width: 40px; height: 28px; padding: 2px; cursor: pointer;
  border: 1px solid var(--lod-gray-200); border-radius: var(--radius-md); background: var(--color-surface);
}
.einst-color::-webkit-color-swatch-wrapper { padding: 0; }
.einst-color::-webkit-color-swatch { border: none; border-radius: var(--radius-sm); }

/* ── Responsive (Notebook 1000–1399 · Tablet 600–999 · Mobile <600) ──────────── */
@media (max-width: 1399px) {
  .einst-konto-grid { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
  /* Konto-Spalte schmaler, Regeln dürfen zuerst schrumpfen. */
  .einst-kat-table.has-konto { --einst-kat-cols: minmax(0, 1fr) 120px var(--einst-kat-sw) var(--einst-kat-akt); }
  .einst-kat-table.has-konto.has-regeln { --einst-kat-cols: minmax(0, 1fr) 120px minmax(0, 1fr) auto auto; }
}
@media (max-width: 999px) {
  .einst-layout { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
  /* Tablet: Regeln-Spalte weicht, Konto + Name bleiben lesbar. */
  .einst-kat-table { --einst-kat-cols: minmax(0, 1fr) auto auto; }
  .einst-kat-table.has-konto, .einst-kat-table.has-konto.has-regeln { --einst-kat-cols: minmax(0, 1fr) 120px auto auto; }
  .einst-kat-table.has-regeln { --einst-kat-cols: minmax(0, 1fr) auto auto; }
  .einst-kat-c-regeln { display: none; }
  /* ── BEREICHS-NAVIGATION: RASTER STATT SCROLLER (2026-08-01) ──────────────
     Hier stand eine waagerechte Leiste mit `overflow-x: auto`. Im Browser gemessen
     (Kyle-Meldung „Responsive Menü geht gar nicht", Screenshot bei ~760px):
     Inhalt **3095px** in 670px sichtbarer Breite — **2425px verdeckt**, also 12 von
     17 Bereichen unerreichbar ohne Wischen, und der Schnitt fiel mitten in „KI-".

     ★ EIN FADE WÄRE HIER DIE FALSCHE ANTWORT, und das ist im Repo schon entschieden:
     der Header-Vertrag (`check:header-live`) meldet eine Fade-Kante ÜBER Pills
     ausdrücklich als Verstoß — sie löscht die angeschnittene Pille und damit den
     einzigen Hinweis, dass es weitergeht. Für Pills ist der sichtbare Anschnitt die
     Andeutung. Nur trägt ein Anschnitt bei 2425px verdecktem Inhalt nichts mehr:
     eine Liste von 17 Zielen ist keine Reiterleiste, und Scrollen über viereinhalb
     Bildschirmbreiten ist das falsche Steuerelement, nicht die falsche Verzierung.

     Das Raster zeigt ALLES ohne Geste. `auto-fill` statt fester Spaltenzahl, damit
     es von 999px bis 380px dieselbe Regel bleibt (bei 670px drei Spalten, bei 346px
     eine) — eine Spaltenzahl je Breakpoint wäre die nächste Zahl, die beim 18.
     Bereich nicht mehr stimmt. Der Preis ist Bauhöhe; sie ist vertretbar, weil man
     die Bereichsliste einmal benutzt und danach in der Fläche arbeitet.

     Die BORDER-Behandlung der alten Leiste (`border-bottom` als Aktiv-Marke) fällt
     mit ihr weg: im Raster ist ein Eintrag wieder eine Menü-Zeile, und dafür gilt
     die Desktop-Behandlung (gefüllte Fläche + linke Kante) aus der Basis-Regel. */
  .einst-nav {
    position: static;
    display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: var(--space-1) var(--space-2);
    overflow: visible;
  }
  /* Kein `.einst-nav-group`-Padding hier: das Element ist ab 1199px `display:none`
     (Regel oben) und wird in diesem Band nicht zurückgesetzt — eine Regel darauf
     wirkt nie. */
  .einst-search-panel { left: 0; right: 0; width: auto; max-width: none; }
  /* Kein Deckel unter 1000px: der Bildschirm ist hier ohnehin schmaler als 800px
     oder nur knapp darüber, ein Deckel würde nur eine leere Spalte am rechten Rand
     erzeugen. Die Fläche bleibt dabei einheitlich — alles nimmt dieselbe Breite.
     Gilt auch für den Flächen-Deckel selbst: die Nav-Spalte ist hier eine waagerechte
     Leiste, `--einst-flaeche` (Nav + Karte) beschreibt das Layout dann nicht mehr. */
  .einst-sec, .einst-pane .einst-intro { max-width: none; }
  .einst-layout, .einst-root .app-page-toolbar { max-width: none; margin-inline: 0; }
}
/* Touch-Maße der ZEILE (Control-Höhen, ⓘ-Trefferfläche) stehen im Zeilen-Modul —
   sonst hätte eine Zeile in einem anderen Kontext andere Finger-Maße. */
@media (max-width: 599px) {
  .einst-wrap { padding: var(--space-4) 0 var(--space-6); }
  .einst-input { width: 100%; max-width: none; }
  .einst-sec-toggle { min-height: 44px; }
  .app-scope .einst-reset { min-width: 40px; min-height: 40px; }
  .einst-kat-badges { display: none; } /* Mobile: Chip+Name+Switch reichen — Details im Drawer */
  /* Mobile: nur noch Name + Aktiv + Bearbeiten; Konto steht im Drawer. */
  .einst-kat-table, .einst-kat-table.has-konto,
  .einst-kat-table.has-regeln, .einst-kat-table.has-konto.has-regeln { --einst-kat-cols: minmax(0, 1fr) auto auto; }
  .einst-kat-c-konto { display: none; }
  .einst-kat-head { display: none; } /* Spaltenköpfe ohne Spalten sind nur Rauschen */
  .einst-konto-grid { grid-template-columns: minmax(0, 1fr); }
  .setx-input { width: 100%; max-width: none; }
}

/* ── Sektions-Blöcke mit Klapp-Kopf ──────────────────────────────────────────
   Jede Sektion ist ein umrandeter Block mit getöntem Kopf: Titel + Kurztext +
   optionale Primär-Aktion. Der ganze Kopf ist die Klappfläche (Hover sichtbar).
   Zustand pro Nutzer in LoD.prefs; Startzustand aus dem Deskriptor (Feld zugeklappt). */
/* Fläche, Rahmen und Radius kommen aus `.lod-surface` (Flächen-SSOT, panel.css) —
   die Klasse setzt die Shell. Hier stand das dreifach von Hand (#fff, gray-150,
   radius-lg); auf dem grauen Hintergrund braucht die Karte zusätzlich die
   Ruhe-Elevation, und die gehört dem Primitive, nicht dieser Datei. */
.einst-sec { overflow: hidden; }

/* ── Kartenbreite: EINE für alle ─────────────────────────────────────────────
   Keine Klasse, keine Ableitung aus Feldtypen, keine Ausnahme — sonst sieht der
   Wechsel von „Lizenzen" nach „Anfragen & SLA" anders aus, und genau das darf
   nicht sein. Begründung und Vorgeschichte bei `--einst-karte` in `.einst-wrap`. */
.einst-sec { max-width: var(--einst-karte); }
/* ── KEINE TÖNUNG IM KOPF — Struktur aus Typografie + EINER echten Linie ───────
   Bis 2026-07-29 (2) trug der Kopf `--lod-gray-50` (#F7F8FA). Damit standen auf der
   Fläche DREI Grautöne übereinander: der graue Seitenhintergrund, die weiße Karte und
   ein Kopf, der farblich genau dazwischen liegt — er las sich als Loch in der Karte
   (Kyle: „das muss ordentlicher, Grau auf Grau ist billig").

   ★ Die Tönung zu entfernen hat den Kopf ZUERST ZERLEGT, nicht verbessert — das ist
   die Lehre dieser Zeilen: die getönte Bande hatte drei Layout-Schwächen KASCHIERT,
   die auf Weiß einzeln sichtbar wurden (Kyles Screenshots, 29.07.):
     · das ⓘ hing 46px vom Titel entfernt in seiner eigenen linken Bahn,
     · der Chevron-Kreis (weiß + Rahmen) wurde auf Weiß zum leeren Umriss,
     · die Ersatz-Trennlinie (#f0f0f0) war zu schwach, der Kopf wirkte „mager".
   Deshalb gehören diese vier Entscheidungen ZUSAMMEN und keine darf einzeln
   zurückgedreht werden: keine Tönung + ⓘ am Titel + Chevron als bloßes Zeichen
   rechts + eine SICHTBARE Linie (`--color-border`, nicht `-light`). */
.einst-sec-head {
  /* `flex-start`: die Klappfläche hat zwei Zeilen — `center` würde Knöpfe und
     Schalter zwischen Titel und Beschreibung setzen. Die 28px-Titel-Zeile trägt
     `.einst-sec-kopfzeile` als `min-height`, damit alle Oberkanten fluchten.
     RECHTS 48px statt 16px: der Eck-Slot des Sektions-ⓘ (unten) liegt ABSOLUT
     in der Karten-Ecke — das Padding reserviert seinen Platz, damit Chevron,
     Schalter und „+ Neu" nie darunterrutschen. 48 = 16 Rand + 20 ⓘ + 12 Abstand;
     konstant für JEDE Karte (jede Sektion trägt ein ⓘ), also bleibt auch die
     Chevron-Spalte über alle Karten auf EINER Kante. */
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-3) calc(var(--space-4) + 32px) var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-border);
}
/* ── Sektions-ⓘ: FESTER ANKER OBEN RECHTS (Kyle 02.08.) ──────────────────────
   „Immer rechts oben in der Sektion — und darf sich nicht durch Mehrzeiligkeit
   verschieben." Ein Flex-Kind im Kopf kann das nicht leisten: es wandert mit der
   Titel-LÄNGE (x) und mit jeder `thema`-Zeile (Kopf-Höhe). Der Slot ist deshalb
   an der KARTE verankert, nicht im Textfluss — eine Ecke, eine Spalte, egal wie
   der Kopf umbricht. `height: 28px` + `align-items: center` zentriert das ⓘ
   optisch auf der 28px-Titel-Zeile (deren Oberkante = Kopf-Padding = 12px). */
.einst-sec { position: relative; }
.einst-sec-infoslot {
  position: absolute; top: var(--space-3); right: var(--space-4);
  height: 28px; display: inline-flex; align-items: center;
}
.einst-sec.is-zu .einst-sec-head { border-bottom-color: transparent; }
/* ── Sektions-Schalter im Kopf ────────────────────────────────────────────────
   Der Schalter, der die ganze Sektion an- und abschaltet, sitzt RECHTS IM KOPF —
   nicht als erste Zeile im Inhalt (als getönte Zeile war er „ein hässlicher grauer
   Balken", Kyle 27.07.). Die Position sagt „ich gelte für alles darunter".
   Er liegt NEBEN der Klappfläche — sonst würde jeder Klick auf den Schalter die
   Sektion zuklappen. Sein ⓘ bleibt bei IHM (es erklärt den Schalter, nicht die
   Sektion) und ist als direktes Kind des Kopfes gegen Stauchung gesichert. */
.einst-sec-switch { flex-shrink: 0; margin-left: auto; }
.einst-sec-head > .set-row-info { flex-shrink: 0; }
/* Ausgeschaltete Sektion: Kopf bleibt voll lesbar (dort schaltet man wieder ein),
   der Titel wird gedämpft — sonst verspricht die Karte Wirkung, die sie nicht hat. */
.einst-sec--aus .einst-card-sec-title,
.einst-sec--aus .einst-sec-thema { color: var(--color-text-muted); }
/* Statt einer leeren Karte: ein Satz. Alle Felder sind `hidden`, wenn der Schalter
   aus ist — ohne diesen Satz stand dort nur weiße Fläche (sah nach Ladefehler aus). */
.einst-sec-aus {
  margin: 0; padding: var(--space-3) 0;
  font-size: var(--fs-body, 14px); color: var(--color-text-muted);
}
/* In der AUSGESCHALTETEN Sektion verschwinden auch die Gruppen-Überschriften.
   Die Felder sind `hidden`, die Eyebrow-Zeilen (`.set-gruppe`) aber nicht — übrig
   blieb ein verwaistes „FENSTER" über dem Ausgeschaltet-Satz, und der sektionsweite
   Hinweis las sich als Kind eines Gruppen-Titels (Hierarchie invertiert; Befund der
   unabhängigen Sicht-Prüfung an der Ruhezeit-Karte). Eine Überschrift über null
   sichtbaren Feldern ist keine Information. */
.einst-sec--aus .einst-fields .set-gruppe { display: none; }
/* ── Klappfläche: ZWEI Zeilen ────────────────────────────────────────────────
   Zeile 1 trägt Chevron + Titel + Zähler, Zeile 2 das vollständige `thema`.
   Vorher lagen beide in EINER Flex-Zeile — mit zwei Folgen gleichzeitig: der Titel
   ohne `flex-shrink: 0` wurde geschrumpft und umgebrochen (7 Sektionen gemessen),
   und das `thema` war per Ellipse trotzdem abgeschnitten (10 Sektionen, schlimmster
   Fall 452 von 1158px = 61% unlesbar). Der Kopf wird dadurch höher; das ist gewollt. */
.einst-sec-toggle {
  display: flex; flex-direction: column; align-items: stretch; gap: 2px;
  flex: 1; min-width: 0; padding: 0;
  background: none; border: 0; cursor: pointer; text-align: left; color: inherit; font: inherit;
}
/* Titel-Zeile: Titel · Zähler · Modul-Marke dicht beieinander (8px). Das
   Sektions-ⓘ liegt NICHT mehr hier, sondern im Eck-Slot `.einst-sec-infoslot`
   (oben rechts an der Karte, Begründung dort) — in der Zeile wanderte seine
   x-Position mit der Titel-Länge, Karte für Karte anders. */
.einst-sec-kopfzeile {
  display: flex; align-items: center; gap: var(--space-2);
  min-width: 0; min-height: 28px;
}
/* Die MODUL-MARKE am Sektionskopf hat hier bewusst KEINE eigene Regel: sie ist
   dieselbe Sache wie an der Gruppen-Überschrift und trägt deshalb dieselbe Klasse
   `.set-modul-marke` (settings-row.css). Ein zweiter Block hier sähe am Tag der
   Kopie identisch aus und liefe danach auseinander — das Muster, gegen das
   `check:css-doppel` gebaut ist. Erscheint nur, wenn AUSNAHMSLOS jedes Feld der
   Sektion dasselbe Modul liest (abgeleitet in `_einstSekMarke`). */
.einst-sec-toggle:focus-visible { outline: none; box-shadow: var(--lod-shadow-focus); border-radius: var(--radius-sm); }
/* ── Chevron: ein ZEICHEN, kein Knopf-im-Kreis — und IMMER das letzte Kopf-Element.
   Die Kreis-Fassung (weißer Grund + Rahmen) funktionierte nur auf der getönten
   Bande; auf dem weißen Kopf blieb ein leerer Umriss, der wie ein vergessenes
   Radio-Element aussah (Kyles Screenshot: „Oder das mit den Chevrons"). Links vor
   dem Titel brauchte er zudem bei jeder nicht klappbaren Sektion einen unsichtbaren
   Platzhalter — das Loch im Kopf.
   Er sitzt als DIREKTES KIND des Kopfes hinter allen Aktionen (nicht in der
   Titel-Zeile): dort verdrängten ihn Sektions-Schalter samt ⓘ um ~90px nach links,
   und die Auf/Zu-Zeichen zweier übereinander liegender Karten standen nicht auf
   einer Spalte (Befund der unabhängigen Sicht-Prüfung). Die 28px-Höhe zentriert
   ihn auf der Titel-Zeile des flex-start-Kopfes; klickbar ist er zusätzlich zum
   Kopf (Binder in einstellungen.js), die Tastatur läuft über die Klappfläche. */
.einst-sec-chev {
  flex-shrink: 0; width: 20px; height: 28px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: transform var(--duration-fast, .15s) var(--ease-soft, ease);
}
.einst-sec-chev img { width: 16px; height: 16px; opacity: .45; transition: opacity var(--duration-fast, .15s) var(--ease-soft, ease); }
.einst-sec.is-zu .einst-sec-chev { transform: rotate(-90deg); }
.einst-sec-head:hover .einst-sec-chev img { opacity: .85; }
/* Der Titel bricht NIE und gibt NIE nach — er ist die Beschriftung der Karte.
   Nachgeben darf nur der Zähler-Chip, und der ist ohnehin einstellig.
   15px ist die bewusste Stufe ZWISCHEN den Tokens: `--fs-section` (16px) trägt der
   Bereichs-Titel im Seitenkopf, `--fs-card-title` (14px) war dem Feld-Label (13px)
   zu nah — genau das „mager", das der Kopf nach dem Ende der Tönung hatte. Die
   Hierarchie liest sich jetzt 16 → 15 → 13. */
.einst-sec-head .einst-card-sec-title {
  margin: 0; font-size: 15px; font-weight: var(--fw-semibold); letter-spacing: -.01em;
  flex-shrink: 0; white-space: nowrap;
}
/* Zeile 2: das `thema`, vollständig und umbrechend, bündig unter dem Titel (die
   Einrückung um den früheren Chevron-Slot ist mit ihm verschwunden — EINE linke
   Kante im Kopf). Lesemaß gedeckelt: über die ganze Kartenbreite wären das ~110
   Zeichen pro Zeile, deutlich über dem Lesbaren. */
.einst-sec-thema {
  font-size: var(--fs-meta, 12px); font-weight: var(--fw-regular, 400); color: var(--color-text-muted);
  line-height: 1.45; min-width: 0; max-width: 62ch;
}
/* Zähler-Chip am Sektionstitel: wie viele Einträge steckt die Liste — sichtbar ohne
   Aufklappen oder Scrollen. Neutral getönt, damit er die Überschrift begleitet und
   nicht mit den Status-Badges der Zeilen konkurriert. */
.einst-sec-count {
  flex-shrink: 0; margin-left: calc(var(--space-1) * -1);
  min-width: 22px; padding: 1px var(--space-1-5);
  border-radius: var(--radius-pill, 999px);
  background: var(--lod-gray-100, #eef0f3); color: var(--color-text-muted);
  font-size: var(--fs-caption, 12px); font-weight: var(--fw-semibold); text-align: center;
}
.einst-sec-neu { flex-shrink: 0; }
/* Nicht klappbare Sektion (nur eine Tabelle): gleiche Optik, aber kein Cursor,
   kein Hover, kein Chevron — der Kopf ist reine Überschrift. */
.einst-sec-toggle--fix { cursor: default; background: none; border: none; }
.einst-sec-toggle--fix:hover { background: none; }
.einst-sec--fix .einst-fields { display: block; }
/* Inhalt: eigene Innenluft, damit die erste Zeile nicht am Kopf klebt. */
.einst-sec .einst-fields { padding: var(--space-2) var(--space-4) var(--space-3); }

/* ── Lesemaß der Formularzeilen: NICHT hier ──────────────────────────────────
   Der Deckel steht im Zeilen-Modul (`--set-mass` in settings-row.css), weil die
   Zeile ihre natürliche Breite selbst kennt — sie ist die Summe ihrer Bahnen.
   Hier stand er als `max-width: 1100px` auf `.einst-fields > .set-row`, mit zwei
   Folgen: die Zahl existierte zweimal (Bahnen dort, Deckel hier) und griff nur
   bei DIREKTEN Kindern — Zeilen in einem Panel-Host (Abrechnungsarten) liefen
   ungedeckelt durch. */
.einst-sec.is-zu .einst-fields { display: none; }

/* ── Einheitliche Zeilen-Typografie ─────────────────────────────────────────────
   Kyle: „zig unterschiedliche Schriftarten". Drei Ebenen, sauber gestaffelt:
   Sektionskopf 14px/600 → Zeilen-Label 13px/500 → Hilfetext 12px/400. Label- und
   Satz-Zeilen teilen Größe, Farbe und Zeilenhöhe; nur die Anordnung unterscheidet
   sich (Label links/Control rechts vs. Control im Lesefluss). */
/* Zeilen-Label und die Erklärung am ⓘ tragen ihre Typo im Zeilen-Modul. Hier bleibt
   der frei stehende Hinweistext, den Tabellen und Sonderflächen benutzen (Kopf einer
   Katalog-Liste, Konto-Hinweis, Wochenplan-Fehler). Vermessen (Kyle: „Mini Text mit
   3410230 Umbrüchen"): `max-width: 78ch` auf 12px brach einen Ein-Zeiler in drei
   Zeilen um, während rechts 600px leer blieben. Untergeordnet bleibt er über Gewicht
   und Farbe, nicht über Winzigkeit. */
.einst-row-hilfe {
  font-size: var(--fs-body, 14px); font-weight: var(--fw-regular, 400);
  color: var(--color-text-secondary); line-height: 1.5; max-width: 88ch;
}
.app-scope .einst-textarea {
  width: 100%; min-height: 92px; resize: vertical;
  font-size: var(--fs-body, 14px); line-height: 1.55;
}

/* ── Wochenplan-Tabelle (Feld-Typ 'wochenplan') ──────────────────────────────
   Sieben Zeilen Mo–So mit Arbeitstag-Schalter und den Zeiten DIREKT in der Zeile.
   Kyle-Feedback 2026-07-26: Zeiten hinter einem Stift pro Tag zu verstecken war
   falsch — die Woche muss auf einen Blick lesbar und sofort editierbar sein.
   Ein Grid mit fixen Spalten sorgt dafür, dass alle Felder gleich groß sind
   (auch im Standort-Drawer, weil dort dieselbe Komponente rendert). */
.einst-wplan-table {
  display: flex; flex-direction: column;
  border: 1px solid var(--lod-border-light);
  border-radius: var(--radius-md, 8px);
  overflow: hidden;
}
.einst-wplan-head,
.einst-wplan-row {
  display: grid;
  grid-template-columns: minmax(120px, 1.4fr) 92px repeat(4, minmax(96px, 1fr));
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
}
.einst-wplan-head {
  background: var(--lod-gray-50, #f7f8fa);
  border-bottom: 1px solid var(--lod-border-light);
  font-size: var(--fs-badge, 11px); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps, .08em); text-transform: uppercase;
  color: var(--lod-gray-500);
}
.einst-wplan-row + .einst-wplan-row { border-top: 1px solid var(--lod-gray-100, #eef0f3); }
.einst-wplan-row:hover { background: var(--lod-gray-50); }
/* Erste Spalte im KOPF trug 13px/500/uppercase, die uebrigen 11px/700/uppercase —
   zwei Uppercase-Stile in einer Tabellenzeile. Der Kopf-Stil kommt jetzt komplett
   aus `.einst-wplan-head`; hier bleibt nur die ZEILEN-Zelle. */
.einst-wplan-row .einst-wplan-c-tag {
  font-size: var(--fs-body, 14px); font-weight: var(--fw-medium, 500);
  color: var(--color-text); text-transform: none; letter-spacing: normal;
}
.einst-wplan-row.is-aus .einst-wplan-c-tag { color: var(--color-text-muted); }
.einst-wplan-dot {
  width: 6px; height: 6px; border-radius: var(--radius-circular, 50%);
  background: var(--brand-default); flex-shrink: 0;
}
/* Zeit-Eingaben: gleiche Breite in jeder Spalte, kompakt und mittig. */
.app-scope .einst-wplan-zeit {
  width: 100%; min-width: 0; text-align: center;
  font-variant-numeric: tabular-nums;
}
.einst-wplan-row.is-aus .einst-wplan-zeit { opacity: .45; }
.einst-wplan-fuss {
  margin: var(--space-2) 0 0; font-size: var(--fs-meta, 12px); color: var(--color-text-muted);
}
.einst-wplan-loading { padding: var(--space-3); font-size: var(--fs-meta, 12px); color: var(--color-text-muted); }

/* Notebook/Tablet: Pausen-Spalten dürfen schmaler werden, bevor umgebrochen wird. */
@media (max-width: 1399px) {
  .einst-wplan-head,
  .einst-wplan-row { grid-template-columns: minmax(100px, 1.2fr) 84px repeat(4, minmax(84px, 1fr)); gap: var(--space-2); }
}
@media (max-width: 999px) {
  /* Tablet: zwei Zeilen je Tag — Kopfzeile entfällt, Felder tragen aria-label. */
  .einst-wplan-head { display: none; }
  .einst-wplan-row {
    grid-template-columns: 1fr 1fr 1fr 1fr;
    grid-template-areas: 'tag tag sw sw' 'von bis pv pb';
    row-gap: var(--space-2);
  }
  .einst-wplan-c-tag { grid-area: tag; }
  .einst-wplan-c-sw { grid-area: sw; justify-self: end; }
}

/* ── Zwei gemessene Ursachen (Playwright, 2026-07-26) ────────────────────────
   1) Der LEERE Banner-Div zählte als Flex-Item und erzeugte über den Wrap-Gap
      16px Extra-Luft ZUSÄTZLICH zur Scroll-Polsterung → Abstand oben war 32px
      statt der üblichen 16px. Leeren Banner ausblenden statt Gaps zu frisieren.
   2) Die Nav-Items sind <button> in .app-scope — der App-Scope-Button-Reset
      (`.app-scope button { padding:0 }`) ist SPEZIFISCHER als `.einst-nav-item`
      und hat mein Padding überstimmt (deshalb klebten Icon und Änderungs-Punkt
      am Rand). Über .app-scope qualifizieren, dann greift es. */
#einst-banner:empty { display: none; }
.app-scope .einst-nav-item {
  padding: var(--space-2-5) var(--space-4);
  border-left: 3px solid transparent;
}
.app-scope .einst-nav-item.is-active { border-left-color: var(--lod-darkblue); }
.app-scope .einst-nav-group { padding: var(--space-2) var(--space-4) var(--space-1); }

/* Hilfetexte über Listen/Tabellen: volle Breite statt schmaler Flex-Spalte.
   Kyle: „Was soll dieser Mini-Text hier mit 3410230 Umbrüchen?" — der Text stand
   als Flex-Kind neben dem Button und brach nach ~400px vierzeilig um. */

/* Wochenplan als Sub-Feld im Editor-Drawer: volle Zeilenbreite (die Tabelle
   braucht Platz), Label darüber statt links daneben. */
.einst-setx-row--voll { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-3) 0; }
.einst-setx-row--voll .einst-setx-label {
  font-size: var(--fs-body, 14px); font-weight: var(--fw-semibold); color: var(--color-text);
}
.einst-wplan--sub .einst-wplan-head,
.einst-wplan--sub .einst-wplan-row {
  grid-template-columns: minmax(88px, 1fr) 72px repeat(4, minmax(72px, 1fr));
  gap: var(--space-2); padding: var(--space-1-5) var(--space-2);
}
.einst-wplan--sub .einst-wplan-fuss { display: none; }
.einst-wplan--sub { overflow-x: auto; }
.einst-wplan--sub .einst-wplan-table { min-width: 560px; }
.app-scope .einst-wplan--sub .einst-wplan-zeit { padding-left: var(--space-1); padding-right: var(--space-1); }

/* Firmensitz-Kennzeichnung in der Standort-Liste (Kyle: „nirgends ersichtlich,
   dass das der Firmenstandard ist"). */
.einst-row-badge--std {
  background: var(--lod-darkblue); color: #fff; border-color: var(--lod-darkblue);
}

/* ── Variablen-Leiste + Vorschau (LoD.TextVariablen) ─────────────────────────
   Sitzt unter dem Textfeld: Einfuege-Menue, Vorschau-Knopf und die Warnung bei
   unbekannten Platzhaltern. In der gestapelten Zeile spannt sie ueber die Breite. */
/* Läuft über den `unten`-Slot der Zeile und spannt daher über alle Bahnen. */
.einst-var-host { min-width: 0; grid-column: 1 / -1; }
.tvar-leiste { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; padding-top: var(--space-1-5); }
.tvar-warnung {
  font-size: var(--fs-meta, 12px); color: var(--status-warning-fg, #8a5a00);
  background: var(--status-warning-bg); border-radius: var(--radius-sm);
  padding: 2px var(--space-2); min-width: 0;
}
.tvar-warnung[hidden] { display: none; }

.tvar-vorschau-body { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-1) var(--space-1) var(--space-3); }
.tvar-vorschau-hinweis { margin: 0; font-size: var(--fs-body, 14px); color: var(--color-text-secondary); }
.tvar-vorschau-warn { margin: 0; font-size: var(--fs-meta, 12px); color: var(--status-warning-fg, #8a5a00); }
/* Termin-Attrappe: bewusst schlicht (ein Balken + Titel) — sie soll den Betreff
   zeigen, nicht Outlook nachbauen. */
.tvar-vorschau-termin {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-3-5);
  border: 1px solid var(--lod-border-light); border-radius: var(--radius-md);
  background: var(--color-surface, #fff);
}
.tvar-vorschau-termin-bar { width: 4px; align-self: stretch; min-height: 28px; border-radius: var(--radius-pill-sm); background: var(--lod-darkblue); }
.tvar-vorschau-termin-titel { font-size: var(--fs-body, 14px); font-weight: var(--fw-semibold); color: var(--color-text); }

.tvar-vorschau-seg { display: inline-flex; gap: 2px; padding: 2px; background: var(--lod-gray-100, #eef0f3); border-radius: var(--radius-md); align-self: flex-start; }
.app-scope .tvar-seg-btn {
  padding: var(--space-1) var(--space-3); border: none; background: transparent; cursor: pointer;
  font-size: var(--fs-meta, 12px); font-weight: var(--fw-medium); color: var(--lod-gray-700); border-radius: var(--radius-sm);
}
.app-scope .tvar-seg-btn.is-active { background: var(--color-surface, #fff); color: var(--lod-darkblue); font-weight: var(--fw-semibold); box-shadow: var(--shadow-2, 0 1px 2px rgba(0,0,0,.08)); }
/* Mail-HTML laeuft im sandboxed iframe — es traegt eigene Inline-Styles und darf
   die App-Optik nicht anfassen. */
/* Die Vorschau füllt den Drawer. Vorher: iframe fix 460px + overflow:hidden —
   gemessen wurden 225px abgeschnittener Inhalt (genau die Signatur) bei 522px
   ungenutzter Höhe darunter. Die konkrete Höhe setzt `_rahmenHoehe()` beim
   Hydrieren (JS kennt den freien Platz); hier nur Boden und Deckel. */
.tvar-vorschau-mail { border: 1px solid var(--lod-border-light); border-radius: var(--radius-md); overflow: hidden; background: #fff; flex: 1 1 auto; min-height: 0; display: flex; }
.tvar-vorschau-frame { display: block; width: 100%; height: 100%; min-height: 360px; border: 0; }
.tvar-vorschau-body--voll { flex: 1 1 auto; min-height: 0; }

/* Betreff-Zeile der Mail-Vorschau (art: 'mail').
   BEWUSST ÜBER dem Rahmen und nicht darin: der Betreff ist das, was im Postfach in
   der Liste steht — er entscheidet, ob die Mail überhaupt geöffnet wird, und ist
   getrennt vom Rumpf zu beurteilen. Im gerenderten HTML kommt er nicht vor (das ist
   nur der Body), er wäre sonst gar nicht sichtbar. Monospace wäre falsch: der Leser
   soll ihn als Postfach-Zeile lesen, nicht als Code. */
.tvar-vorschau-betreff {
  display: flex; align-items: baseline; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-3);
  border: 1px solid var(--lod-border-light);
  border-radius: var(--radius-md);
  background: var(--color-bg-subtle, #f8f9fb);
  flex: 0 0 auto;
}
.tvar-vorschau-betreff-label {
  flex: 0 0 auto;
  font-size: var(--fs-caption); text-transform: uppercase; letter-spacing: .04em;
  color: var(--color-text-muted);
}
.tvar-vorschau-betreff-text {
  flex: 1 1 auto; min-width: 0;
  font-size: var(--fs-body); font-weight: var(--fw-medium, 500); color: var(--color-text);
  /* Kein `nowrap` + Ellipse: ein abgeschnittener Betreff ist in einer VORSCHAU
     wertlos — man prüft ja gerade, ob er zu lang ist. */
  overflow-wrap: anywhere;
}

@media (max-width: 999px) {
  .tvar-vorschau-frame { min-height: 320px; }
}
@media (max-width: 599px) {
  .tvar-vorschau-betreff { flex-direction: column; gap: var(--space-1); }
}
@media (max-width: 599px) {
  .tvar-leiste { gap: var(--space-1-5); }
  .tvar-leiste .app-cta-btn { flex: 1 1 auto; }
  .tvar-vorschau-frame { min-height: 260px; }
}

/* ── Rich-Text-Feld (typ 'html', LoD.RichText) ───────────────────────────────
   Der Editor bringt seine Optik selbst mit (SunEditor); hier nur die Einbettung:
   volle Zeilenbreite, Rahmen im App-Stil, Lesemaß fuer den Editorbereich. */
.einst-html { grid-column: 1 / -1; min-width: 0; width: 100%; }
.einst-html-host { max-width: 100%; }
/* SunEditor setzt eigene Rahmen/Radien — auf App-Werte ziehen, damit der Editor
   nicht wie ein Fremdkoerper im Formular sitzt. */
/* Auswahl-Knöpfe (Schriftart/-größe) tragen einen WERT, nicht nur ein Label —
   sie brauchen Platz. Was nicht passt, endet mit Ellipse statt mitten im Wort
   („Schriftgr" mit Chevron war der gemessene Zustand). */
.app-scope .sun-editor .se-btn-select { min-width: 116px; max-width: 148px; }
.app-scope .sun-editor .se-btn-select > span:first-child {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.app-scope .sun-editor .se-btn-select.se-btn-select-font-size { min-width: 92px; max-width: 108px; }
@container drawer (max-width: 760px) {
  .app-scope .sun-editor .se-btn-select { min-width: 88px; max-width: 104px; }
  .app-scope .sun-editor .se-btn-select.se-btn-select-font-size { min-width: 72px; max-width: 84px; }
  .app-scope .sun-editor .se-toolbar { min-width: 0; }
}
/* Dasselbe für die PANE, nicht nur für den Drawer. Der Editor stand dort mit einer
   Mindestbreite aus den Werkzeug-Auswahlfeldern (116px × n) in der Karte und ließ
   sie ab ~1100px Fensterbreite WAAGERECHT SCROLLEN — als einzige Fläche der
   Einstellungen. Kein CSS-Fehler, nur eine Mindestbreite ohne Gegenstück, und
   deshalb bis zur Messung unbemerkt. */
.app-scope .einst-html-host .sun-editor,
.app-scope .einst-html-host .se-toolbar { min-width: 0; max-width: 100%; }
@media (max-width: 1199px) {
  .app-scope .einst-html-host .sun-editor .se-btn-select { min-width: 88px; max-width: 104px; }
  .app-scope .einst-html-host .sun-editor .se-btn-select.se-btn-select-font-size { min-width: 72px; max-width: 84px; }
}

.lod-richtext
.einst-html-host .se-toolbar { border-top-left-radius: var(--radius-md); border-top-right-radius: var(--radius-md); }
.einst-html-host .se-wrapper-inner { font-family: var(--font-sans); }

/* ── Platzhalter-Chip im Editor (`LoD.RichText` mit `chips: true`) ────────────
   `{NAME}` / `{AVATAR}` sind Platzhalter, keine Tippfehler — als roher Text in
   einer Bildzelle sah eine geladene Signatur-Vorlage aus wie ein kaputtes Gerüst
   („mit geladener Vorlage ist noch billiger", Kyle 27.07.).
   Der Chip ist REINE ANZEIGE: `getHtml()` liefert wieder den nackten Platzhalter
   (Round-Trip im Unit-Test bewiesen), gespeichert wird nie ein Chip. */
.rt-ph {
  display: inline-block;
  padding: 0 5px;
  border: 1px dashed var(--lod-darkblue-300, #9fb2cc);
  border-radius: var(--radius-sm, 4px);
  background: var(--lod-darkblue-50, #eef2f8);
  color: var(--lod-darkblue, #1b3a5c);
  font-size: .92em;
  line-height: 1.5;
  white-space: nowrap;
  user-select: none;
}

@media (max-width: 599px) {
  .einst-html-host .se-toolbar { overflow-x: auto; }
}

/* ── Berechtigungs-Fläche (Panel `berechtigungen`) ─────────────────────────────
   Eigene Fläche statt Formularzeilen: Rechtevergabe braucht Personensuche, Avatare
   und Mehrfachauswahl. Self-scoped über `.ber-panel` (Modul-CSS-Regel). */
.ber-panel { display: flex; flex-direction: column; gap: var(--space-4); }
.ber-kopf { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
/* Sicht-Umschaltung: der SSOT `ViewSwitcher` bringt Aussehen und URL-Sync mit — hier nur
   der Platz dafür. Eigene Tab-Knöpfe hatten weder Deeplink noch Zurück-Verhalten. */
.ber-vs { display: inline-flex; }
.ber-suche { margin-left: auto; min-width: 260px; }
.ber-suche input { width: 100%; }

.ber-liste { display: flex; flex-direction: column; }
.app-scope .ber-zeile {
  display: grid; grid-template-columns: 32px minmax(160px, 1.1fr) minmax(0, 2fr) 40px;
  align-items: center; gap: var(--space-3);
  width: 100%; text-align: left; border: 0; background: transparent; cursor: pointer;
  padding: var(--space-2) var(--space-2-5); border-radius: var(--radius-md);
}
.ber-zeile + .ber-zeile { border-top: 1px solid var(--lod-gray-100); }
.app-scope .ber-zeile:hover { background: var(--lod-gray-50); }
.app-scope .ber-zeile:focus-visible { outline: none; box-shadow: var(--lod-shadow-focus); }
.ber-zeile-txt { display: flex; flex-direction: column; min-width: 0; }
.ber-zeile-name { font-weight: var(--fw-medium); color: var(--color-text); }
.ber-zeile-mail { font-size: var(--fs-caption, 12px); color: var(--color-text-muted); overflow: hidden; text-overflow: ellipsis; }
.ber-zeile-chips { display: flex; flex-wrap: wrap; gap: var(--space-1); min-width: 0; }
.ber-zeile-n { font-size: var(--fs-caption, 12px); color: var(--color-text-muted); text-align: right; }

.ber-chip {
  display: inline-flex; align-items: center; padding: 1px var(--space-2);
  border-radius: var(--radius-pill, 999px); background: var(--lod-gray-100);
  color: var(--color-text-muted); font-size: var(--fs-caption, 12px); white-space: nowrap;
}
/* Aus der Azure-Gruppe geerbt — hier nicht änderbar, deshalb sichtbar anders. */
.ber-chip--extern { background: transparent; border: 1px dashed var(--lod-gray-300); }
/* Legende zu den gestrichelten Chips. Zeigt den Chip SELBST als Muster, nicht nur ein
   Wort: der Unterschied IST die Umrandung, und „gestrichelt umrandet" zu lesen ist
   schwerer, als das Muster daneben zu sehen. Erscheint nur, wenn es solche Chips auf der
   Flaeche gibt (Renderer) — nach der Azure-Abloesung verschwindet sie von selbst. */
.ber-legende {
  display: flex; align-items: center; gap: var(--space-2);
  margin: var(--space-3) 0 0; padding-top: var(--space-3);
  border-top: 1px solid var(--color-border-subtle, var(--lod-gray-100));
  font-size: var(--fs-meta, 12px); color: var(--color-text-muted);
}
/* Reichweite als Chip in der Personen-Zeile: erscheint nur über „nur eigene", also nur
   dann, wenn die Person tatsächlich fremde Daten sieht. */
.ber-chip--scope { background: var(--status-info-bg); color: var(--brand-default); }
/* Diese Rolle bringt die Fähigkeit derzeit NICHT mit („nur ausdrücklich"). */
.ber-chip--durchgestrichen { text-decoration: line-through; opacity: .6; }
.ber-chip--faehig { background: var(--lod-darkblue-50, #eef2f7); color: var(--lod-darkblue); }
.ber-chip--warn { background: var(--lod-amber-50, #fff4e5); color: var(--lod-amber-700, #8a5a00); }
.ber-chip--keine { background: transparent; color: var(--lod-gray-400); }

/* ── Sicht „Rollen": MASTER-DETAIL ────────────────────────────────────────────
   Vorher acht Karten untereinander: ~2.500px, davon 942px allein „Management"
   (gemessen 2026-07-31 bei 1800×1100). Zwei Probleme in einem — man sah nie mehr
   als zwei Rollen gleichzeitig, konnte sie also nicht vergleichen, und die
   Fähigkeits-Wand einer einzigen Rolle bestimmte die Höhe der ganzen Fläche.

   Liste links (schmal, gleichförmig, KLEBT beim Scrollen), Detail rechts an fester
   Position. Ein Wechsel tauscht damit nur den rechten Inhalt und verschiebt nichts:
   die Regel „kein Layout-Springen bei Interaktion" ist hier der Grund für die
   Zwei-Spalten-Form und nicht bloss ihr Nebeneffekt. */
.ber-md { display: grid; grid-template-columns: 244px minmax(0, 1fr); gap: var(--space-4); align-items: start; }
.ber-md-liste {
  display: flex; flex-direction: column; gap: 2px;
  position: sticky; top: var(--space-2);
}
.app-scope .ber-md-item {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: 2px;
  width: 100%; text-align: left; cursor: pointer;
  border: 0; background: transparent;
  padding: var(--space-2) var(--space-2-5);
  border-radius: var(--radius-md);
  border-left: 3px solid transparent;
  transition: background var(--motion-fast, 120ms) var(--ease-standard, ease);
}
.app-scope .ber-md-item:hover { background: var(--lod-gray-50); }
.app-scope .ber-md-item:focus-visible { outline: none; box-shadow: var(--lod-shadow-focus); }
/* Die aktive Zeile trägt eine Kante, keine Füllfläche: bei acht gleich langen Zeilen
   ist die Kante das ruhigere Signal, und dunkler Text auf getöntem Grund ist genau
   das Grau-auf-Grau, das hier nicht vorkommen soll. */
.app-scope .ber-md-item.is-aktiv { background: var(--lod-gray-50); border-left-color: var(--lod-darkblue); }
.ber-md-item-kopf { display: flex; align-items: baseline; gap: var(--space-1-5); min-width: 0; }
.ber-md-item-titel {
  font-size: var(--fs-body, 14px); font-weight: var(--fw-semibold); color: var(--color-text);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ber-md-item.is-aktiv .ber-md-item-titel { color: var(--lod-darkblue); }
.ber-md-item-meta { font-size: var(--fs-caption, 12px); color: var(--color-text-muted); }

.ber-md-detail { padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-3); }
/* Beschreibung der Rolle und die „Enthält"-Summe: gedämpfter Fliesstext neben dem
   Titel. Beide Regeln standen im ausgebauten Karten-Block — ohne sie rendern sie in
   Erbgrösse und -farbe, also so schwer wie die Überschrift. Genau der Fehlermodus, den
   CSS nie meldet: die Klasse ist da, sie tut nur nichts. */
.ber-rolle-txt { margin: 0; font-size: var(--fs-body, 14px); color: var(--color-text-muted); }
.ber-enthaelt-summe { font-size: var(--fs-meta, 12px); color: var(--color-text-muted); }
/* Destruktiv = nicht rückholbar (z.B. Fremde Zeiteinträge löschen): ein roter Punkt VOR
   dem Titel. Nur der Punkt — eine rote Chip-Fläche würde 77 blaue und einen roten Chip
   zu einem Alarm-Muster machen, das keines ist. Dieselbe Marke trägt die Zeile im
   Fähigkeiten-Reiter (`.ber-fk-titel--destruktiv`); zwei verschiedene Marken für
   dieselbe Aussage lernt niemand. */
.ber-chip--destruktiv::before {
  content: ''; display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--status-danger-fg); margin-right: var(--space-1); vertical-align: middle;
}
.ber-det-kopf { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.ber-det-titel { font-size: var(--fs-section, 16px); font-weight: var(--fw-semibold); }
.ber-det-akt { margin-left: auto; display: inline-flex; gap: var(--space-2); }
/* Eine Detail-Zeile: Label in fester Bahn, Wert daneben. Dieselbe Bahn wie die
   Feldzeilen der Settings-Fläche — der Wechsel zwischen generischer Seite und
   diesem Panel soll sich nicht wie zwei Produkte anfühlen. */
.ber-det-block {
  display: grid; grid-template-columns: 96px minmax(0, 1fr);
  gap: var(--space-2) var(--space-3); align-items: baseline;
  padding: var(--space-2) 0;
}
.ber-det-block + .ber-det-block { border-top: 1px solid var(--color-border-light); }
.ber-det-wert { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); min-width: 0; }
.ber-det-block--scope { align-items: center; }
.ber-det-block--abd { border-bottom: 1px solid var(--color-border-light); }
/* Bereiche, die diese Rolle ÖFFNET (Tab-Sichtbarkeit). Bewusst anders getönt als die
   Fähigkeits-Chips: „Zugang zu einem Bereich" und „einzelne Handlung" sind zwei
   verschiedene Aussagen, und sie stehen auf derselben Karte untereinander. */
.ber-chip--bereich {
  background: var(--status-info-bg); color: var(--brand-default); font-weight: var(--fw-medium);
}

/* ── Abdeckung „x von y" ──────────────────────────────────────────────────────
   Die Zahl, die der Fläche gefehlt hat. „Enthält 77 Fähigkeiten in 21 Bereichen"
   ist eine Summe; sie sagt nicht, wie WEIT die Rolle in einen Bereich reicht.
   Zwischen „Personal 6 von 6" und „Personal 1 von 6" liegt der ganze Unterschied,
   und beides sah vorher gleich aus. Der Balken trägt die Antwort, die Chips
   darunter die Begründung — deshalb bleiben sie sichtbar statt hinter einem
   Aufklapper, der bei jedem Klick alles darunter verschöbe. */
.ber-abdeckung { display: flex; flex-direction: column; }
.ber-abd { padding: var(--space-2) 0; }
.ber-abd + .ber-abd { border-top: 1px solid var(--color-border-light); }
.ber-abd-kopf {
  display: grid; grid-template-columns: 168px 72px auto;
  align-items: center; gap: var(--space-2) var(--space-3);
  margin-bottom: var(--space-1-5);
}
.ber-abd-name {
  font-size: var(--fs-meta, 12px); font-weight: var(--fw-semibold); color: var(--color-text-muted);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ber-abd-zahl {
  font-size: var(--fs-meta, 12px); font-variant-numeric: tabular-nums; color: var(--lod-gray-400);
}
/* Vollständige Abdeckung ist die Aussage „hier darf die Rolle alles" — sie verdient
   Gewicht, aber keine Farbe: rot/grün wäre eine Wertung, die niemand getroffen hat. */
.ber-abd-zahl.is-voll { color: var(--color-text-muted); font-weight: var(--fw-semibold); }
.ber-abd-chips { display: flex; flex-wrap: wrap; gap: var(--space-1-5); min-width: 0; }
/* Die Füllbreite ist ein DATUM und kommt als Custom-Property vom Renderer — ein
   Inline-`width` wäre ein Layout-Property im Markup (Repo-Regel). */
.ber-meter {
  display: block; height: 4px; border-radius: var(--radius-pill, 999px);
  background: var(--lod-gray-200); overflow: hidden;
}
.ber-meter-fill {
  display: block; height: 100%; width: var(--ber-fuell, 0%);
  border-radius: inherit; background: var(--lod-darkblue-300, #7f9cbb);
}
.ber-meter.is-voll .ber-meter-fill { background: var(--lod-darkblue); }
.ber-md-item .ber-meter { margin-top: var(--space-1); }

.ber-label { font-size: var(--fs-caption, 12px); font-weight: var(--fw-semibold); color: var(--color-text-muted); min-width: 62px; }
.ber-badge { font-size: 11px; font-weight: var(--fw-semibold); text-transform: uppercase; letter-spacing: .04em;
  padding: 1px var(--space-1-5); border-radius: var(--radius-sm); background: var(--lod-gray-100); color: var(--lod-gray-500); }
.ber-badge--eigen { background: var(--lod-darkblue-50, #eef2f7); color: var(--lod-darkblue); }
/* „nur intern" = LoDs eigenes Geschäft, auf einem Kunden-Stamp gar nicht angeboten.
   Bewusst NEUTRAL getönt und nicht warnend: es ist eine Herkunfts-Angabe, kein Problem —
   ein Amber-Badge wie bei „nur ausdrücklich" läse sich als Handlungsbedarf. */
.ber-badge--intern { background: var(--lod-gray-100); color: var(--lod-gray-500); }
/* Der Zusatz „· n davon nur intern" hängt an der Summenzeile und darf sie nicht
   überstimmen — dieselbe Größe, nur leiser. */
.ber-enthaelt-intern { margin-left: var(--space-1); color: var(--lod-gray-400); }
/* Reichweite je Bereich — Segment-Schalter direkt im Rollen-Detail. */
.ber-scope { display: inline-flex; align-items: center; gap: var(--space-2); }
.ber-scope-name { font-size: var(--fs-caption, 12px); color: var(--color-text-muted); }
.ber-seg { display: inline-flex; background: var(--lod-gray-100); padding: 2px; border-radius: var(--radius-md); }
.app-scope .ber-seg-btn {
  border: 0; background: transparent; cursor: pointer;
  padding: 2px var(--space-2); border-radius: var(--radius-sm);
  font-size: var(--fs-caption, 12px); font-weight: var(--fw-medium); color: var(--color-text-muted);
  transition: background var(--motion-fast, 120ms) var(--ease-standard, ease), color var(--motion-fast, 120ms) var(--ease-standard, ease);
}
.app-scope .ber-seg-btn:hover { color: var(--color-text); }
/* Token heisst `--shadow-2` (tokens.css) — `--lod-shadow-2` existiert NICHT und fiel
   still auf einen hartcodierten Schatten zurück. */
.app-scope .ber-seg-btn.is-aktiv { background: var(--lod-white, #fff); color: var(--lod-darkblue); font-weight: var(--fw-semibold); box-shadow: var(--shadow-2); }
.app-scope .ber-seg-btn:focus-visible { outline: none; box-shadow: var(--lod-shadow-focus); }

.ber-stapel { display: inline-flex; align-items: center; }
.ber-stapel-av { margin-left: -6px; }
.ber-stapel-av:first-child { margin-left: 0; }
.ber-stapel-rest { margin-left: var(--space-1-5); font-size: var(--fs-caption, 12px); color: var(--color-text-muted); }
.ber-neu-rolle { align-self: flex-start; }
/* Abgrenzung der drei Rechte-Mechaniken (Reichweite / Zustaendigkeit / Gast-Rechte).
   Steht unter den Rollenkarten, weil dort der Eindruck entsteht, die Reichweite gelte
   app-weit — sie gilt fuer die Personaldaten. */
.ber-abgrenzung { margin-top: var(--space-2); padding-top: var(--space-2);
  border-top: 1px dashed var(--lod-gray-200); font-size: 13px; }


.ber-hzeile {
  display: grid; grid-template-columns: minmax(140px, 1fr) auto minmax(0, 1.6fr) auto;
  align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-2-5);
}
.ber-hzeile + .ber-hzeile { border-top: 1px solid var(--lod-gray-100); }
.ber-hzeile-titel { font-weight: var(--fw-medium); }
.ber-hzeile-zahl { display: inline-flex; gap: var(--space-1); }
.ber-hzeile-namen { font-size: var(--fs-caption, 12px); color: var(--color-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ber-hinweis { margin: 0 0 var(--space-2); font-size: var(--fs-body, 14px); color: var(--color-text-muted); }
.ber-leer, .ber-leer-inline { color: var(--lod-gray-400); font-size: var(--fs-body, 14px); }

/* Drawer-Innenleben */
.ber-dr { display: flex; flex-direction: column; gap: var(--space-4); }
.ber-dr-grp h4 { margin: 0 0 var(--space-1); font-size: var(--fs-card-title, 14px); font-weight: var(--fw-semibold); }
.ber-dr-hint { margin: 0 0 var(--space-2); font-size: 13px; color: var(--color-text-muted); }
/* ★ Die ganze Zeile schaltet (Delegation im Panel-JS). Vorher stand hier `cursor: pointer`
   ohne Klick-Handler: die Zeile SAH klickbar aus, reagierte aber nur auf den 40px-Schalter.
   Der Hover macht die Fläche jetzt auch sichtbar aktiv. */
.ber-dr-row { display: flex; align-items: flex-start; gap: var(--space-3); padding: var(--space-2) var(--space-1); cursor: pointer; border-radius: var(--radius-sm); }
.ber-dr-row:hover { background: var(--lod-gray-50); }
.ber-dr-row.is-fix:hover { background: transparent; }
.ber-dr-row + .ber-dr-row { border-top: 1px solid var(--lod-gray-100); }
/* Fix = kommt aus einer Fremdquelle und ist hier nicht änderbar. */
.ber-dr-row.is-fix { cursor: default; opacity: .75; }
.ber-dr-txt { display: flex; flex-direction: column; gap: 2px; font-size: var(--fs-body, 14px); }
.ber-dr-txt span { font-size: 13px; color: var(--color-text-muted); }
.ber-dr-quelle { font-style: italic; }
.ber-dr-av { flex-shrink: 0; }
/* Gestapeltes Feld (Label über Eingabe). Die Eingabe ist ein `.app-drawer-input`;
   dessen `flex: 1` wirkt in diesem SPALTEN-Flex auf die HÖHE — ohne die
   `min-height`-Absicherung im Drawer-Primitive (drawer-fields.css) fiel das Feld
   auf 19px Inhaltshöhe zusammen. `align-items: stretch` hält es zusätzlich auf
   voller Breite, damit ein Bezeichnungsfeld nicht schmaler ist als das darunter. */
.ber-dr-feld { display: flex; flex-direction: column; align-items: stretch; gap: var(--space-1); }
.ber-dr-feld > span { font-size: 13px; font-weight: var(--fw-medium); }
/* Zähler im Gruppen-Kopf („2 von 8") — rechts, unaufdringlich. */
.ber-dr-grp h4 { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.ber-dr-zahl { font-size: 12px; font-weight: var(--fw-regular); color: var(--color-text-muted); white-space: nowrap; }
/* ── Bereichs-Gruppe im Rollen-Drawer: Klappfläche ───────────────────────────
   8 Produkt-Rollen + 78 Faehigkeiten = 86 Schalter, gemessen **7.658px** Scrollhoehe in
   einem 560px breiten Drawer (2026-07-31). Dieselbe Krankheit wie die alte Rollenkarte,
   eine Ebene tiefer — und dieselbe Heilung wie im Faehigkeiten-Reiter, damit die zwei
   Flaechen nicht wieder auseinanderlaufen. Zugeklappt traegt die Zeile die Zahl
   „n von m", also genau das, was man an einer geschlossenen Gruppe braucht.
   Kein Rahmen, keine Toenung: der Kopf ist eine Ueberschrift, die man druecken kann. */
.app-scope .ber-dr-sub {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%; margin: var(--space-3) 0 var(--space-1); padding: var(--space-1) 0;
  background: none; border: 0; cursor: pointer; text-align: left;
  font-size: 12px; font-weight: var(--fw-semibold);
  text-transform: uppercase; letter-spacing: .04em; color: var(--color-text-muted);
}
.app-scope .ber-dr-sub:hover { color: var(--color-text); }
.app-scope .ber-dr-sub:focus-visible { outline: none; box-shadow: var(--lod-shadow-focus); }
.ber-dr-sub-chev { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; flex: 0 0 auto;
  transition: transform var(--motion-fast, 120ms) var(--ease-standard, ease); }
.ber-dr-sub-chev img { width: 16px; height: 16px; opacity: .55; }
/* Gedreht wird der ZUGEKLAPPTE Zustand, damit das Icon im Ruhezustand seiner Datei
   entspricht (chevron_down) — dieselbe Entscheidung wie bei `.ber-fk-gruppe-chev`. */
.ber-dr-sub:not(.is-offen) .ber-dr-sub-chev { transform: rotate(-90deg); }
.ber-dr-sub-titel { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ber-dr-sub-zahl { margin-left: auto; font-variant-numeric: tabular-nums; letter-spacing: 0;
  text-transform: none; font-weight: var(--fw-regular); color: var(--lod-gray-400); }
/* ── Bereichs-Kopf im Fähigkeiten-Reiter: Klappfläche ────────────────────────
   65 Karten à 221px = 20.901px Seitenhöhe (gemessen 30.07.). Zugeklappt startet die
   Fläche mit 19 Zeilen statt mit einem Endlos-Band; die Zahl rechts sagt, was drin
   ist. Kein `border`, keine Tönung: der Kopf ist eine Überschrift, die man drücken
   kann — kein Knopf, der wie ein Formularelement aussieht (dieselbe Entscheidung wie
   beim Sektionskopf der Settings-Karten). */
.ber-fk-gruppe {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%; margin: var(--space-4) 0 var(--space-1); padding: var(--space-1) 0;
  background: none; border: 0; cursor: pointer; text-align: left;
}
.ber-fk-gruppe:hover .ber-fk-gruppe-titel { color: var(--color-text); }
.ber-fk-gruppe-titel {
  font-size: 12px; font-weight: var(--fw-semibold);
  text-transform: uppercase; letter-spacing: .04em; color: var(--color-text-muted);
}
.ber-fk-gruppe-chev {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; flex: 0 0 auto;
  transition: transform var(--motion-fast, .12s) ease;
}
.ber-fk-gruppe-chev img { width: 16px; height: 16px; opacity: .55; }
/* Zu = Pfeil nach rechts, offen = nach unten. Gedreht wird der ZUGEKLAPPTE Zustand,
   damit das Icon im Ruhezustand seiner Datei entspricht (chevron_down). */
.ber-fk-gruppe:not(.is-offen) .ber-fk-gruppe-chev { transform: rotate(-90deg); }
/* „über Rolle X" — diese Fähigkeit kommt schon aus einer gewählten Produkt-Rolle.
   Rechts in der Zeile, damit die Spalte der Titel ruhig bleibt. */
.ber-dr-deckung { margin-left: auto; align-self: center; flex-shrink: 0; padding: 2px var(--space-2);
  border-radius: var(--radius-sm); background: var(--status-info-bg); color: var(--brand-default);
  font-size: 11px; font-weight: var(--fw-semibold); white-space: nowrap; }
.ber-avatar-fallback {
  display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px;
  border-radius: 50%; background: var(--lod-gray-200); font-size: 12px; font-weight: var(--fw-semibold);
}

/* ── Gruppierung + Fenster der Personen-Liste ─────────────────────────────────
   „Ohne Sonderrechte" ist die Mehrheit und beantwortet keine Prüf-Frage — zugeklappt.
   Das Fenster („Weitere N anzeigen") hält die Fläche auch bei mehreren hundert
   Mitarbeitern reaktionsfähig. */
.ber-gruppe { margin-top: var(--space-2); border-top: 1px solid var(--lod-gray-100); }
.app-scope .ber-gruppe-kopf {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%; padding: var(--space-2) var(--space-2-5); border: 0; background: transparent;
  cursor: pointer; text-align: left;
  font-size: var(--fs-caption, 12px); font-weight: var(--fw-semibold);
  text-transform: uppercase; letter-spacing: .04em; color: var(--color-text-muted);
}
.app-scope .ber-gruppe-kopf:hover { color: var(--color-text); }
.app-scope .ber-gruppe-kopf:focus-visible { outline: none; box-shadow: var(--lod-shadow-focus); }
.ber-gruppe-kopf .ui-ico { transition: transform var(--motion-fast, 120ms) var(--ease-standard, ease); }
.ber-gruppe.is-offen .ber-gruppe-kopf .ui-ico { transform: rotate(90deg); }
.ber-mehr { align-self: flex-start; margin-top: var(--space-1); }

/* ── Reichweite: Herkunft + Zurücksetzen ──────────────────────────────────────
   „Alle" sieht gleich aus, egal ob Vorgabe, geerbt oder fest gesetzt — nur im letzten
   Fall ändert Zurücksetzen etwas. Deshalb steht die Herkunft daneben. */
.ber-scope-herkunft { font-size: 11px; color: var(--lod-gray-400); font-style: italic; }
.app-scope .ber-scope-reset {
  border: 0; background: transparent; cursor: pointer; padding: 0 var(--space-1);
  font-size: 11px; color: var(--brand-default); text-decoration: underline;
}
.app-scope .ber-scope-reset:focus-visible { outline: none; box-shadow: var(--lod-shadow-focus); }

/* ── Sicht „Fähigkeiten" (wer darf X): ZEILEN statt Karten ────────────────────
   Vorher 221px hohe Karten je Fähigkeit — bei 78 Einträgen rund 20.900px, weshalb
   die Bereiche überhaupt zugeklappt starten. Zugeklappt zeigte die Fläche dann
   21 Zeilen mit NUR einer Zahl daneben (gemessen 675 Zeichen Text auf dem ganzen
   Reiter): um „wer darf fremde Zeiteinträge löschen?" zu beantworten, musste man
   den Bereich raten, aufklappen und scannen.

   Eine Handlung ist eine Zeile mit vier festen Bahnen — Titel, Rollen, Personen,
   Schalter. Die Bahnen fluchten über alle Zeilen einer Gruppe; das ist der ganze
   Unterschied zwischen „Liste von Karten" und „Tabelle, die man überfliegt". */
.ber-fk-tab { display: flex; flex-direction: column; margin-bottom: var(--space-4); }
/* ★ DIE LETZTEN ZWEI SPUREN SIND FEST, und das ist kein Feinschliff. `.ber-fk-th` und
   `.ber-fk-tr` sind GETRENNTE Grid-Container (kein Subgrid), also bemisst sich jede
   `auto`-Spur am eigenen Inhalt: im Kopf ist die Aktions-Zelle LEER (0px), in der Zeile
   trägt sie den „Externe & Gruppen …"-Knopf (~130px). Damit bekommen die `fr`-Spuren im
   Kopf mehr Platz als in der Zeile, und jede Überschrift steht ein Stück rechts von
   ihrer Spalte — gemessen 111px Versatz bei „Wer darf". Genau derselbe Fehler wie
   2026-07-30 an `.einst-kat-head`; dort war die Lehre schon aufgeschrieben. */
.ber-fk-th, .ber-fk-tr {
  display: grid;
  grid-template-columns: minmax(200px, 2.2fr) minmax(120px, 1.2fr) minmax(110px, 1fr) 132px 132px;
  gap: var(--space-3); align-items: center;
  padding: var(--space-2) var(--space-2-5);
}
/* Der Spaltenkopf ist eine Beschriftung, keine getönte Bahn: ein graues Band mit
   dunklem Text ist genau das Grau-auf-Grau, das hier nicht vorkommt. Getrennt wird
   über eine Haarlinie. */
.ber-fk-th {
  font-size: 11px; font-weight: var(--fw-semibold); text-transform: uppercase;
  letter-spacing: .04em; color: var(--lod-gray-400);
  border-bottom: 1px solid var(--color-border-light); padding-bottom: var(--space-1-5);
}
.ber-fk-th-streng { text-align: center; }
.ber-fk-tr + .ber-fk-tr { border-top: 1px solid var(--lod-gray-100); }
.ber-fk-tr:hover { background: var(--lod-gray-50); }
.ber-fk-td { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1-5); min-width: 0; }
.ber-fk-td--titel { flex-direction: column; align-items: flex-start; gap: 2px; }
.ber-fk-td--streng { justify-content: center; }
.ber-fk-td--akt { justify-content: flex-end; }
.ber-fk-titel { font-size: var(--fs-body, 14px); font-weight: var(--fw-medium); color: var(--color-text); }
/* Destruktiv = nicht rückholbar. Derselbe rote Punkt wie am Fähigkeits-Chip — die
   Marke muss in beiden Sichten dieselbe sein, sonst lernt man sie nicht. */
.ber-fk-titel--destruktiv::before {
  content: ''; display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--status-danger-fg); margin-right: var(--space-1); vertical-align: middle;
}
.ber-fk-txt { font-size: var(--fs-meta, 12px); color: var(--color-text-muted); }
.ber-fk-namen { font-size: var(--fs-caption, 12px); color: var(--color-text-muted); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* Die Aktions-Spalte ist nur bei Bedarf sichtbar — ein Knopf in jeder der 78 Zeilen
   wäre 78-mal dieselbe Einladung. Bei Tastatur-Fokus bleibt er erreichbar. */
.ber-fk-td--akt > .app-cta-btn { opacity: 0; transition: opacity var(--motion-fast, 120ms) var(--ease-standard, ease); }
.ber-fk-tr:hover .ber-fk-td--akt > .app-cta-btn,
.ber-fk-td--akt > .app-cta-btn:focus-visible { opacity: 1; }
.ber-badge--streng { background: var(--lod-amber-50, #fff4e5); color: var(--lod-amber-700, #8a5a00); }

/* Zugeklappte Bereichszeile mit AUSSAGE statt nur einer Zahl: „nur ausdrücklich"
   und „darf niemand" sind genau das, wonach ein Prüfer sucht — und waren vorher
   nur zu finden, indem man jede der 21 Gruppen einzeln aufklappte. */
.ber-fk-gruppe-meta {
  margin-left: auto; display: inline-flex; align-items: center; gap: var(--space-1-5);
  font-size: var(--fs-meta, 12px); font-variant-numeric: tabular-nums; color: var(--lod-gray-400);
}
.ber-fk-meta-sep { color: var(--lod-gray-300); }
.ber-fk-meta-streng { color: var(--lod-amber-700, #8a5a00); }
.ber-fk-meta-ohne { color: var(--color-text-muted); }

/* ── Sicht „Herkunft": Schrittfolge ───────────────────────────────────────────
   Die Ablösung ist ein Ablauf (übernehmen → prüfen → umlegen), kein Formular. Der
   Schalter sitzt deshalb IM dritten Schritt und nicht in einer anderen Sektion. */
.ber-schritte { list-style: none; margin: 0 0 var(--space-4); padding: 0; display: flex; flex-direction: column; gap: var(--space-3); }
.ber-schritt {
  display: flex; flex-direction: column; gap: var(--space-1);
  padding: var(--space-3) var(--space-4);
  border-left: 3px solid var(--lod-gray-200); border-radius: var(--radius-sm);
  background: var(--lod-gray-50);
}
.ber-schritt > b { font-size: var(--fs-body, 14px); }
.ber-schritt > span { font-size: 13px; color: var(--color-text-muted); }
.ber-schritt.is-offen { border-left-color: var(--lod-amber-700, #8a5a00); }
.ber-schritt.is-fertig { border-left-color: var(--status-success-fg); }
.ber-schritt-akt { display: flex; align-items: flex-start; gap: var(--space-3); margin-top: var(--space-1); }

/* ── Sicht „Protokoll" ────────────────────────────────────────────────────────
   Zeit links, Vorgang rechts: beim Nachweis liest man chronologisch. */
.ber-pzeile {
  display: grid; grid-template-columns: 130px minmax(0, 1fr);
  gap: var(--space-3); padding: var(--space-2) var(--space-2-5);
}
.ber-pzeile + .ber-pzeile { border-top: 1px solid var(--lod-gray-100); }
.ber-pzeile-zeit { font-size: var(--fs-caption, 12px); color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
.ber-pzeile-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ber-pzeile-kopf { font-weight: var(--fw-medium); }
.ber-pzeile-diff { font-size: 13px; color: var(--color-text-muted); }
.ber-pzeile-diff i { font-style: normal; text-decoration: line-through; opacity: .7; }

/* Drawer: Suchfeld über einer langen Auswahlliste + Wirkungs-Zusammenfassung. */
.ber-dr-suche { display: block; }
.ber-dr-suche input { width: 100%; }
.ber-dr-liste { display: flex; flex-direction: column; }
.ber-dr-wirkung {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-1-5) 0; font-size: var(--fs-body, 14px);
}
.ber-dr-wirkung + .ber-dr-wirkung { border-top: 1px solid var(--lod-gray-100); }
.ber-dr-wirkung > span { color: var(--color-text-muted); }
/* Verlauf DIESER Person im Drawer — dieselbe Zeit/Diff-Sprache wie die Protokoll-Sicht,
   nur schmaler (der Drawer hat keine 130px-Zeitspalte übrig). */
.ber-dr-verlauf { display: flex; flex-direction: column; gap: 2px; padding: var(--space-1-5) 0; }
.ber-dr-verlauf + .ber-dr-verlauf { border-top: 1px solid var(--lod-gray-100); }

/* Notebook/Tablet: die Chip-Spalte darf schrumpfen, Mail-Zeile entfällt. */
@media (max-width: 1399px) {
  .ber-zeile { grid-template-columns: 32px minmax(140px, 1fr) minmax(0, 1.4fr) 36px; }
  /* Das Suchfeld darf auf dem Notebook schmaler werden, statt die Tab-Leiste zu drücken. */
  .ber-suche { min-width: 200px; }
}
@media (max-width: 999px) {
  /* ★ Die Chips bleiben. Sie wurden hier früher ausgeblendet — damit fehlte auf dem Tablet
     genau die Information, wegen der man die Liste öffnet (welche Rollen hat die Person).
     Stattdessen wandern sie unter den Namen und die Zeile wird zweizeilig. */
  .ber-zeile { grid-template-columns: 32px minmax(0, 1fr) auto; grid-template-areas: "av txt n" ". chips chips"; }
  .ber-zeile-av { grid-area: av; }
  .ber-zeile-txt { grid-area: txt; }
  .ber-zeile-n { grid-area: n; }
  .ber-zeile-chips { grid-area: chips; margin-top: var(--space-1); }
  .ber-hzeile { grid-template-columns: 1fr auto; }
  .ber-hzeile-namen { display: none; }
  .ber-suche { margin-left: 0; width: 100%; }
  /* Ab Tablet bricht die Reichweite unter das Label statt das Detail zu sprengen. */
  .ber-det-block--scope { align-items: flex-start; }
  .ber-scope { flex-wrap: wrap; }
  .ber-pzeile { grid-template-columns: minmax(0, 1fr); }
  /* Master-Detail hat unter ~1000px keine zwei Spalten mehr: die Liste würde die
     244px behalten und dem Detail unter 400px lassen. Sie wird zur waagerecht
     scrollenden Auswahl-Leiste ÜBER dem Detail — die Auswahl bleibt sichtbar, das
     Detail bekommt die volle Breite, und ein Wechsel verschiebt weiterhin nichts. */
  .ber-md { grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
  .ber-md-liste {
    position: static; flex-direction: row; gap: var(--space-1);
    overflow-x: auto; padding-bottom: var(--space-1);
  }
  .app-scope .ber-md-item {
    flex: 0 0 auto; max-width: 220px;
    border-left: 0; border-bottom: 3px solid transparent; border-radius: var(--radius-sm);
  }
  .app-scope .ber-md-item.is-aktiv { border-bottom-color: var(--lod-darkblue); }
  .ber-md-item .ber-meter { display: none; }
  .ber-neu-rolle { flex: 0 0 auto; }
  /* Die Personen-Spalte fällt zuerst: „wer darf" ist auf schmalem Schirm die
     Nachfrage, „welche Handlung" und der Schalter sind die Antwort. */
  .ber-fk-th, .ber-fk-tr { grid-template-columns: minmax(0, 2fr) minmax(0, 1.2fr) 108px 108px; }
  .ber-fk-th > :nth-child(3), .ber-fk-td:nth-child(3) { display: none; }
}
@media (max-width: 1399px) {
  .ber-seg { flex-wrap: nowrap; }
  .ber-abd-kopf { grid-template-columns: 140px 64px auto; }
}
/* ★ MIT UNTERGRENZE. Dieser Block steht in der Datei NACH dem 999px-Block, und beide
   greifen unterhalb von 1000px — ohne `min-width` gewinnt hier die spätere Regel und
   die Liste bliebe auch auf dem Telefon eine 208px-Spalte. Genau so gemessen: bei
   420px war `.ber-md-liste` 208px breit, die 220px-Einträge liefen heraus und der
   Rumpf wuchs auf 468px in einem 354px-Fenster. Nichts daran wirft — man sieht es
   nur als waagerechten Scroll. */
@media (min-width: 1000px) and (max-width: 1399px) {
  /* Notebook: die Liste gibt zuerst nach, das Detail trägt den Inhalt. Die
     Bereichs-Bahn der Abdeckung schrumpft mit, sonst bleibt für die Chips zu wenig. */
  .ber-md { grid-template-columns: 208px minmax(0, 1fr); gap: var(--space-3); }
}
@media (max-width: 599px) {
  .ber-vs { width: 100%; overflow-x: auto; }
  .ber-det-akt { margin-left: 0; width: 100%; }
  /* Auf dem Telefon steht das Label über seinem Wert — 96px Bahn plus Chips ergeben
     sonst zwei Zeichen je Zeile. */
  .ber-det-block { grid-template-columns: minmax(0, 1fr); gap: var(--space-1); }
  .ber-abd-kopf { grid-template-columns: minmax(0, 1fr) auto; }
  .ber-abd-kopf .ber-meter { grid-column: 1 / -1; order: 3; }
  /* Die Rollen-Spalte fällt als zweite: der Schalter muss erreichbar bleiben. */
  .ber-fk-th, .ber-fk-tr { grid-template-columns: minmax(0, 1fr) 88px; }
  .ber-fk-th > :nth-child(2), .ber-fk-td:nth-child(2) { display: none; }
  .ber-fk-th > :nth-child(5), .ber-fk-td--akt { display: none; }
  /* Der Segment-Schalter darf nicht schrumpfen, bis die Stufen unlesbar werden —
     lieber der Bereichsname über die volle Breite und der Schalter darunter. */
  .ber-scope { flex-direction: column; align-items: flex-start; gap: var(--space-1); width: 100%; }
  .ber-seg { width: 100%; }
  .app-scope .ber-seg-btn { flex: 1; justify-content: center; }
}

/* Externe Zugänge in der Berechtigungs-Fläche (ehemals Admin-Tab). Die Liste selbst
   bringt ihre eigenen Styles aus dem Admin-Bereich mit — hier nur der Kopf. */
.ber-ext-kopf { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-3); }
.ber-ext-kopf .ber-hinweis { margin: 0; flex: 1; min-width: 220px; }
@media (max-width: 599px) { .ber-ext-kopf { flex-direction: column; align-items: stretch; } }

/* ── Abrechnungs-Artikel & -Preise (Panel `abrechnung-artikel`) ─────────────────
   Die Fläche kam aus dem Abrechnung-Tab (Karten mit Hint-Text unter jedem Feld) und
   spricht hier die Sprache der Settings-Zeile: `LoD.SettingsRow` liefert Label-Bahn,
   ⓘ-Karte, Aktions-Bahn und Control-Kante — Speichern passiert bei Änderung wie
   überall auf der Fläche. Eigene Regeln nur da, wo die Zeile es nicht wissen kann:
   die Bahnbreite. Wurzelklasse setzt das Panel-JS. */
.abrart { display: block; }
/* KEINE eigene Bahnbreite mehr. Hier stand `--set-ctrl: 380px` (und 300px im
   Tablet-Band), weil die Control-Bahn der Zeile fest war und eine Artikel-Pille
   („DL-CONSULTING — Consulting-/Projektstunde") in der Standard-Bahn mitten im Wort
   abriss. Seit 2026-07-29 ist die Bahn `1fr` und der Slot füllt sie (Regel unten) —
   damit ist die Pille breiter als je zuvor, ohne Sonderwert. */
/* Der Slot ist ein eigener Knoten, den das Modul nicht kennt (es behandelt
   `input/select/textarea`). Regel 1 holt für den Slot dieselbe Behandlung;
   `min-width: 0` ist der wichtige Teil, sonst sprengt eine lange
   Artikel-Bezeichnung die Spalte statt zu kürzen.
   Regel 2 gilt den Controls IM Slot: bei Eingabefeldern umschließt der Slot sein Control,
   beim Artikel-Picker IST er das Trigger-Element (AsyncPicker hängt seine Klassen an den
   übergebenen Knoten) — zwei Fälle, zwei Zeilen. */
.app-scope .abrart .set-row-ctrl > .abrart-slot { flex: 1 1 auto; width: 100%; min-width: 0; max-width: none; }
.app-scope .abrart .abrart-slot > .app-drawer-input,
.app-scope .abrart .abrart-slot > .app-drawer-number-wrap { width: 100%; min-width: 0; }
/* Dormanter Zustand (503/403): das Banner IST der Inhalt der Sektion, deshalb ohne
   zusätzlichen Außenabstand (die Sektion bringt ihr Polster mit). */
.abrart-state { margin: 0; }
.abrart-state strong { display: block; margin-bottom: var(--space-1); }

/* Notebook/Tablet: nichts zu tun — die Zeile schrumpft ihre Label-Bahn selbst und
   der Slot folgt der 1fr-Bahn. */
/* Mobile: Control unter das Label (wie `.set-row--stapel`) — 300px Bahn neben einem
   Label passen auf 360px Viewport nicht mehr. */
@media (max-width: 599px) {
  .abrart .set-row { grid-template-columns: minmax(0, 1fr) var(--set-aktionen); }
  .abrart .set-row > .set-row-ctrl { grid-column: 1 / -1; grid-row: 2; margin-top: var(--space-2); }
  .abrart .set-row > .set-row-aktionen { align-self: start; }
}

/* ── Tag/Monat-Paar (Feldtyp 'tagmonat') ─────────────────────────────────────
   Zwei Auswahlen in EINER Control-Bahn: Tag schmal, Monat nimmt den Rest. Vorher
   war das ein Textfeld mit „(MM-TT)" im Label und „12-20" als Wert — ein Format,
   das der Kunde erraten musste (Kyle 27.07.: „super lächerlich"). Ein Datumsfeld
   wäre falsch: der Tag gilt JEDES Jahr, ein Jahr im Feld wäre eine Lüge. */
.einst-tagmonat { display: grid; grid-template-columns: 84px minmax(0, 1fr); gap: var(--space-2); min-width: 0; }
.app-scope .einst-tagmonat .select[data-cs-trigger] { width: 100%; min-width: 0; height: 32px; }
@media (max-width: 999px) {
  .app-scope .einst-tagmonat .select[data-cs-trigger] { height: 36px; }
}
@media (max-width: 599px) {
  .app-scope .einst-tagmonat .select[data-cs-trigger] { height: 40px; }
}

/* Variablen-Leiste unter einem EINZEILIGEN Feld: rechts, an der Control-Kante.
   Links unter dem Label stand sie 1200px vom Feld entfernt — Label(links) →
   Feld(rechts) → „Variable einfügen"(links) war ein Zickzack über die Karte. */
.einst-var-host--kompakt { display: flex; justify-content: flex-end; }
.einst-var-host--kompakt .tvar-leiste { padding-top: var(--space-1); }
@media (max-width: 999px) {
  /* Gestapelte Zeile: das Feld liegt sowieso links — dann auch die Leiste. */
  .einst-var-host--kompakt { justify-content: flex-start; }
}

/* ── Blatt-Optik für E-Mail-Inhalte (Signatur, Notiz-Text, Dokument-Rahmen) ───
   Der Editor ist so breit wie die Karte (~1800px), der Inhalt einer Signatur aber
   ~520px. Ergebnis war eine kleine Tabelle links in einer weißen Fläche mit 1200px
   Leerraum daneben — „mit geladener Vorlage ist noch billiger" (Kyle 27.07.).
   Jetzt liegt der bearbeitbare Bereich als BLATT auf getönter Fläche, in der Breite,
   die die Mail später hat. Dieselbe Sprache wie die Brief-Vorschau der
   Projektaufnahme (`pauf-mail-letter`). */
/* Spezifitaet bewusst hoch (0,4,0): das Vendor-Stylesheet stylt denselben Knoten
   ueber `.sun-editor .se-wrapper .se-wrapper-inner` und gewinnt sonst — gemessen
   blieb das Blatt bei voller Breite stehen. */
.einst-html { --einst-blatt: 700px; }
.einst-html .sun-editor .se-wrapper { background: var(--lod-gray-50, #f7f8fa); }
.einst-html .sun-editor .se-wrapper .se-wrapper-inner {
  max-width: var(--einst-blatt); margin: var(--space-4) auto;
  background: #fff;
  border: 1px solid var(--lod-border-light);
  border-radius: var(--radius-sm);
  box-shadow: 0 1px 4px rgba(16, 24, 40, .06);
}
/* Der Platzhalter liegt absolut im Wrapper — ohne dieselbe Breite und Mitte stünde
   „Leer lassen = eingebaute Vorgabe" neben dem Blatt statt darin. */
.einst-html .sun-editor .se-wrapper .se-placeholder {
  left: 50%; transform: translateX(-50%);
  width: 100%; max-width: var(--einst-blatt);
  margin-top: var(--space-4); padding-left: var(--space-4); padding-right: var(--space-4);
  box-sizing: border-box;
}
@media (max-width: 999px) {
  .einst-html { --einst-blatt: none; }
  .einst-html .sun-editor .se-wrapper .se-wrapper-inner { margin: var(--space-2); }
}

/* ── Editor zeigt das ERGEBNIS, nicht seine Hilfslinien ──────────────────────
   SunEditor erzwingt auf JEDER Tabelle im Editierbereich `border: 1px solid` und
   `width: 100%`. Eine Signatur-Tabelle sah damit aus wie ein rohes HTML-Gerüst,
   über die ganze Blattbreite gezogen — „mit geladener Vorlage ist noch billiger"
   (Kyle 27.07.). Im Postfach hat dieselbe Tabelle ihre eigene Breite und keine
   Ränder. Der Editor darf darüber nicht lügen.
   Hilfslinien gibt es weiter — aber nur bei FOKUS und als `outline`, damit sie das
   Layout nicht verschieben. */
.einst-html .sun-editor-editable table { width: auto; border: 0; }
.einst-html .sun-editor-editable table td,
.einst-html .sun-editor-editable table th { border: 0; }
.einst-html .sun-editor .se-wrapper-inner:focus-within table td,
.einst-html .sun-editor .se-wrapper-inner:focus-within table th {
  outline: 1px dashed var(--lod-gray-200, #dee2e8);
  outline-offset: -1px;
}
grep -n "rt-ph" web/styles/sections/einstellungen/einstellungen.css web/styles/components/editor/rich-text.css 2>/dev/null | head -3

/* ══════════════════════════════════════════════════════════════════════════
   Projekt-Teams (Settings-Panel „projekt-teams", Sektion in „Berechtigungen")
   Namespace: epjt-
   Zeigt je Stakeholder-Projekt, ob das Dataverse-Owner-Team mit der Soll-Liste
   uebereinstimmt. Reine ANZEIGE + eine Reparatur-Aktion — kein Formular, deshalb
   auch keine SettingsRow: es gibt keinen Wert, den man eingeben koennte.
   ══════════════════════════════════════════════════════════════════════════ */

.epjt-banner { display: flex; align-items: center; gap: var(--space-2); margin: 0 0 var(--space-3); }
.epjt-alles-gut {
  display: flex; align-items: center; gap: var(--space-2);
  margin: 0 0 var(--space-3);
  color: var(--color-text-secondary);
  font-size: var(--fs-body);
}
.epjt-alles-gut .ui-ico img { filter: none; opacity: .8; }

.epjt-liste { list-style: none; margin: 0; padding: 0; }

/* Eine Zeile, vier Bahnen: Name (gibt nach) · Zustand · Zahlen · Team · Aktion.
   Nur der Name darf schrumpfen — Pille, Zaehler und Knopf tragen atomare Werte und
   duerfen weder gestaucht werden noch umbrechen (gleiche Regel wie in einer
   Subgrid-Row, siehe web/CLAUDE.md). */
.epjt-row {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) var(--space-1);
  border-bottom: 1px solid var(--color-border-subtle, var(--color-border));
  min-height: 44px;
}
.epjt-row:last-child { border-bottom: 0; }
.epjt-row > * { flex-shrink: 0; }

.epjt-name {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: var(--fw-medium, 500);
}
.epjt-pill { white-space: nowrap; }
.epjt-zahlen { white-space: nowrap; font-size: var(--fs-meta); color: var(--color-text-secondary); }
.epjt-zahlen--ok { color: var(--color-text-muted); }
.epjt-team {
  max-width: 220px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--fs-meta); color: var(--color-text-muted);
}
.epjt-aktion { min-width: 0; }

/* Eine abweichende Zeile ist der Grund, warum jemand diese Flaeche oeffnet —
   sie bekommt eine ruhige Toenung, keinen Alarm. */
.epjt-row--drift { background: var(--color-bg-subtle, transparent); }

@media (max-width: 1399px) {
  .epjt-team { max-width: 160px; }
}
@media (max-width: 999px) {
  /* Team-Name faellt zuerst: er beantwortet keine Frage, die man auf dieser Flaeche
     stellt — man will wissen WELCHES Projekt abweicht, nicht wie sein Team heisst. */
  .epjt-team { display: none; }
}
@media (max-width: 599px) {
  /* Zweizeilig statt Quetschung: Name oben, Zustand + Aktion darunter. */
  .epjt-row { flex-wrap: wrap; gap: var(--space-2); padding: var(--space-3) var(--space-1); }
  .epjt-name { flex: 1 0 100%; white-space: normal; }
  .epjt-aktion { margin-left: auto; }
}

/* ══════════════════════════════════════════════════════════════════════════
   Portfolio-Kategorien (Settings-Panel „portfolio-kategorien", Seite „Vertrieb")
   Namespace: epf-
   Bis 2026-07-28 ein eigenes Modal im Vertriebs-Tab (`pot-pf-*` in
   sections/vertrieb/potenziale.css) — die zweite Konfigurations-Oberflaeche der
   App. Die alten Klassen sind mit dem Modal entfallen.
   ══════════════════════════════════════════════════════════════════════════ */

/* Kopfzeile + Zeilen teilen dasselbe Spaltenraster. Zwei Definitionen waeren die
   Sorte Drift, bei der die Ueberschrift ueber der falschen Spalte steht. */
.epf-kopf,
.epf-row {
  display: grid;
  grid-template-columns: 110px minmax(0, 1fr) 200px minmax(0, 180px) 90px;
  align-items: center;
  gap: var(--space-3);
}
.epf-kopf {
  padding: 0 var(--space-1) var(--space-2);
  border-bottom: 1px solid var(--color-border);
  font-size: var(--fs-caption);
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--color-text-muted);
}
.epf-liste { list-style: none; margin: 0; padding: 0; }
.epf-row {
  padding: var(--space-2) var(--space-1);
  border-bottom: 1px solid var(--color-border-subtle, var(--color-border));
  min-height: 48px;
}
.epf-row:last-child { border-bottom: 0; }

.epf-aktiv { justify-self: start; }
.epf-label { min-width: 0; width: 100%; }
/* Die Latent-Pille sitzt IN der Kategorie-Spalte hinter dem Feld — eine eigene
   Spalte waere fuer ein Merkmal, das nur wenige Zeilen tragen, zu viel Raster. */
.epf-latent { justify-self: start; margin-left: calc(-1 * var(--space-2)); white-space: nowrap; }
.epf-thema { min-width: 0; width: 100%; }
.epf-paket {
  min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--fs-meta); color: var(--color-text-muted);
}
/* Feste Breite: die Quittung erscheint und verschwindet, und eine Spalte, die dabei
   ihre Breite aendert, laesst die ganze Tabelle zucken. */
.epf-quittung { min-width: 84px; font-size: var(--fs-caption); }

@media (max-width: 1399px) {
  .epf-kopf, .epf-row { grid-template-columns: 100px minmax(0, 1fr) 170px 90px; }
  /* Einstiegspaket faellt zuerst: es ist hier ohnehin nicht aenderbar. */
  .epf-k-paket, .epf-paket { display: none; }
}
@media (max-width: 999px) {
  .epf-kopf, .epf-row { grid-template-columns: 90px minmax(0, 1fr) 150px; }
  .epf-k-quittung, .epf-quittung { display: none; }
}
@media (max-width: 599px) {
  /* Zweizeilig statt Quetschung: Schalter + Name oben, Thema darunter. */
  .epf-kopf { display: none; }
  .epf-row {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas: "aktiv label" ". thema";
    row-gap: var(--space-2);
    padding: var(--space-3) var(--space-1);
  }
  .epf-aktiv { grid-area: aktiv; }
  .epf-label { grid-area: label; }
  .epf-thema { grid-area: thema; }
  .epf-latent { display: none; }
}

/* ── Datenexport-Panel (Selbstbedienungs-Ausleitung, SaaS-AGB 10.1) ─────────
   Fläche: web/js/sections/einstellungen-datenexport.js, Deklaration:
   api/config/settings-datenexport.js. Aufbau bewusst wie `.epf-*` eine Zeile
   ohne Formularfelder — hier wird nichts eingestellt, nur etwas ausgelöst. */
.edx-kopf {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--color-border);
}
.edx-hinweis { margin: 0; color: var(--color-text-muted); font-size: var(--fs-caption); }
.edx-alles { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.edx-alles-hilfe { color: var(--color-text-muted); font-size: var(--fs-caption); min-width: 0; }

.edx-bereich { margin-top: var(--space-4); }
.edx-bereich-titel {
  margin: 0 0 var(--space-2);
  font-size: var(--fs-caption);
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--color-text-muted);
}
.edx-liste { list-style: none; margin: 0; padding: 0; }
.edx-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 140px 140px;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-1);
  border-bottom: 1px solid var(--color-border-subtle, var(--color-border));
  min-height: 44px;
}
.edx-row:last-child { border-bottom: 0; }
/* Der Registername ist die einzige nachgebende Spalte — die Spaltenzahl und der
   Knopf tragen atomare Werte und dürfen nicht umbrechen. */
.edx-titel { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.edx-spalten { color: var(--color-text-muted); font-size: var(--fs-caption); white-space: nowrap; }
.edx-einzeln { justify-self: end; white-space: nowrap; }

@media (max-width: 1399px) {
  .edx-row { grid-template-columns: minmax(0, 1fr) 120px 130px; }
}
@media (max-width: 999px) {
  /* Die Spaltenzahl ist eine Zusatzauskunft und fällt zuerst — der Knopf nie. */
  .edx-row { grid-template-columns: minmax(0, 1fr) 130px; }
  .edx-spalten { display: none; }
}
@media (max-width: 599px) {
  .edx-row { grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-2); }
  .edx-alles { align-items: flex-start; flex-direction: column; }
}

/* ── Persona-Vorschau der Signaturen (Panel `signatur-vorschau`) ─────────────
   Die Fläche beantwortet EINE Frage: „was bekommt diese Person in dieser Lage?" Deshalb
   liegt die Leiste oben (Person · Empfänger · Verfassen), darunter die MERKMALE — sie
   erklären, warum eine Regel greift oder nicht — und erst dann die gerenderten Vorlagen.
   Eine Signatur ist 600–700px breit; die Karten stehen einspaltig, damit nichts skaliert
   werden muss (ein verkleinerter Signaturtext ist unlesbar, siehe Add-in-Pane). */
.sigv-panel { display: flex; flex-direction: column; gap: var(--space-4); }
.sigv-leiste { display: flex; flex-wrap: wrap; gap: var(--space-4); align-items: flex-end; }
.sigv-feld { display: flex; flex-direction: column; gap: var(--space-1); }
.sigv-feld-label { font-size: var(--fs-meta, 12px); color: var(--color-text-muted); font-weight: var(--fw-semibold); }
.sigv-person { min-width: 280px; }
.sigv-schalter { display: inline-flex; border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; }
.sigv-schalter-btn {
  padding: var(--space-1) var(--space-3); font-size: var(--fs-body, 14px);
  background: var(--color-surface); color: var(--color-text-muted); cursor: pointer;
  border: none; border-right: 1px solid var(--color-border);
}
.sigv-schalter-btn:last-child { border-right: none; }
/* `--brand-text-on` und NICHT ein hartes Weiß: die Marke ist pro Instanz gesetzt, und auf
   einer hellen Kundenfarbe wäre weißer Text unlesbar (52× im Bestand, dieselbe Regel wie im
   Add-in-Pane). `--color-on-accent` gibt es nicht — der erste Entwurf hatte den Namen
   erfunden, `check:css-tokens` hat ihn als Fremd-Vokabular gemeldet. */
.sigv-schalter-btn.is-aktiv { background: var(--color-accent); color: var(--brand-text-on); }

.sigv-merkmale { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); }
.sigv-merkmal { display: flex; gap: var(--space-1); align-items: baseline; font-size: var(--fs-body, 14px); }
.sigv-merkmal-label { color: var(--color-text-muted); }
.sigv-merkmal-wert { font-weight: var(--fw-medium, 500); color: var(--color-text); }
/* Ein leeres Merkmal ist die häufigste Ursache dafür, dass eine Regel nicht greift —
   es wird getönt, nicht ausgelassen. */
.sigv-merkmal.is-leer .sigv-merkmal-wert { color: var(--status-warning-fg); font-style: italic; font-weight: var(--fw-regular, 400); }

.sigv-hinweis { margin: 0; font-size: var(--fs-body, 14px); color: var(--color-text-muted); }
.sigv-karten { display: flex; flex-direction: column; gap: var(--space-3); }
/* EIN Block für beide Signatur-Flächen: die Vorlagen-Karte der Persona-Vorschau und die
   Design-Karte der Galerie (`.siggal-karte`, weiter unten) sind dieselbe Fläche — ein
   gerahmter Kasten mit gestapeltem Inhalt. Als zwei Blöcke wären sie am Tag der Kopie
   identisch und liefen danach auseinander, weil niemand beide Stellen kennt (Gate
   `check:css-doppel`; genau so divergierten die sechs `.cs-trigger`-Nachbauten). Was die
   Karten UNTERSCHEIDET, steht bei ihnen selbst — hier nur, was sie teilen. */
.sigv-karte,
.siggal-karte {
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface); padding: var(--space-3);
  display: flex; flex-direction: column; gap: var(--space-2);
}
/* Die eine Vorlage, die WIRKLICH gesetzt würde, muss auf den ersten Blick zu finden sein —
   sonst ist die Liste eine Aufzählung ohne Antwort. */
.sigv-karte.is-empfohlen { border-color: var(--color-accent); box-shadow: 0 0 0 1px var(--color-accent) inset; }
.sigv-karte-kopf { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); }
.sigv-karte-name { font-weight: var(--fw-semibold); color: var(--color-text); }
.sigv-karte-meta { font-size: var(--fs-meta, 12px); color: var(--color-text-muted); }
.sigv-warn {
  font-size: var(--fs-meta, 12px); color: var(--status-warning-fg);
  border-left: 2px solid var(--status-warning-fg); padding-left: var(--space-2);
}
.sigv-rahmen { border: 1px solid var(--lod-gray-100); border-radius: var(--radius-sm); overflow: auto; background: #fff; }
.sigv-frame { display: block; width: 100%; border: 0; min-height: 40px; }

@media (max-width: 999px) {
  .sigv-leiste { flex-direction: column; align-items: stretch; }
  .sigv-person { min-width: 0; width: 100%; }
}
@media (max-width: 599px) {
  .sigv-schalter { width: 100%; }
  .sigv-schalter-btn { flex: 1 1 0; text-align: center; }
}
/* Testversand: der Knopf und der Satz, der die Grenze nennt („nur an Sie selbst"). Sie
   stehen ZUSAMMEN in einer Zeile — der Satz ist keine Fußnote, sondern Teil der Zusage. */
.sigv-test { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.sigv-test-hinweis { font-size: var(--fs-meta, 12px); color: var(--color-text-muted); }

/* ══════════════════════════════════════════════════════════════════════════
   Vorlagen-Galerie der Signaturen
   Namespace: siggal-
   Flaeche: web/js/sections/einstellungen-signatur-galerie.js (Auswahl-Dialog,
   geoeffnet aus der Variablen-Leiste eines `typ:'html'`-Signaturfeldes).

   ★ WARUM EIN GITTER UND KEINE LISTE wie bei `sigv-`: dort steht EINE Person in
   EINER Lage und die Vorlagen sind Alternativen derselben Regel — man liest sie
   nacheinander. Hier VERGLEICHT man Designs, und Vergleichen heisst nebeneinander.
   ══════════════════════════════════════════════════════════════════════════ */

.siggal-hinweis { margin: 0 0 var(--space-3) 0; font-size: var(--fs-body, 14px); color: var(--color-text-muted); }
/* ★ `min(300px, 100%)` statt `300px`, und `min-width: 0` an Karte UND Rahmen — beides
   gegen dieselbe Falle: eine `1fr`-Spur trägt `min-width: auto` und kann damit nicht
   unter die MIN-CONTENT-Breite ihres Inhalts schrumpfen. Der Vorschau-Rahmen bekommt
   vom Renderer die UNSKALIERTE Breite des Designs (bis 520px) — `transform: scale()`
   verkleinert nur die Darstellung, nicht den Platzbedarf im Layout. Ohne diese drei
   Zeilen zieht ein 518px-Design die Spalte auf und die ganze Fläche läuft waagerecht
   über: gemessen 548px Inhalt in einem 371px-Fenster. Gefunden hat das
   `check:signatur-galerie-live` (Block G), nicht das Auge — CSS wirft nie. */
.siggal-gitter {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
  gap: var(--space-3);
}
/* Die Karten-Grundform teilt sich diese Klasse mit `.sigv-karte` (oben, EIN Block).

   ★★ KEIN `max-height` — hier stand einer (260px), und er war falsch. Die Vorschau soll
   das GANZE Design zeigen; sie ist der einzige Grund, warum man vergleichen kann. Mit
   Deckel endete „Klassisch" mitten im Vertraulichkeitssatz, und das liest sich nicht wie
   ein Deckel, sondern wie ein kaputtes Design. Die Höhe setzt jetzt der Renderer aus der
   GEMESSENEN Inhaltshöhe (`_rahmenFuellen`, nachmessend per ResizeObserver) — die Karten
   werden dadurch unterschiedlich hoch (gemessen 82–275px), und das ist ehrlicher als eine
   Kante, die Inhalt verschluckt.
   `overflow: hidden` bleibt als NETZ: misst der Renderer einmal daneben, quillt nichts
   über die Karte. Es ist damit ausdrücklich kein Gestaltungsmittel mehr — dass darunter
   nichts abgeschnitten wird, sichert `check:signatur-galerie-live` zu. */
.siggal-karte { min-width: 0; }
.siggal-rahmen {
  border: 1px solid var(--lod-gray-100); border-radius: var(--radius-sm);
  background: #fff; overflow: hidden; min-width: 0;
}
/* Die Verkleinerung macht `transform`, nicht die Rahmenbreite — ein Tabellen-Layout mit
   festen Breiten wuerde sonst umbrechen statt kleiner zu werden (siehe `_rahmenFuellen`). */
.siggal-frame { display: block; border: 0; transform-origin: top left; }
.siggal-text { display: flex; flex-direction: column; gap: var(--space-1); flex: 1 1 auto; }
.siggal-name { margin: 0; font-size: var(--fs-body, 14px); font-weight: var(--fw-semibold); color: var(--color-text); }
.siggal-besch { margin: 0; font-size: var(--fs-meta, 12px); color: var(--color-text-muted); line-height: 1.5; }
.siggal-chips { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.siggal-chip {
  font-size: var(--fs-meta, 12px); color: var(--color-text-muted);
  background: var(--lod-gray-50); border: 1px solid var(--color-border);
  border-radius: var(--radius-pill, 999px); padding: 1px var(--space-2);
}
/* Dieselbe Tonart wie die Pflichtangaben-Warnung des Outlook-Panes — es ist derselbe
   Sachverhalt (§ 35a GmbHG) und darf nicht zweimal verschieden aussehen. */
.siggal-warn {
  margin: 0; font-size: var(--fs-meta, 12px); color: var(--status-warning-fg);
  border-left: 2px solid var(--status-warning-fg); padding-left: var(--space-2);
}
.siggal-aktion { display: flex; justify-content: flex-end; }

/* Lupe auf der Vorschau: die Karte zeigt das Design auf ~63 % (Schrift effektiv ~8px) —
   genug zum Unterscheiden, nicht zum Beurteilen. `position: absolute` braucht den Rahmen
   als Bezug, deshalb steht er auf `relative`. Sie liegt ÜBER dem iframe (`z-index`), weil
   ein Klick IM iframe das Elterndokument nicht erreicht. */
.siggal-rahmen { position: relative; }
.siggal-lupe {
  position: absolute; top: var(--space-1); right: var(--space-1); z-index: 1;
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0;
  border: 1px solid var(--color-border); border-radius: var(--radius-sm);
  background: var(--color-surface); cursor: pointer; opacity: 0.85;
}
.siggal-lupe:hover { opacity: 1; border-color: var(--color-accent); }

/* Großvorschau: ersetzt den Dialog-Inhalt, statt eine dritte Ebene zu öffnen. */
.siggal-gross { display: flex; flex-direction: column; gap: var(--space-3); }
.siggal-gross-kopf { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.siggal-gross-name { font-weight: var(--fw-semibold); color: var(--color-text); flex: 1 1 auto; }
/* `overflow: auto` und NICHT `hidden`: hier soll nichts abgeschnitten werden — das ist der
   ganze Zweck der Ansicht. Ein Design ist bis 520px breit, im schmalen Fenster scrollt es. */
.siggal-gross-rahmen {
  border: 1px solid var(--lod-gray-100); border-radius: var(--radius-sm);
  background: #fff; overflow: auto; min-width: 0;
}
.siggal-gross-frame { display: block; width: 100%; border: 0; min-height: 120px; }

@media (max-width: 599px) {
  /* `minmax(0, 1fr)`, nicht `1fr`: siehe die Begründung am Gitter oben — ein blankes
     `1fr` trägt `min-width: auto` und lässt den unskalierten Rahmen die Spalte aufziehen. */
  .siggal-gitter { grid-template-columns: minmax(0, 1fr); }
  .siggal-aktion .app-cta-btn { width: 100%; }
}

/* ══════════════════════════════════════════════════════════════════════════
   Themen-Katalog-Panel (Themen-Baum, bisher „Betreff")
   Namespace: eth-
   Flaeche: web/js/sections/einstellungen-themen.js · Deklaration:
   api/config/settings-allgemein.js, Seite `allgemein`, Reiter „Themen".

   ★ WARUM EIN BAUM UND KEINE FLACHE LISTE MIT EINRUECKUNG: die Hierarchie ist
   seit dem Kyle-Entscheid 2026-07-31 FREI TIEF. Die alte Darstellung im
   Betreff-Picker rueckte je Ebene um 14px ein — ab Ebene 3 in einem 320-420px
   breiten Popover unlesbar. Hier tragen Chevron + `--eth-tiefe` die Struktur,
   und die Einrueckung ist GEDECKELT (siehe unten).
   ══════════════════════════════════════════════════════════════════════════ */

/* ★★ DER MESSBEZUG IST DIE KARTE, NICHT DAS FENSTER (2026-08-01).
   Die Breakpoints dieser Zeile hingen bis dahin am VIEWPORT, der Zwang liegt aber an
   `--einst-karte` (1116px Deckel) plus Bereichs-Navigation. Im Notebook-Band
   1000–1399px zeigte das Raster deshalb alle sechs Spalten, die die Karte nie tragen
   konnte — und weil der Titel die EINZIGE flexible Spur war (`minmax(0, 1fr)` erlaubt
   ausdrücklich null), fiel das Titelfeld bei 1056px Fensterbreite auf **22px**. Auf
   jeder Ebene, nicht nur tief im Baum; im Browser gemessen, gemeldet vom Auge.
   Die einzige Spalte, die Bedeutung trägt, war die einzige, die nachgibt.
   ★ Und das Gate war dabei GRÜN: `check:themen-live` fuhr [2248, 1440, 900, 380] und
   stieg damit genau über das kaputte Band hinweg — unter 1000px fallen Oberthema und
   Reihenfolge weg, darüber trägt die Karte wieder. Die Leiter hat seither eine Sprosse
   im Band (1100).
   Jetzt entscheidet der Container: einzeilig erst, wenn er die Zeile WIRKLICH trägt
   (300px Titel-Minimum + 460px Festbedarf = 760px, Schwelle 780px). Darunter rutscht
   der Metadaten-Block GESCHLOSSEN unter den Titel, statt ihn zu zerdrücken — nichts
   wird unerreichbar, und der Name behält seine Breite. */
.eth-wrap { container-type: inline-size; container-name: eth; }

/* Kopfzeile + Zeilen teilen dasselbe Spaltenraster — zwei Definitionen waeren die
   Sorte Drift, bei der die Ueberschrift ueber der falschen Spalte steht (derselbe
   Grund wie bei `.epf-*`).
   VORGABE IST DER GESTAPELTE FALL: eine Container-Query, die nicht greift (oder von
   einem Browser nicht verstanden wird), liefert damit die Form, die IMMER funktioniert
   — und nicht die, die den Titel erdrückt. */
.eth-kopf { display: none; }
.eth-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    'baum     aktionen'
    'meta     meta';
  align-items: center;
  column-gap: var(--space-3);
  row-gap: var(--space-2);
}
.eth-baum { grid-area: baum; }
.eth-meta { grid-area: meta; }
.eth-aktionen { grid-area: aktionen; }

/* Der Metadaten-Block ist EIN Grid-Knoten und teilt seine Spuren mit dem Kopf — genau
   wie `.eth-kopf`/`.eth-row` eine Ebene darüber. Zwei Definitionen wären hier dieselbe
   Drift eine Ebene tiefer: `auto`-Spuren bemessen sich je Container am eigenen Inhalt,
   und der Kopf trägt Wörter, die Zeile Steuerelemente (gemessen 111px Versatz, als
   `.einst-kat-head` diesen Fehler machte). */
.eth-k-meta,
.eth-meta {
  display: grid;
  grid-template-columns: minmax(0, 150px) 56px 44px minmax(0, 90px);
  align-items: center;
  gap: var(--space-3);
}

@container eth (min-width: 780px) {
  .eth-kopf { display: grid; }
  .eth-kopf,
  .eth-row {
    /* 300px ist das Titel-MINIMUM, nicht seine Breite: die Spur wächst mit `1fr` auf
       alles, was die Karte hergibt (gemessen 530px bei 1440px Fenster, 616px bei
       1920px). Bei maximaler Einrückung (8 Ebenen × 16px) bleiben an der Schwelle
       selbst noch 164px Feld — über der Lesbarkeitsgrenze des Gates (120px). */
    grid-template-columns: minmax(300px, 1fr) 376px 60px;
    grid-template-areas: none;
    /* Der Kopf braucht dieselbe Spalten-Luecke wie die Zeile. Ohne sie stehen seine
       Spuren 12px weiter links — klein, aber genau die Sorte Versatz, gegen die die
       gemeinsame Raster-Definition ueberhaupt gebaut ist. */
    column-gap: var(--space-3);
    row-gap: 0;
  }
  /* ★★ `grid-area` MUSS ZURUECKGENOMMEN WERDEN, `grid-template-areas: none` reicht NICHT.
     Ein `grid-area: baum` ohne passende Linie faellt nicht auf Auto-Platzierung zurueck:
     nach Grid-Spec §8.3 gelten dann ALLE IMPLIZITEN Linien als so benannt, das Kind
     landet also in einer implizit angelegten Spalte HINTER dem expliziten Raster. Die
     Zeile verliess damit ihre eigenen drei Spuren, waehrend der Kopf (dessen Kinder kein
     `grid-area` tragen) korrekt darin blieb — im Browser als 146px/230px Versatz
     gemessen, und das Titelfeld fiel bei 1440px auf 178px statt 500px. Nichts daran
     wirft, und im gestapelten Fall sieht alles richtig aus. */
  .eth-baum,
  .eth-meta,
  .eth-aktionen { grid-area: auto; }
}
.eth-kopf {
  padding: 0 var(--space-1) var(--space-2);
  border-bottom: 1px solid var(--color-border);
  font-size: var(--fs-caption);
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--color-text-muted);
}
.eth-liste { list-style: none; margin: 0; padding: 0; }
.eth-row {
  padding: var(--space-2) var(--space-1);
  border-bottom: 1px solid var(--color-border-subtle);
  min-height: 44px;
}
.eth-row:last-child { border-bottom: 0; }

/* Die Baum-Spalte traegt Chevron + Titelfeld. Die Einrueckung kommt aus
   `--eth-tiefe` (vom Renderer je Zeile gesetzt) und ist bei 8 Ebenen GEDECKELT:
   bei freier Tiefe wuerde eine ungedeckelte Einrueckung das Titelfeld irgendwann
   auf null Breite druecken — ein Feld, das man nicht mehr lesen kann, ist
   schlimmer als eine Struktur, die man ab Ebene 9 nur noch am Chevron erkennt. */
.eth-baum {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  /* Im gestapelten Fall faellt die Einrueckung kleiner aus und ist frueher gedeckelt —
     dort teilt sich der Titel seine Zeile nur mit den Aktionen, aber der Container ist
     eben auch schmal. Der grosszuegige Wert steht in der Container-Query unten. */
  padding-left: calc(min(var(--eth-tiefe, 0), 5) * var(--space-3));
}
.eth-titel { min-width: 0; width: 100%; }
@container eth (min-width: 780px) {
  .eth-baum { padding-left: calc(min(var(--eth-tiefe, 0), 8) * var(--space-4)); }
}

/* Der Chevron-PLATZ ist immer reserviert, auch am Blatt (`--leer`) — sonst springt
   die Einrueckung je Zeile um die Chevron-Breite und der Baum sieht schief aus.
   Dieselbe Regel wie beim Sektionskopf der Settings-Flaeche. */
.eth-chevron {
  flex: 0 0 auto;
  width: 20px; height: 20px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
}
.eth-chevron img { opacity: .7; }
.eth-chevron--leer { visibility: hidden; }
.eth-liste .eth-chevron:hover { background: var(--color-bg-subtle); }

.eth-aktionen { display: flex; align-items: center; gap: var(--space-1); justify-self: end; }
@container eth (min-width: 780px) {
  .eth-aktionen { justify-self: start; }
}
.eth-akt {
  width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
}
.eth-akt:hover { background: var(--color-bg-subtle); color: var(--color-text); }
.eth-akt--weg:hover { background: var(--status-danger-bg); color: var(--status-danger-fg); }

/* Feste Breite: die Quittung erscheint und verschwindet, und eine Spalte, die dabei
   ihre Breite aendert, laesst die ganze Tabelle zucken. */
.eth-quittung { min-width: 84px; font-size: var(--fs-caption); }

.eth-neu-zeile { padding-top: var(--space-3); }

/* Ganz schmaler Container: der Metadaten-Block gibt sein Raster auf und umbricht. Vier
   feste Spuren (376px) passen sonst nicht mehr neben die Polsterung, und ein Grid, das
   nicht passt, LAEUFT UEBER statt umzubrechen. */
@container eth (max-width: 460px) {
  .eth-meta { display: flex; flex-wrap: wrap; }
  .eth-row .eth-flaechen { flex: 1 1 140px; }
}

/* Themen-Panel, Welle 2: Aktiv-Schalter, Reihenfolge, Flaechen-Facette.
   Das Raster waechst um drei Spuren — Kopf und Zeile teilen es weiter (die
   `.eth-kopf, .eth-row`-Regel oben), damit die Ueberschrift nicht ueber der
   falschen Spalte steht. */
.eth-aktiv { justify-self: start; }
.eth-sort { width: 100%; min-width: 0; text-align: center; }
/* ★ MIT ZEILEN-VORFAENGER, NICHT EIN-KLASSIG. `.app-scope button` setzt border/background/
   padding zurueck und traegt (0,1,1) — eine Ein-Klassen-Regel (0,1,0) verliert und der
   Knopf erschien RANDLOS. Im Browser gemessen (borderStyle „none"), nicht vermutet;
   genau der Fall, den `audit:button-reset` und das Memory app-scope-button-reset
   beschreiben. Praefix ist die EIGENE Zeilenklasse, NICHT `.app-scope` (Modul-Regel).
   Die Facetten-Zelle ist ein KNOPF und kein Feld: sie oeffnet eine Mehrfachauswahl.
   Sie traegt den Ist-Zustand als Text („ueberall", „Zeiten, Aufgaben", „4 Bereiche") —
   eine leere Zelle liesse sich als „nirgends" lesen, also als das Gegenteil. */
.eth-row .eth-flaechen {
  min-width: 0; width: 100%;
  padding: 4px var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: transparent;
  font-size: var(--fs-meta);
  color: var(--color-text-muted);
  text-align: left;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  cursor: pointer;
}
.eth-row .eth-flaechen:hover:not(:disabled) { background: var(--color-bg-subtle); color: var(--color-text); }
.eth-row .eth-flaechen:disabled { cursor: default; opacity: .6; }

/* ★★ RUHE IM KATALOG. Ein Themen-Baum wird gelesen und selten bearbeitet — ~60 Zeilen
   mit je drei gerahmten Steuerelementen sind eine Wand aus Kaesten, in der der Name
   untergeht. Die Rahmen erscheinen an der Zeile, auf der der Zeiger steht oder in der
   der Fokus sitzt.
   ★ Die Steuerelemente BLEIBEN dabei an ihrem Platz — nur Rahmen und Flaeche schalten.
   Ein- und Ausblenden waere die naheliegende, aber falsche Variante: die Zeile
   springt dann unter dem Zeiger weg und man klickt auf das Nachbarelement.
   ★ Und der fokussierte Knoten ist AUSGENOMMEN (`:not(:focus)`): sein Rahmen gehoert
   dem Fokus-Ring der Control-Familie (`.app-scope .app-drawer-input:focus`, tuerkis).
   Beide Regeln traegen (0,3,0), diese steht spaeter — ohne den Ausschluss haette der
   Hover-Rahmen den Fokus-Ring geschlagen und das Tabben seinen staerksten Indikator
   verloren. */
.eth-row .eth-titel,
.eth-row .eth-sort,
.eth-row .eth-flaechen {
  border-color: transparent;
  background: transparent;
}
.eth-row:hover .eth-titel:not(:focus),
.eth-row:hover .eth-sort:not(:focus),
.eth-row:hover .eth-flaechen:not(:focus),
.eth-row:focus-within .eth-titel:not(:focus),
.eth-row:focus-within .eth-sort:not(:focus),
.eth-row:focus-within .eth-flaechen:not(:focus) {
  border-color: var(--lod-gray-200);
  background: var(--color-surface);
}

/* Ein stillgelegtes Thema muss man im RUHENDEN Zustand erkennen — der Schalter allein
   ist zu klein, um beim Ueberfliegen von 60 Zeilen aufzufallen. */
.eth-row--aus .eth-titel { color: var(--color-text-muted); }

/* ── Popover-Inhalte (Facette, Zeilen-Menue, Umhaengen) ────────────────────────
   Die Panels haengen an `document.body` und liegen damit AUSSERHALB von `.app-scope`
   — der Button-Reset greift dort nicht. Trotzdem zwei Klassen tief (0,2,0) statt
   ein-klassig: `.app-popover button` waere (0,1,1) und wuerde eine Ein-Klassen-Regel
   schlagen, sobald das Popover-Modul selbst einen solchen Reset bekommt. */
.eth-pop {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-1);
}
.eth-pop-hinweis { font-size: var(--fs-meta); color: var(--color-text-muted); }
.eth-pop .eth-pop-select { width: 100%; min-width: 0; }
.eth-fz-liste { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.eth-pop .eth-fz-chip {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: 3px var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill, 999px);
  font-size: var(--fs-meta);
  cursor: pointer;
}
.eth-pop .eth-fz-chip.is-an { background: var(--lod-darkblue-100); border-color: var(--lod-darkblue); color: var(--lod-darkblue); }
.eth-pop .eth-fz-chip input { margin: 0; }

.eth-menue { display: flex; flex-direction: column; }
.eth-menue .eth-menue-item {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--fs-body);
  color: var(--color-text);
  text-align: left;
  cursor: pointer;
}
.eth-menue .eth-menue-item:hover { background: var(--color-bg-subtle); }
.eth-menue .eth-menue-item--weg:hover { background: var(--status-danger-bg); color: var(--status-danger-fg); }

/* ── Entwurf → Übernehmen: Commit-Leiste + Zeilen-Marker (2026-08-02) ──────────
   Die Einstellungen speichern nicht mehr bei jeder Feldänderung (Kyle-Entscheid,
   Begründung: settings-framework.md § Entwurf → Übernehmen). Die Leiste ist der
   sichtbare Träger des Entwurfs: sie klebt am unteren Rand der Scroll-Fläche
   (sticky, letztes Kind von .einst-wrap) und ist damit unübersehbar, egal wie
   weit die Seite gescrollt ist — das strukturelle Gegenmittel gegen „wer den
   Speichern-Knopf übersieht, rechnet mit alten Werten weiter". */
.einst-entwurf-leiste {
  position: sticky;
  bottom: 0;
  z-index: 5; /* über den Karten, unter Drawern/Popovers (die leben am body) */
  max-width: var(--einst-flaeche);
  padding: var(--space-2) 0 var(--space-2);
}
.einst-entwurf-inner {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2-5) var(--space-4);
  border: 1px solid var(--lod-darkblue);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  /* Eigene, deutliche Elevation: die Leiste SCHWEBT über dem Inhalt — mit der
     flachen Karten-Ruhe-Elevation wäre sie eine Karte unter Karten. */
  box-shadow: var(--shadow-16);
}
.einst-entwurf-ico { flex-shrink: 0; color: var(--lod-darkblue); display: inline-flex; }
.einst-entwurf-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1 1 auto;
}
.einst-entwurf-text strong { font-size: var(--fs-body); font-weight: var(--fw-semibold); color: var(--color-text); }
.einst-entwurf-felder {
  font-size: var(--fs-meta);
  color: var(--color-text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.einst-entwurf-aktionen { display: flex; align-items: center; gap: var(--space-2); flex-shrink: 0; }

/* Zeilen-Marker „noch nicht übernommen": Akzent-Kante + leichte Fläche an der
   ganzen Zeile. NICHT amber — der Entwurf ist kein Problemzustand, sondern
   Arbeit in der Hand des Bedieners; Amber gehört den Warnungen. Nicht mit
   `.einst-nav-dirty` verwechseln (das heißt „weicht vom Standard ab"). */
.einst-wrap .set-row.is-entwurf {
  box-shadow: inset 3px 0 0 var(--lod-darkblue);
  background: var(--lod-darkblue-50, var(--lod-gray-50));
}
/* Dieselbe Aussage am Sektions-KOPF: ein Sektions-Schalter (Kyle-Regel „Schalter in
   den Kopf") hat keine .set-row — ohne diese Regel nannte die Leiste das Feld, aber
   am geänderten Element war nichts zu sehen (Live-Gate-Fund 2026-08-02). */
.einst-wrap .einst-sec-head.is-entwurf {
  box-shadow: inset 3px 0 0 var(--lod-darkblue);
  background: var(--lod-darkblue-50, var(--lod-gray-50));
}

/* Notebook (1000–1399): unverändert fluid — die Leiste folgt der Flächen-Breite. */
/* Tablet (600–999): die Nav kollabiert einspaltig, die Leiste bleibt einzeilig. */
@media (max-width: 999px) {
  .einst-entwurf-leiste { max-width: none; }
}
/* Mobile (<600): Text und Aktionen stapeln, die Knöpfe füllen die Breite —
   nebeneinander wären sie unter 360px nicht mehr treffsicher. */
@media (max-width: 599px) {
  .einst-entwurf-inner { flex-wrap: wrap; }
  .einst-entwurf-aktionen { width: 100%; justify-content: stretch; }
  .einst-entwurf-aktionen .app-cta-btn { flex: 1 1 0; }
}
