/* ============================================================================
   Score — Admin-Theme (handgebaut, kein Framework)

   Basis: das Trove-Theme (Inter, Indigo-Brand, Slate-Seitenleiste, Dunkelmodus).
   Es ist der globale Standard; jeder Mandant kann sein Corporate Design darauf
   legen — ThemeInjector setzt pro aktivem Mandant nur die abweichenden Tokens
   (Primär-/Akzentfarbe, Seitenleiste, Schrift, Radius, Modus, Logo).

   Kompatibilitaets-Tokens (--navy*, --teal, --brand-ink, --font-head) bleiben
   erhalten, sind aber auf die Trove-Welt umgemappt, damit die vorhandenen
   Komponenten (u. a. das Scoring-Modul) unveraendert weiterlaufen.
   ========================================================================== */

:root {
  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-head: var(--font-sans);

  /* Brand — Indigo (Trove) */
  --brand-50:  #eef2ff;
  --brand-100: #e0e7ff;
  --brand-500: #6366f1;
  --brand-600: #4f46e5;
  --brand-700: #4338ca;

  /* Kompatibilitaet: fruehere Navy/Teal-Tokens auf die Indigo/Slate-Welt gemappt. */
  --navy:      #1e293b;
  --navy-mid:  #334155;
  --brand-ink: #4f46e5;
  --teal:      #0ea5e9;

  /* Neutrals (hell) */
  --bg:        #f6f7fb;
  --surface:   #ffffff;
  --surface-2: #f9fafb;
  --border:    #e5e7eb;
  --text:      #111827;
  --text-2:    #6b7280;
  --text-3:    #9ca3af;

  --sidebar-bg:   #0f172a;
  --sidebar-text: #cbd5e1;
  --sidebar-muted:#64748b;
  --sidebar-active-bg: rgba(99,102,241,.18);
  --sidebar-active-text: #ffffff;

  --success: #10b981;
  --warning: #f59e0b;
  --danger:  #ef4444;
  --info:    #3b82f6;

  --radius:    12px;
  --radius-sm:  8px;
  --radius-lg: 16px;
  --radius-pill: 999px;
  --shadow-sm: 0 1px 2px rgba(16,24,40,.06), 0 1px 3px rgba(16,24,40,.10);
  --shadow-md: 0 4px 12px rgba(16,24,40,.08);
  --shadow-lg: 0 12px 32px rgba(16,24,40,.14);

  --sidebar-w: 260px;
  --topbar-h: 64px;
  --control-h: 42px;

  /* Diagramm-Palette (Trove). Reihenfolge = Absicherung gegen Farbfehlsichtigkeit:
     Nachbarn maximal getrennt, Slots strikt der Reihe nach vergeben. */
  --viz-1: #2a78d6;
  --viz-2: #1baf7a;
  --viz-3: #eda100;
  --viz-4: #008300;
  --viz-5: #4a3aa7;
  --viz-6: #e34948;
  --viz-7: #e87ba4;
  --viz-8: #eb6834;
}

:root[data-theme="dark"] {
  --bg:        #0b1120;
  --surface:   #111827;
  --surface-2: #0f1626;
  --border:    #1f2937;
  --text:      #f3f4f6;
  --text-2:    #9ca3af;
  --text-3:    #6b7280;
  --brand-ink: #a5b4fc;
  --navy:      #1e293b;
  --navy-mid:  #475569;
  --sidebar-bg:#0a0f1d;
  --shadow-sm: 0 1px 2px rgba(0,0,0,.4);
  --shadow-md: 0 4px 12px rgba(0,0,0,.45);
  --shadow-lg: 0 12px 32px rgba(0,0,0,.55);

  --viz-1: #3987e5;
  --viz-2: #199e70;
  --viz-3: #c98500;
  --viz-4: #008300;
  --viz-5: #9085e9;
  --viz-6: #e66767;
  --viz-7: #d55181;
  --viz-8: #d95926;
}
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.6;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}
a { color: var(--brand-ink); text-decoration: none; }
a:hover { color: var(--navy); text-decoration: underline; }
:root[data-theme="dark"] a:hover { color: #a9cbf2; }
/* Ueberschriften in der Hausschrift (Inter, halbfett).
   */
h1,h2,h3,h4 { font-family: var(--font-head); font-weight: 650; margin: 0 0 .4em;
  line-height: 1.2; letter-spacing: -.005em; color: var(--text); }
/* Das hidden-Attribut muss gewinnen: Klassen wie .badge oder .btn setzen display
   und schlagen damit die display:none-Regel des Browsers — ausgeblendete
   Elemente blieben sonst sichtbar. */
[hidden] { display: none !important; }

/* ── Scrollbalken ────────────────────────────────────────────────────────────
   Der Standardbalken ist in einer dunklen Seitenleiste ein heller Fremdkoerper
   und im hellen Inhalt ein grauer Klotz aus einem anderen Jahrzehnt. Beide
   werden deshalb an ihre Umgebung angeglichen — dieselbe Breite, dieselben
   Farben wie der Rand daneben.

   Zwei Schreibweisen, weil sich die Browser nicht einig sind: Firefox kennt
   scrollbar-width/scrollbar-color, die uebrigen ::-webkit-scrollbar. Beide
   sagen dasselbe, keine ist Ersatz fuer die andere. */
* { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border); border-radius: 6px;
  /* Der Rand aus der Hintergrundfarbe laesst den Balken schlanker wirken, ohne
     die Trefferflaeche zu verkleinern — getroffen werden will er trotzdem. */
  border: 2px solid var(--bg);
}
::-webkit-scrollbar-thumb:hover { background: var(--text-3); }
::-webkit-scrollbar-corner { background: transparent; }

/* In der Seitenleiste gilt ihre eigene, dunkle Welt. */
.sidebar, .sidebar * { scrollbar-color: rgba(255, 255, 255, .22) transparent; }
.sidebar ::-webkit-scrollbar-thumb,
.sidebar::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, .22); border-color: transparent;
}
.sidebar ::-webkit-scrollbar-thumb:hover,
.sidebar::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, .38); }

/* Innerhalb einer Karte ist der Bezug die Kartenflaeche, nicht der Seitengrund. */
.card ::-webkit-scrollbar-thumb, .tablewrap::-webkit-scrollbar-thumb {
  border-color: var(--surface);
}

/* ── App-Shell ───────────────────────────────────────────────────────────── */
.app { display: grid; grid-template-columns: var(--sidebar-w) 1fr; height: 100vh; overflow: hidden; }

/* Griff zum Ziehen der Breite.
   Sitzt AUF der Kante (rechts, halb ueberlappend) statt daneben: so faengt er
   den Zeiger auch, wenn man die Kante nur ungefaehr trifft, ohne dafuer Platz
   aus dem Menue zu nehmen. Sichtbar wird er erst beim Beruehren — eine
   dauerhaft gezeichnete Linie waere ein Element mehr, das nichts sagt. */
.sidebar__griff {
  position: absolute; top: 0; right: -3px; bottom: 0; width: 7px; z-index: 30;
  cursor: col-resize; background: transparent; transition: background .15s;
}
.sidebar__griff::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: 3px; width: 1px;
  background: transparent; transition: background .15s;
}
.sidebar__griff:hover::after,
.sidebar__griff:focus-visible::after,
body.is-resizing .sidebar__griff::after { background: var(--brand-500); }
.sidebar__griff:focus-visible { outline: none; }

/* Waehrend des Ziehens: kein Text markieren, ueberall derselbe Zeiger. Sonst
   blinkt er, sobald die Maus die Kante verlaesst, und halbe Ueberschriften
   stehen blau hinterlegt da. */
body.is-resizing { user-select: none; cursor: col-resize; }
body.is-resizing * { cursor: col-resize !important; }

.sidebar {
  background: var(--sidebar-bg);
  color: var(--sidebar-text);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
}
.sidebar__brand {
  display: flex; align-items: center; gap: 10px;
  height: var(--topbar-h); padding: 0 22px;
  color: #fff; font-family: var(--font-head); font-weight: 650; font-size: 19px; letter-spacing: -.01em;
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.brandmark { flex: none; border-radius: 22%; }
/* Menüfilter am Kopf der Leiste: bewusst unauffällig — ohne Rahmen, ohne
   eigene Fläche und ohne Symbol. Er ist ein Werkzeug für den Vielnutzer und
   soll die Punkte darunter nicht optisch überstimmen. */
.navfilter {
  display: flex; align-items: center;
  margin: 10px 14px 14px;
  color: var(--sidebar-muted);
}
.navfilter input {
  width: 100%; border: 0; background: transparent; outline: none;
  padding: 6px 8px; text-align: center;
  color: var(--sidebar-text); font: inherit; font-size: 13px;
}
.navfilter input::placeholder { color: var(--sidebar-muted); }
.navfilter:focus-within input::placeholder { color: var(--sidebar-text); }
/* Das WebKit-Kreuz sitzt im dunklen Feld schlecht und ist neben Escape entbehrlich. */
.navfilter input::-webkit-search-cancel-button { -webkit-appearance: none; }

/* Vom Filter weggeblendete Punkte und leer gewordene Rubriken. */
.nav-item.is-gefiltert, .navgruppe.is-gefiltert, .navfilter__leer.is-versteckt { display: none; }
.navfilter__leer { padding: 10px 18px; color: var(--sidebar-muted); font-size: 12.5px; }

.sidebar__section { padding: 18px 14px 6px; color: var(--sidebar-muted);
  font-size: 11px; text-transform: uppercase; letter-spacing: .1em; font-weight: 700; }
.sidebar__nav { flex: 1; overflow-y: auto; padding: 6px 12px 20px; }
.nav-item {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 12px; margin: 2px 0; border-radius: var(--radius-sm);
  color: var(--sidebar-text); font-weight: 500; cursor: pointer;
  transition: background .12s, color .12s;
}
.nav-item:hover { background: rgba(255,255,255,.06); color: #fff; text-decoration: none; }
/* Aktiv: grüne Tönung UND ein grüner Balken links. Die Farbe allein wäre für
   Farbfehlsichtige zu wenig — der Balken trägt die Aussage mit.
   Der Balken selbst steckt in .is-marked (weiter unten). */
.nav-item { position: relative; }
.nav-item.active { background: var(--sidebar-active-bg); color: var(--sidebar-active-text); }
.nav-item .ic { width: 18px; height: 18px; flex: none; opacity: .9; }
.nav-item .badge-count { margin-left: auto; font-size: 11px; background: var(--brand-500);
  color: var(--navy); font-weight: 700; border-radius: var(--radius-sm); padding: 1px 7px; }
.sidebar__foot { padding: 14px; border-top: 1px solid rgba(255,255,255,.08); }

/* ── Aktiv-Balken links (Seitenleiste) ──────────────────────────────────────
   EIN gerader Strich über die volle Höhe, mit rechtwinkligen Enden.
   Bewusst als Pseudo-Element und nicht als `box-shadow: inset 3px 0 0`: ein
   Inset-Schatten folgt dem border-radius des Elements und läuft an den Enden
   rund aus. Auch kein `border-left`, denn dessen Ecken werden mit border-top/
   -bottom auf Gehrung geschnitten — beides ergibt genau die abgewinkelten
   Enden, die hier nicht sein sollen.
   `bottom: -1px` schadet ohne Trennlinie darunter nicht und lässt den Balken
   sicher bis zur Unterkante laufen. */
.nav-item.active::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: -1px;
  width: 3px;
  background: var(--brand-500);
  border-radius: 0;
  pointer-events: none;
}

/* ── Hauptspalte ─────────────────────────────────────────────────────────── */
.main { display: flex; flex-direction: column; min-width: 0; height: 100vh; min-height: 0; }
.topbar {
  height: var(--topbar-h); background: var(--surface);
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 16px; padding: 0 24px;
  position: sticky; top: 0; z-index: 20;
  /* Nicht schrumpfen: die Topbar sitzt in der Flex-Spalte .main; auf
     fullHeight-Seiten (.content--fill) presste die hohe Content-Spalte den Kopf
     sonst zusammen → Topbar je Menüpunkt unterschiedlich hoch. */
  flex: none;
}
.topbar__spacer { flex: 1; }
.search {
  display: flex; align-items: center; gap: 8px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 7px 14px; color: var(--text-2);
  min-width: 260px; min-height: var(--control-h);
}
.search input { border: 0; background: transparent; outline: none; color: var(--text); width: 100%; font: inherit; font-size: 13px; }
.search--global { position: relative; min-width: 320px; transition: min-width .15s ease; }
.search--global:focus-within { min-width: 400px; border-color: var(--brand-500); }

.icon-btn {
  width: 38px; height: 38px; border-radius: var(--radius-sm); border: 1px solid var(--border);
  background: var(--surface); display: grid; place-items: center; cursor: pointer; color: var(--text-2);
}
.icon-btn:hover { background: var(--surface-2); color: var(--text); }
/* Dieselbe Kante wie Buttons und Badges (6px), kein Kreis: in der Kopfleiste
   steht der Avatar direkt neben den Symbol-Knöpfen, und ein Kreis daneben
   fiele aus der Reihe. */
.avatar { width: 38px; height: 38px; border-radius: var(--radius-sm); flex: none;
  background: var(--brand-500); color: var(--navy);
  display: grid; place-items: center; font-weight: 700; overflow: hidden; }
/* Mit Bild: cover, weil das Bild bereits quadratisch zugeschnitten ankommt. */
.avatar--img { object-fit: cover; background: var(--surface-2); }

/* ── Zuschnitt fürs Profilbild (web/js/avatar-crop.js) ───────────────────────
   Die Maske liegt ÜBER der Leinwand und nimmt keine Klicks an — sonst käme das
   Ziehen zum Verschieben nie bei der Leinwand an. */
.avatarcrop { position: relative; width: 100%; max-width: 320px; margin: 0 auto;
  aspect-ratio: 1; background: var(--surface-2);
  border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.avatarcrop__canvas { display: block; width: 100%; height: 100%; cursor: grab; touch-action: none; }
.avatarcrop__canvas:active { cursor: grabbing; }
/* Das Fenster hat dieselbe Form wie der spätere Avatar — abgerundetes Quadrat,
   kein Kreis. Es zeigt sonst einen Ausschnitt, den es hinterher nicht gibt.
   Die Fläche selbst ist durchsichtig, ihr nach AUSSEN laufender Schatten
   verdunkelt den Rest — einfacher und zuverlässiger als ein clip-path. */
.avatarcrop__maske { position: absolute; left: 50%; top: 50%;
  width: 88%; height: 88%; transform: translate(-50%, -50%);
  border-radius: 12px; pointer-events: none;
  box-shadow: 0 0 0 2000px rgba(0, 33, 71, .45), inset 0 0 0 1px rgba(255,255,255,.5); }

/* Status-Lämpchen in der Kopfleiste */
.sysleds { display: flex; align-items: center; gap: 14px; }
.sysled { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 600;
  color: var(--text-2); cursor: default; user-select: none; }
.sysled__dot { width: 9px; height: 9px; border-radius: 50%; background: var(--text-3); flex: none;
  transition: background .2s; }
.sysled.is-up .sysled__dot { background: var(--success); }
.sysled.is-down .sysled__dot { background: var(--danger); }

.content { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 28px 32px; width: 100%; }

/* ── Vollhöhen-Pane ──────────────────────────────────────────────────────────
   Ein einzelnes Pane füllt den Content-Bereich bis zum unteren Bildschirmrand
   und bekommt bei Überlauf einen eigenen Scrollbalken. Seite opt-in via
   $this->params['fullHeight'] = true (Layout setzt .content--fill), das Pane
   trägt .pane (i. d. R. am .card). Nicht bei mehreren Panes verwenden. */
.content--fill { display: flex; flex-direction: column; overflow: hidden; }
.content--fill > * { flex: none; }
.content--fill > .pane { flex: 1 1 auto; min-height: 0; }
.pane.card { display: flex; flex-direction: column; overflow: hidden; }
.pane.card > .card__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.content--fill > .pane:not(.card) { overflow-y: auto; }
/* Listen-Pane: Filterkopf und Blätterleiste stehen fest, die Tabelle dazwischen
   scrollt. Den klebenden Tabellenkopf bringt .tablewrap schon mit — nur seine
   feste max-height passt hier nicht: im Pane gibt der Bildschirm die Höhe vor.
   Ohne flex:none an Kopf und Fuß schrumpfen beide mit, sobald die Tabelle lang
   wird; sie sind die einzigen beiden Elemente, die genau das nicht sollen. */
.pane.card > .card__head, .pane.card > .pager { flex: none; }
.pane.card > .tablewrap { flex: 1 1 auto; min-height: 0; max-height: none; }
.pane.card > .empty { flex: 1 1 auto; }

/* Liste und ihre Auswertung nebeneinander, beide in voller Hoehe. Hoehere
   Spezifitaet als die Regel oben (.content--fill > .pane:not(.card)), sonst
   scrollte die ganze Spalte statt der Tabelle darin. */
.content--fill > .pane.pane--split { display: grid; overflow: hidden; align-items: stretch; }
.pane--split > .card { display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.pane--split > .card > .card__head { flex: none; }
.pane--split > .card > .tablewrap { flex: 1 1 auto; min-height: 0; max-height: none; }
.pane--split > .card > .card__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* Eine weitere Anschrift im Immobilienformular. Nur so viel Rahmen, dass die
   Zeilen als Gruppe lesbar bleiben — eine Karte je Anschrift waere fuer vier
   Felder zu viel Aufhebens. */
.anschrift { padding: 12px 0; border-bottom: 1px dashed var(--border); }
.anschrift:first-child { padding-top: 0; }
.anschrift:last-of-type { border-bottom: 0; }
.anschrift label { font-size: 12px; }

/* Firma oder Person — in einer gemischten Liste die erste Frage. Als Symbol
   und nicht als Wort: eine eigene Spalte dafuer waere Platz fuer eine Auskunft,
   die man mit einem Blick erfasst. */
.kontakt-ico { display: inline-grid; place-items: center; width: 26px; height: 26px; flex: none;
  border-radius: 7px; background: var(--surface-2); color: var(--text-2); }
.kontakt-ico svg { width: 15px; height: 15px; }

/* Kontakt-Auswahl (Select2): drei Zeilen je Treffer — Name, Zusammenhang,
   Anschrift. Der Name allein beantwortet nicht, welcher von zwei Meiers
   gemeint ist; genau dafuer ist die Liste da. */
.k2__name { font-weight: 600; color: var(--text); }
.k2__zusatz { font-size: 12.5px; color: var(--text-2); margin-top: 1px; }
.k2__adresse { font-size: 12px; color: var(--text-3); margin-top: 1px; }
/* Die Erreichbarkeit steht unten und leiser als die Anschrift: sie ist
   die Antwort auf die naechste Frage, nicht auf die gestellte. */
.k2__kontakt { font-size: 12px; color: var(--text-3); margin-top: 1px; }

/* Select2 traegt sein eigenes Aussehen mit. Hier nur so viel, dass es neben
   den uebrigen Feldern nicht wie ein Fremdkoerper wirkt: gleiche Hoehe,
   gleicher Rand, gleiche Rundung, gleiche Farben — auch im Dunkelmodus, wo
   die Vorgabe sonst weiss bleibt. */
/* Die Hoehe kommt aus derselben Angabe wie die der Eingabefelder. Fest
   eingetragene 38 Pixel waren vier zu wenig: Ein Auswahlfeld neben einem
   Textfeld stand vier Pixel niedriger, und in einer Zeile mit beidem sah die
   Reihe ausgefranst aus. */
.select2-container--default .select2-selection--single {
  height: var(--control-h); border: 1px solid var(--border); border-radius: 9px;
  background: var(--surface); color: var(--text); display: flex; align-items: center;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
  color: var(--text); line-height: calc(var(--control-h) - 2px); padding-left: 12px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
  height: calc(var(--control-h) - 2px);
}
.select2-dropdown {
  border: 1px solid var(--border); border-radius: 10px; background: var(--surface);
  box-shadow: var(--shadow-md, 0 8px 24px rgba(0,0,0,.12));
}
.select2-container--default .select2-results__option { color: var(--text); padding: 8px 12px; }
.select2-container--default .select2-results__option--highlighted[aria-selected] {
  background: var(--surface-2); color: var(--text);
}
.select2-container--default .select2-results__group {
  color: var(--text-3); font-size: 11.5px; text-transform: uppercase;
  letter-spacing: .05em; font-weight: 700; padding: 10px 12px 4px;
}

/* ── Die Einträge unter ihrer Gruppe ──────────────────────────────────────
   Eingerückt und mit einer Linie am Zweig: Ohne sie stehen Gruppenname und
   Einträge auf derselben Höhe, und aus der Gliederung wird eine Liste mit
   Zwischenüberschriften. Bei dreißig Objektarten in sechs Gruppen ist der
   Unterschied der zwischen Suchen und Finden. */
.select2-container--default .select2-results__options--nested {
  margin-left: 12px;
  border-left: 1px solid var(--border);
}
.select2-container--default .select2-results__options--nested .select2-results__option {
  padding-left: 12px;
}
/* Der erste Eintrag rückt an seine Gruppe heran. */
.select2-container--default .select2-results__group + .select2-results__options--nested {
  margin-top: 2px;
}
.select2-container--default .select2-search--dropdown .select2-search__field {
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface);
  color: var(--text); padding: 7px 10px;
}

/* Kontaktdaten neben einem Auswahlfeld (web/js/kontakt-karte.js).
   Abgesetzt, aber leiser als eine Karte: sie ist keine eigene Rubrik, sondern
   die Antwort auf "wen habe ich da gerade gewaehlt". */
/* Das Zeichen neben der Beschriftung zeigt dieselben Daten wie die Karte —
   nur dort, wo gerade gearbeitet wird. Eigenes Innenmass, weil die
   Kontaktzeilen keines mitbringen: .infoi__pop selbst ist randlos und verlaesst
   sich auf .infoi__text, den es hier nicht gibt. */
.kontaktpop { padding: 12px 14px; min-width: 250px; text-align: left; font-weight: 400; }
.kontaktpop .kontaktkarte__kopf { font-weight: 700; margin-bottom: 4px; }
.kontaktpop .kontaktkarte__zusatz { margin-bottom: 8px; }
.kontaktpop .info-row { padding: 3px 0; }
.kontaktpop .kontaktkarte__adresse { margin-top: 8px; padding-top: 8px; }

.kontaktkarte { margin-top: 12px; padding: 14px 16px; border: 1px solid var(--border);
  border-radius: var(--radius); background: var(--surface-2); }
.kontaktkarte__kopf { font-weight: 700; display: flex; align-items: center; gap: 8px;
  flex-wrap: wrap; margin-bottom: 2px; }
.kontaktkarte__zusatz { color: var(--text-2); font-size: 13px; margin-bottom: 10px; }
.kontaktkarte__adresse { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border);
  color: var(--text-2); font-size: 13px; line-height: 1.6; }
.kontaktkarte .info-row { padding: 4px 0; }

/* ── Erklaerung am Feld ──────────────────────────────────────────────────
   Ein Fragezeichen neben der Beschriftung statt einer grauen Zeile unter dem
   Feld. Der Grund ist Platz: bei dreissig Feldern war ein Drittel der Hoehe
   Text, den man einmal liest und danach nie wieder — und wo es eng wurde, ist
   die Erklaerung weggelassen worden.

   Es ist ein POPOVER und kein Tooltip: ein heller Kasten in der Formsprache der
   Seite, mit der gruenen Linie oben wie auf dem Webauftritt, fetter Ueberschrift
   und Haarlinie darunter, wenn es beides gibt. Ein dunkles Kaestchen mit einer
   Zeile Text saehe aus wie eine Systemmeldung; das hier gehoert zum Formular.

   Ohne JavaScript: der Griff ist ein <button>, und :hover/:focus genuegen.
   Hover zeigt es im Vorbeigehen, ein Klick haelt es offen — deshalb :focus und
   nicht :focus-visible, das bei der Maus nicht greift. */
.labelzeile { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
/* Der Abstand zum Feld sitzt an der Zeile, nicht am Label: sonst zaehlt er zur
   Hoehe des Labels, und das Zeichen daneben steht um genau diese sechs Pixel
   zu tief.

   DIE ERSTE FASSUNG DIESER REGEL HAT NIE GEGRIFFEN.

   Sie stand als `.labelzeile > label` da — dieselbe Spezifitaet wie
   `.form-group label { margin-bottom: 6px }` weiter unten in dieser Datei, und
   bei Gleichstand gewinnt die spaetere. Das Label behielt seine sechs Pixel,
   die Zeile wurde 26,8 statt 20,8 Pixel hoch, und jedes Feld MIT Erklaerung
   stand sechs Pixel tiefer als eines ohne. In einer Reihe aus beidem standen
   die Eingabefelder damit nicht auf einer Linie.

   Gemessen im Browser gegen das ausgelieferte Stylesheet, nicht geschaetzt:
   ohne 20,8 / mit 26,8. Deshalb hier mit `.form-group` davor — eine Klasse
   mehr, und die Regel gewinnt unabhaengig von der Reihenfolge. */
.labelzeile > label,
.form-group .labelzeile > label { margin: 0; }

/* ── UND AUS DEMSELBEN GRUND AUCH NICHT AM ZEICHEN ──────────────────────────
   `.infoi` bringt fuer den freistehenden Fall ein `margin-bottom: 6px` mit
   (siehe dort). In der Zeile ist dieser Abstand schon da — er steht an
   `.labelzeile` —, und ein zweites Mal zaehlt er zur Zeilenhoehe: das Zeichen
   misst dann 17 + 6 Pixel, die Beschriftung daneben nur ihre 19, und die Zeile
   richtet sich nach dem hoeheren.

   Sichtbar wurde es nicht am Zeichen, sondern UNTER dem Feld daneben: ein Feld
   mit Erklaerung stand vier Pixel tiefer als eines ohne, und in einer Reihe aus
   beidem standen die Eingabefelder nicht mehr auf einer Linie. */
.labelzeile > .infoi { margin-bottom: 0; }

/* `margin-bottom` wie bei `.form-group label`: das Zeichen steht NEBEN einer
   Beschriftung, und ohne denselben Abstand nach unten haengt es um sechs Pixel
   tiefer als das Wort, zu dem es gehoert. */
.infoi {
  position: relative; display: inline-grid; place-items: center;
  width: 17px; height: 17px; padding: 0; margin-bottom: 6px; flex: none;
  border: 0; background: transparent; color: var(--text-3); cursor: pointer;
  border-radius: 50%;
}
.infoi:hover, .infoi:focus { color: var(--brand-600); outline: none; }
.infoi:focus-visible { box-shadow: 0 0 0 2px var(--brand-100, rgba(70, 185, 114, .35)); }
.infoi__ico { width: 15px; height: 15px; display: block; }

.infoi__pop {
  position: absolute; bottom: calc(100% + 10px); left: 50%; transform: translateX(-50%);
  z-index: 60; width: max-content; max-width: 300px;
  background: var(--surface); color: var(--text);
  font-weight: 400; font-size: 12.5px; line-height: 1.55; text-align: left;
  border: 1px solid var(--border); border-radius: 10px; overflow: hidden;
  box-shadow: 0 10px 30px rgba(0, 33, 71, .16);
  /* visibility statt display: ohne sie gibt es keinen Uebergang, und das
     Erscheinen wirkt wie ein Sprung. */
  opacity: 0; visibility: hidden; transition: opacity .12s, visibility .12s;
  pointer-events: none; white-space: normal; cursor: default;
}
/* Die gruene Linie oben — dieselbe Handschrift wie auf dem Webauftritt. */
.infoi__pop::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: var(--brand-500);
}
.infoi__kopf {
  display: block; font-weight: 700; color: var(--navy);
  padding: 12px 14px 8px; margin-top: 3px;
}
/* Die Haarlinie steht nur zwischen zweien — ohne Ueberschrift gaebe es nichts
   zu trennen. */
.infoi__kopf + .infoi__text { border-top: 1px solid var(--border); padding-top: 10px; }
.infoi__text { display: block; padding: 12px 14px; color: var(--text-2); }
.infoi__kopf + .infoi__text { padding-top: 10px; }
.infoi__pop .num { color: var(--brand-ink); font-weight: 600; }

.infoi:hover .infoi__pop, .infoi:focus .infoi__pop { opacity: 1; visibility: visible; }

/* Am Rand einer Karte liefe es sonst heraus; dort haengt es an der Kante. */
.form-group:first-child .infoi__pop, .grid > .form-group:first-child .infoi__pop {
  left: 0; transform: none;
}

/* ── Einheitentabelle ──────────────────────────────────────────────────────
   Eine Tabelle, die sich wie ein Tabellenblatt bedienen laesst: enge Zeilen,
   Felder ohne eigenen Rahmen, sichtbar wird die Zelle erst, wenn man in ihr
   steht. Ein Formularfeld je Zelle mit Rand und Schatten waere ein Gitter aus
   Kaesten, in dem man die Zahlen nicht mehr liest. */
.einheiten td { padding: 0; }
.einheiten th { white-space: nowrap; }
.einheit__in {
  width: 100%; border: 0; background: transparent; padding: 7px 10px;
  font-family: inherit; font-size: 13px; color: var(--text); outline: none;
}
.einheit__in:focus { background: var(--brand-50, rgba(70, 185, 114, .08)); box-shadow: inset 0 0 0 2px var(--brand-500); }
.einheit__in::placeholder { color: var(--text-3); }
.einheiten .einheit__weg { text-align: right; padding-right: 6px; }
/* Die Zeile wird beim Ueberfahren nicht eingefaerbt: hier zielt man auf eine
   ZELLE, und ein wanderndes Band darunter macht das schwerer, nicht leichter. */
.einheiten tbody tr:hover { background: transparent; }


/* Unterlagenbaum.
   Die Einrueckung traegt die Struktur, nicht Rahmen oder Farben: ein Baum aus
   Kaesten liest sich wie eine Liste von Kaesten. Die senkrechte Linie zeigt,
   wohin ein Ast gehoert, ohne selbst gelesen werden zu wollen. */
.ubaum { list-style: none; margin: 0; padding: 0; }
.ubaum:not(.ubaum--wurzel) { margin-left: 13px; padding-left: 16px; border-left: 1px solid var(--border); }
.ubaum__ast { padding: 1px 0; }
.ubaum__zeile { display: flex; align-items: center; gap: 10px; padding: 5px 6px; border-radius: 7px; }
.ubaum__zeile:hover { background: var(--surface-2); }
.ubaum__nr { flex: none; min-width: 34px; font-size: 12px; color: var(--text-3);
  font-variant-numeric: tabular-nums; text-align: right; }
.ubaum__ico { display: inline-grid; place-items: center; width: 22px; height: 22px; flex: none;
  color: var(--text-3); }
.ubaum__ico svg { width: 14px; height: 14px; }
.ubaum__ast--rubrik > .ubaum__zeile > .ubaum__ico { color: var(--brand-600); }
.ubaum__ast--rubrik > .ubaum__zeile > .ubaum__name { font-weight: 700; }
.ubaum__name { flex: 1; min-width: 0; display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.ubaum__quelle { font-size: 12px; color: var(--text-3); white-space: nowrap; }
/* Die Aktionen erscheinen beim Beruehren der Zeile: dauerhaft sichtbar waeren
   es bei fuenfzig Eintraegen zweihundertfuenfzig Symbole. */
.ubaum__aktionen { display: inline-flex; gap: 1px; opacity: 0; transition: opacity .12s; }
.ubaum__zeile:hover .ubaum__aktionen,
.ubaum__aktionen:focus-within { opacity: 1; }
.ubaum__hinweis { font-size: 12px; color: var(--text-3); margin: -2px 0 4px 42px; }
.ubaum__ast--aus > .ubaum__zeile { opacity: .5; }

/* Hinweiskasten fuer offene Angaben — nicht rot.
   Was hier steht, ist kein Fehler: das Objekt darf unvollstaendig sein,
   solange daran gearbeitet wird. Ein roter Kasten sagte "du hast etwas falsch
   gemacht"; gemeint ist "hier ist noch etwas zu tun". Deshalb Bernstein und
   eine ruhige Flaeche statt eines Alarms. */
.hinweisbox {
  background: var(--amber-50, #fffaf0); border: 1px solid var(--amber-200, #fde68a);
  border-left: 3px solid var(--warning, #d97706);
  border-radius: var(--radius); padding: 14px 16px; margin-bottom: 20px;
}
.hinweisbox__kopf {
  display: flex; align-items: center; gap: 8px;
  font-weight: 700; font-size: 13.5px; color: var(--text); margin-bottom: 8px;
}
.hinweisbox__kopf svg { width: 16px; height: 16px; flex: none; color: var(--warning, #d97706); }
.hinweisbox__liste { margin: 0 0 8px; padding-left: 20px; font-size: 13px; color: var(--text-2); }
.hinweisbox__liste li { margin-bottom: 3px; }
.hinweisbox__liste li:last-child { margin-bottom: 0; }
.hinweisbox__fuss { font-size: 12px; color: var(--text-3); }

:root[data-theme="dark"] .hinweisbox {
  background: rgba(217, 119, 6, .08); border-color: rgba(217, 119, 6, .3);
}

/* Telefonnummer mit Landesvorwahl.
   Der Waehler sitzt IM Feld, nicht daneben: er gehoert zur Nummer und ist
   keine zweite Eingabe. Deshalb eine gemeinsame Umrandung, in der nur die
   Trennlinie beide auseinanderhaelt. */
.telfeld { display: flex; align-items: stretch;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface);
  transition: border-color .15s, box-shadow .15s; }
.telfeld:focus-within { border-color: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-50, rgba(70,185,114,.15)); }
.telfeld__land {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  padding: 0 8px 0 12px; font-size: 14px; color: var(--text-2);
  border-right: 1px solid var(--border); flex: none;
  font-family: inherit;
}
.telfeld__land:focus { outline: none; }
.telfeld__nummer.input {
  border: 0; background: transparent; border-radius: 0; flex: 1; min-width: 0;
}
.telfeld__nummer.input:focus { outline: none; box-shadow: none; }

/* Trennung zwischen zwei gleichwertigen Wegen — Passwort oder Passkey.
   Das Wort sitzt IN der Linie, nicht darueber: es trennt die beiden, es
   ueberschreibt nicht den unteren. Die Pseudoelemente nehmen den Platz links
   und rechts, dadurch steht es in jeder Breite mittig. */
.trenner { display: flex; align-items: center; gap: 12px; margin: 24px 0 18px;
  color: var(--text-3); font-size: 12.5px; text-transform: lowercase; }
.trenner::before, .trenner::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.passkey-block .hint { min-height: 18px; margin-top: 10px; }

/* Balken fuer kleine Auswertungen neben einer Liste. Bewusst aus zwei divs
   statt eines Diagramms: es gibt nichts zu zoomen, nichts zu schwenken und
   keine Achse — eine Bibliothek dafuer waere mehr Ladezeit als Aussage. */
.vbars { display: flex; flex-direction: column; gap: 9px; }
.vbar__kopf { display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  font-size: 12.5px; margin-bottom: 3px; }
.vbar__label { color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vbar__val { color: var(--text); font-weight: 700; font-variant-numeric: tabular-nums; flex: none; }
.vbar__track { height: 6px; border-radius: 3px; background: var(--surface-2); overflow: hidden; }
.vbar__fill { height: 100%; border-radius: 3px; background: var(--brand-500); min-width: 2px; }

/* Stapelspuren, Kopfzeilen, Textfassungen: unveraenderte Maschinenausgabe.
   Umgebrochen statt waagerecht scrollend — in einer Fehlermeldung steht das
   Entscheidende oft am Zeilenende, und dorthin scrollt niemand. */
.logdump { margin: 6px 0 0; padding: 10px 12px; max-height: 320px; overflow: auto;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px;
  font-family: ui-monospace, Consolas, monospace; font-size: 12px; line-height: 1.5;
  color: var(--text-2); white-space: pre-wrap; word-break: break-word; }

/* ── Seitenkopf ──────────────────────────────────────────────────────────────
   FESTE Höhe auf jeder Seite — sonst „springt" der Inhalt beim Wechsel der
   Menüpunkte. Bewusst mit `.content `-Präfix (höhere Spezifität): das geteilte
   yii2kit-Widget bringt sein EIGENES pagehead.css mit, das die nackten
   .page-head-Regeln sonst überschriebe. */
.content .page-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 22px;
    gap: 16px; flex-wrap: nowrap; height: 64px; min-height: 0; }
.content .page-head h1 { font-size: 24px; margin: 0; }
.content .page-head__main, .content .page-head > div:not([class]):first-child { min-width: 0; min-height: 0;
    display: flex; flex-direction: column; justify-content: center; }
.page-head__lead { display: flex; align-items: center; gap: 12px; min-width: 0; }
.page-head__back { line-height: 1.3; margin-bottom: 2px; }
.content .page-head__actions { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; flex: none; }
/* Detailseiten mit reichhaltigem Kopf sind KEINE Menüpunkte — sie dürfen höher
   sein und ihren Untertitel umbrechen. */
.content .page-head--free { height: auto; min-height: 64px; align-items: flex-start; flex-wrap: wrap; }
.content .page-head--free .sub { white-space: normal; overflow: visible; }
/* Abschnitts-Symbol vor der Überschrift (zentral per Layout eingesetzt). */
.page-head__ico { width: 22px; height: 22px; flex: none; margin-right: 10px;
    color: var(--brand-600); vertical-align: -3px; }
.content .page-head .sub { color: var(--text-2); font-size: 13px; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis; max-width: 100%; }

/* ── Karten ──────────────────────────────────────────────────────────────── */
.card { background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-sm); }

/* ── ZWEI KARTEN UNTEREINANDER BRAUCHEN LUFT ────────────────────────────────
   `.card` trug keinen Aussenabstand. Wo eine Karte allein steht, ist das
   richtig — den Abstand nach oben setzt das Umfeld. Stehen aber zwei
   untereinander, beruehren sich ihre Raender, und aus zwei Karten wird optisch
   ein Kasten mit einer Trennlinie: genau das war bei der Identifizierung zu
   sehen (Angaben, Ausweis, PEP, Unterlagen in einer Spalte).

   Drei Ansichten hatten sich mit einem `mt-3` von Hand beholfen, 110 Karten
   standen ohne. Das ist der Beweis, dass es an die Regel gehoert und nicht an
   den Aufruf: was man an jeder Stelle wiederholen muss, wird an den meisten
   vergessen.

   Als Geschwisterregel und nicht als `margin-top` an `.card`: eine einzelne
   oder die erste Karte bekommt dadurch keinen Abstand, den sie nicht haben
   soll (gemessen: 0).

   Die drei handgesetzten `mt-3` an gestapelten Karten sind damit wirkungslos —
   zwei Klassen schlagen eine, unabhaengig von der Reihenfolge in dieser Datei.
   Sie bekommen jetzt dieselben 16 statt eigener 12 Pixel, und das ist der
   Zweck: ein Abstand, nicht drei. */
.card + .card { margin-top: 16px; }
.card__head { padding: 16px 20px; border-bottom: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.card__head h3 { font-size: 16px; margin: 0; display: inline-flex; align-items: center; gap: 9px; min-width: 0; }
.card-title__ico { width: 17px; height: 17px; flex: none; color: var(--brand-600); }
.card__body { padding: 20px; }
.card__foot { padding: 14px 20px; border-top: 1px solid var(--border); display: flex; gap: 10px; }

/* ── Raster ──────────────────────────────────────────────────────────────── */
/* Karten untereinander: der Abstand gehört an den Container, nicht an die
   Karte. Mit margin-bottom an jeder Karte außer der letzten stimmt das Bild
   nur so lange, bis jemand eine Karte verschiebt — dann fehlt oben ein Abstand
   und unten hängt einer zu viel. Genau das ist beim Umzug von "Meine
   Mandanten" passiert. 20px, damit es dem gap des Rasters entspricht. */
.stack { display: flex; flex-direction: column; gap: 20px; }

.grid { display: grid; gap: 20px; }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
/* Automatisches Kartenraster für Objekt-Kacheln (Mandanten, Nutzer, …): füllt
   die Breite und bricht von selbst um — kein Media-Query nötig. */
.grid-auto { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }

/* Kennzahl-Kacheln */
.stat { background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 18px 20px; box-shadow: var(--shadow-sm);
  display: flex; flex-direction: column; gap: 6px; }
.stat__top { display: flex; align-items: center; justify-content: space-between; }
.stat__label { color: var(--text-2); font-size: 12.5px; font-weight: 500; }
.stat__value { font-family: var(--font-head); font-size: 28px; letter-spacing: -.02em; color: var(--navy); }
:root[data-theme="dark"] .stat__value { color: var(--text); }
.stat__icon { width: 42px; height: 42px; border-radius: 11px; display: grid; place-items: center;
  background: var(--brand-50); color: var(--brand-600); }
:root[data-theme="dark"] .stat__icon { background: rgba(70,185,114,.15); color: var(--brand-500); }
.stat__delta { font-size: 12px; font-weight: 600; }
.stat__delta.up { color: var(--brand-600); }
.stat__delta.down { color: var(--danger); }

/* Objekt-Kachel im Kartenraster (.grid-auto) — klickbar, hebt beim Überfahren an. */
.tile { display: flex; flex-direction: column; gap: 8px; padding: 16px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  color: var(--text); cursor: pointer; transition: box-shadow .12s, border-color .12s; }
.tile:hover { box-shadow: var(--shadow-md); border-color: var(--brand-500); text-decoration: none; color: var(--text); }
.tile__head { display: flex; align-items: center; gap: 10px; min-width: 0; }
.tile__title { font-weight: 600; min-width: 0; }
.tile__meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* ── Buttons ─────────────────────────────────────────────────────────────────
   Kanten wie auf bewerter-immobilien.de: leicht gebrochen (6 px), nicht
   Pillenform. Der Primär-Button ist grün mit NAVY-Schrift (nicht weiß) — genau
   so steht er auf der Website, und Navy auf Grün trägt 6,3:1, weiß nur 2,3:1. */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; cursor: pointer;
  font-family: inherit; font-size: 13.5px; font-weight: 600; line-height: 1;
  padding: 10px 20px; min-height: var(--control-h);
  border-radius: var(--radius-sm); border: 1.5px solid transparent;
  transition: background .15s, border-color .15s, color .15s, box-shadow .15s; white-space: nowrap; }
.btn:hover { text-decoration: none; }
.btn-primary { background: var(--brand-500); border-color: var(--brand-500); color: var(--navy); }
.btn-primary:hover { background: var(--brand-600); border-color: var(--brand-600); color: #fff; }
.btn-ghost { background: transparent; color: var(--navy); border-color: var(--border); }
.btn-ghost:hover { background: var(--navy); border-color: var(--navy); color: #fff; }
:root[data-theme="dark"] .btn-ghost { color: var(--text); }
:root[data-theme="dark"] .btn-ghost:hover { background: var(--surface-2); border-color: var(--brand-500); color: #fff; }
.btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn-danger:hover { background: #b93b37; border-color: #b93b37; color: #fff; }
.btn-sm { padding: 7px 16px; font-size: 12.5px; min-height: 34px; }
.btn-block { width: 100%; }
.btn svg { width: 15px; height: 15px; flex: none; }

/* ── Listen: Symbol-Aktionen + anklickbare Zeilen (app-weit einheitlich) ─────
   In Tabellen Aktionen als Symbol-Buttons (.iact) statt Text; fehlende
   Aktionen bekommen einen leeren Platzhalter (.iact--empty), damit die Symbole
   spaltenweise untereinander stehen. Eine Zeile mit data-href öffnet ihr Ziel
   (web/js/row-open.js). */
.row-acts { display: inline-flex; gap: 2px; justify-content: flex-end; }
.iact { display: inline-grid; place-items: center; width: 30px; height: 30px; border-radius: 7px;
  color: var(--text-2); flex: none; }
.iact:hover { background: var(--surface-2); color: var(--navy); text-decoration: none; }
.iact svg { width: 16px; height: 16px; }
.iact--danger:hover { color: var(--danger); }
.iact--empty { pointer-events: none; }
/* Ein Schalter, der AN ist — nicht nur eine Aktion, die man ausloesen kann.
   Ohne Farbe stuende der Haken „beim Abgleich mitholen" nirgends geschrieben. */
.iact--an { color: var(--brand-600); background: var(--brand-50, var(--surface-2)); }
tr[data-href] { cursor: pointer; }
tr[data-href]:hover > td { background: var(--surface-2); }

/* ── Badges ──────────────────────────────────────────────────────────────────
   Gleiche Kante wie die Buttons: in einer Tabellenzeile stehen beide
   nebeneinander, unterschiedliche Rundungen fielen sofort auf. */
.badge { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600;
  padding: 3px 10px; border-radius: var(--radius-sm); }
/* Symbol im Badge: „flex: none" verhindert, dass es in engen Tabellenspalten
   zusammengequetscht wird, während der Text umbricht. */
.badge__ico { width: 13px; height: 13px; flex: none; }
.btn .badge__ico { width: 15px; height: 15px; }
.badge-gray   { background: var(--surface-2); color: var(--text-2); border: 1px solid var(--border); }
.badge-green  { background: rgba(70,185,114,.16); color: var(--brand-700); }
.badge-amber  { background: rgba(224,168,0,.18); color: #8a6300; }
.badge-red    { background: rgba(217,83,79,.14); color: #a8322e; }
.badge-blue   { background: rgba(12,58,110,.10); color: var(--navy-mid); }
.badge-indigo { background: rgba(0,161,163,.14); color: #007678; }
:root[data-theme="dark"] .badge-green  { color: #7fd3a2; }
:root[data-theme="dark"] .badge-amber  { color: #e5bd4c; }
:root[data-theme="dark"] .badge-red    { color: #f0918e; }
:root[data-theme="dark"] .badge-blue   { background: rgba(127,176,232,.15); color: #a9cbf2; }
:root[data-theme="dark"] .badge-indigo { color: #4fd3d5; }
.dot { width: 7px; height: 7px; border-radius: 50%; }

/* Dateityp-Kürzel (Badge::fileType) */
.ftype { display: inline-block; padding: 1px 6px; border-radius: 4px; color: #fff;
  font-size: 10px; font-weight: 800; letter-spacing: .03em; line-height: 1.5; }

/* Schalter */
.switch { position: relative; display: inline-flex; align-items: center; gap: 10px; cursor: pointer; user-select: none; }
.switch__input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch__track { position: relative; width: 44px; height: 24px; border-radius: var(--radius-pill);
  background: var(--border); transition: background .18s ease; flex: none; }
.switch__thumb { position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0,33,71,.3); transition: transform .18s ease; }
.switch__input:checked + .switch__track { background: var(--brand-500); }
.switch__input:checked + .switch__track .switch__thumb { transform: translateX(20px); }
.switch__input:focus-visible + .switch__track { box-shadow: 0 0 0 3px rgba(70,185,114,.35); }
.switch__text { font-weight: 600; font-size: 14px; }
.switch__text svg { width: 15px; height: 15px; flex: none; }
/* Steht ein Schalter still, weil es nichts zu schalten gibt, sagt er das auch. */
.switch:has(.switch__input:disabled) { cursor: default; }
.switch__input:disabled + .switch__track { opacity: .45; }
.switch__input:disabled ~ .switch__text { opacity: .55; }

/* ── Reiter ──────────────────────────────────────────────────────────────── */
.ftabs__nav { display: flex; gap: 2px; flex-wrap: wrap; border-bottom: 1px solid var(--border); margin: 0 0 20px; }
.ftabs__tab { display: inline-flex; align-items: center; gap: 7px; appearance: none; border: 0; background: transparent;
    padding: 10px 16px; font-size: 14px; font-weight: 600; color: var(--text-2); cursor: pointer;
    border-bottom: 2px solid transparent; margin-bottom: -1px; border-radius: 8px 8px 0 0; }
.ftabs__tab:hover { color: var(--navy); background: var(--surface-2); text-decoration: none; }
:root[data-theme="dark"] .ftabs__tab:hover { color: var(--text); }
.ftabs__tab.is-active { color: var(--navy); border-bottom-color: var(--brand-500); }
:root[data-theme="dark"] .ftabs__tab.is-active { color: var(--text); }
.ftabs__ico { width: 15px; height: 15px; flex: none; }
/* Reiter INNERHALB einer Seite (web/js/ftabs.js). Ohne JavaScript steht
   jeder Abschnitt untereinander und das Formular bleibt vollstaendig — erst
   das Skript setzt `ftabs--js` und blendet die uebrigen aus. */
.ftabs--js .ftabs__pane { display: none; }
.ftabs--js .ftabs__pane.is-active { display: block; }
/* Als Reiter dient hier ein <button>: er schaltet um, statt zu navigieren. */
.ftabs__nav button.ftabs__tab { font-family: inherit; }

/* ── Mandanten-Zeichen ───────────────────────────────────────────────────────
   Logo oder Anfangsbuchstabe. Abgerundetes Quadrat statt Kreis — ein Kreis
   würde breite Wort-Logos an beiden Enden abschneiden. */
.tmark { flex: none; border-radius: 22%; display: grid; place-items: center; overflow: hidden; }
/* contain, nicht cover: das ganze Logo soll zu sehen sein, auch quer. */
.tmark--img { object-fit: contain; background: var(--surface-2); }
.tmark--initial { background: var(--navy); color: #fff; font-weight: 700; letter-spacing: -.01em; user-select: none; }
/* In der dunklen Seitenleiste braucht ein Logo mit weißer Schrift etwas Fläche. */
.sidebar .tmark--img { background: rgba(255,255,255,.08); }
.sidebar .tmark--initial { background: var(--brand-500); color: var(--navy); }

.logo-up { display: flex; gap: 14px; align-items: flex-start; }
.logo-up__ctl { flex: 1; min-width: 0; }

/* ── Mandanten-Umschalter (Topbar) ───────────────────────────────────────────
   Ersetzt das <select>: zeigt Logo und die Verschachtelung von Unter-Mandanten,
   was ein natives Auswahlfeld nicht kann. */
.tswitch { position: relative; }
.tswitch__btn { display: inline-flex; align-items: center; gap: 8px; min-width: 200px; max-width: 280px;
  padding: 6px 12px; min-height: var(--control-h); border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text); cursor: pointer; font: inherit; }
/* Der Name schiebt den Pfeil nach rechts, statt daneben zu kleben — sonst wirkt
   der Knopf bei kurzen Namen halbleer. */
.tswitch__btn .tswitch__name { flex: 1; text-align: left; }
.tswitch__btn:hover { background: var(--surface-2); }
.tswitch__name { font-size: 13px; font-weight: 600; }
.tswitch__caret { color: var(--text-3); flex: none; }
.tswitch__menu { position: absolute; top: calc(100% + 6px); right: 0; z-index: 40;
  min-width: 260px; max-width: 340px; max-height: 60vh; overflow-y: auto;
  padding: 6px; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-lg); }
.tswitch__item { display: flex; align-items: center; gap: 9px; padding: 7px 12px;
  border-radius: var(--radius-sm); color: var(--text); font-size: 13.5px; }
.tswitch__item:hover { background: var(--surface-2); text-decoration: none; color: var(--text); }
.tswitch__item.is-active { background: var(--brand-50); color: var(--brand-700); font-weight: 600; }
:root[data-theme="dark"] .tswitch__item.is-active { background: rgba(70,185,114,.18); color: #7fd3a2; }
.tswitch__item .tswitch__name { flex: 1; min-width: 0; font-weight: 500; }
.tswitch__item.is-active .tswitch__name { font-weight: 600; }
.tswitch__branch { color: var(--text-3); flex: none; font-size: 12px; margin-right: -2px; }
.tswitch__check { color: var(--brand-600); flex: none; }

/* ── Facetten (Filter-Chips) ─────────────────────────────────────────────────
   Als <a> oder <button> verwendbar; „is-active" markiert die gewählte Facette. */
.facets { display: flex; gap: 6px; flex-wrap: wrap; padding: 10px 18px; border-bottom: 1px solid var(--border); }
.facet { display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px; border-radius: var(--radius-sm);
  font-size: 12.5px; font-weight: 600; color: var(--text-2); border: 1px solid var(--border);
  background: var(--surface); cursor: pointer; }
.facet:hover { background: var(--surface-2); color: var(--navy); text-decoration: none; }
.facet.is-active { background: var(--brand-50); color: var(--brand-700); border-color: var(--brand-500); }
:root[data-theme="dark"] .facet.is-active { background: rgba(70,185,114,.18); color: #7fd3a2; }
.facet__n { font-size: 11px; opacity: .7; }
/* Ohne Groesse fuellte ein Symbol-SVG die ganze Chip-Hoehe. */
.facet svg { width: 14px; height: 14px; flex: none; }

/* Ein Kaestchen IM Chip: die Facetten der Kontaktliste sind Filter, die sich
   addieren, und ein Haken sagt das, was eine Einfaerbung allein nur andeutet.
   Nativ und nicht nachgebaut — Tastatur, Vorlesen und die Dreiviertelsekunde
   Arbeit sind so schon erledigt. */
.facet__box { width: 14px; height: 14px; margin: 0; flex: none; cursor: pointer;
  accent-color: var(--brand-600); }
label.facet { user-select: none; }
label.facet:focus-within { outline: 2px solid var(--brand-500); outline-offset: 1px; }

/* ── Spalten ziehen (js/spalten-ziehen.js) ───────────────────────────────────
   Der Griff steht VOR dem Spaltennamen und bleibt blass, bis der Zeiger auf
   der Spalte steht: eine Tabelle mit acht dauerhaft sichtbaren Griffen liest
   sich wie ein Werkzeugkasten und nicht wie eine Liste. */
.th-griff { display: inline-block; margin-right: 6px; color: var(--text-3); cursor: grab;
  opacity: .35; font-size: 11px; line-height: 1; letter-spacing: -1px; touch-action: none; }
th:hover .th-griff { opacity: .8; }
.th-griff:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 2px; opacity: 1; }
th.is-zieht { background: var(--brand-50); }
th.is-zieht .th-griff { cursor: grabbing; opacity: 1; }
:root[data-theme="dark"] th.is-zieht { background: rgba(70,185,114,.18); }

/* ── Ansichts-Umschalter Liste/Karten ────────────────────────────────────── */
.viewtoggle { display: inline-flex; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; flex: none; }
.viewtoggle__btn { display: grid; place-items: center; width: 34px; height: 32px; color: var(--text-2);
  background: var(--surface); cursor: pointer; }
.viewtoggle__btn + .viewtoggle__btn { border-left: 1px solid var(--border); }
.viewtoggle__btn:hover { background: var(--surface-2); color: var(--navy); }
.viewtoggle__btn.is-active { background: var(--brand-50); color: var(--brand-700); }
:root[data-theme="dark"] .viewtoggle__btn.is-active { background: rgba(70,185,114,.18); color: #7fd3a2; }
.viewtoggle__btn svg { width: 16px; height: 16px; }

/* ── Tabellen ────────────────────────────────────────────────────────────── */
.table { width: 100%; border-collapse: collapse; }
.table th { text-align: left; font-size: 11.5px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-3); font-weight: 700; padding: 11px 16px; border-bottom: 1px solid var(--border); }
.table td { padding: 13px 16px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.table tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--surface-2); }
.table .muted { color: var(--text-2); }
.table code { font-family: ui-monospace, Consolas, monospace; font-size: 12.5px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 4px; padding: 1px 5px; }

/* ── Feststehender Tabellenkopf ──────────────────────────────────────────────
   Wirkt nur, wenn die Tabelle in einem Element mit eigenem Scrollbalken sitzt
   (.tablewrap) — position:sticky richtet sich am nächsten scrollenden Vorfahren
   aus. Der Hintergrund MUSS gesetzt sein, sonst scheinen die Zeilen durch.
   border-bottom am th statt an der Zeile: gemeinsame Ränder werden beim
   Scrollen mit weggeschoben. */
.tablewrap { overflow: auto; max-height: 560px; }

/* Karte mit fester Hoehe: Kopf und Blaetterleiste stehen, die Liste dazwischen
   scrollt. Fuer Karten, die neben anderen Karten stehen und deren Zeilenzahl
   niemand kennt — angemeldete Geraete etwa. Ohne flex:none an Kopf und Fuss
   schrumpfen beide mit, sobald die Liste laenger wird; sie sind die einzigen
   beiden Elemente, die genau das nicht sollen. Die Hoehe haengt an
   --liste-h, damit eine Ansicht sie setzen kann, ohne die Regel zu kopieren. */
.card--liste { display: flex; flex-direction: column; }
.card--liste > .card__head, .card--liste > .pager { flex: none; }
.card--liste > .tablewrap { flex: 1 1 auto; min-height: 0; max-height: var(--liste-h, 320px); }
.card--liste > .pager { flex-wrap: nowrap; }
.tablewrap .table thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--surface); border-bottom: 1px solid var(--border);
}
/* Filterzeile klebt direkt unter den Spaltennamen. Die Höhe ist fest, damit
   `top` ohne JavaScript stimmt. */
.tablewrap .table thead tr.tfilter th {
  top: 38px; z-index: 1; padding: 6px 10px 8px;
  background: var(--surface); border-bottom: 1px solid var(--border);
}
.tfilter__in {
  width: 100%; min-width: 0; height: 30px; padding: 4px 9px;
  font: inherit; font-size: 12.5px; font-weight: 400; text-transform: none; letter-spacing: 0;
  color: var(--text); background: var(--surface-2);
  border: 1px solid var(--border); border-radius: var(--radius-sm); outline: none;
}
.tfilter__in:focus { border-color: var(--brand-500); background: var(--surface); }
.tfilter__in::placeholder { color: var(--text-3); font-weight: 400; }
/* Filter-Auswahl (Stufe) genauso hoch wie die Textfilter daneben. */
.tfilter__in.input { height: 30px; }
/* Sortierbarer Spaltenkopf: wirkt wie die Ueberschrift, reagiert auf Klick. */
.th-sort { color: inherit; text-decoration: none; display: inline-flex; align-items: center; gap: 3px; cursor: pointer; }
.th-sort:hover, .th-sort--aktiv { color: var(--brand-600); }
/* Kundenkuerzel in der Namensspalte — schmal, einfarbig, monospaced. */
.kontakt-kuerzel { font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-size: 11px;
    color: var(--text-3); background: var(--surface-2); border-radius: var(--radius-sm);
    padding: 1px 6px; flex: none; letter-spacing: .02em; }
/* „Keine Treffer" wird vom Skript eingeblendet. */
.tablewrap__empty { padding: 28px 16px; text-align: center; color: var(--text-3); }
/* Treffer-Zähler unter der gefilterten Tabelle (web/js/table-filter.js). */
.tfilter__zaehler { padding: 10px 4px 2px; color: var(--text-3); font-size: 12.5px; }

/* ── Gruppenzeile in Listen ──────────────────────────────────────────────────
   Trennt zwei Gruppen (z. B. Firmen und Personen) innerhalb EINER Tabelle.
   Zwei Tabellen waeren die naheliegende Loesung und die falsche: dann haette
   jede ihren eigenen Kopf, ihre eigene Filterzeile und ihre eigene Breite. */
.table tr.tgroup td,
.table tbody tr.tgroup:hover td {
  padding: 9px 16px; background: var(--surface-2);
  border-bottom: 1px solid var(--border); cursor: default;
}
.tgroup__label { display: inline-flex; align-items: center; gap: 8px;
  font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-2); }
.tgroup__label svg { width: 14px; height: 14px; color: var(--brand-600); }
.tgroup__n { font-weight: 600; letter-spacing: 0; color: var(--text-3); }

/* ── Zeitstempel: Datum oben, relative Angabe darunter ───────────────────── */
.stamp { display: inline-flex; flex-direction: column; line-height: 1.35; }
.stamp__abs { font-size: 13px; white-space: nowrap; }
.stamp__rel { font-size: 11.5px; color: var(--text-3); white-space: nowrap; }

/* ── Herkunft einer IP: Flagge + Ort/Land über der Adresse ───────────────── */
.iploc { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; max-width: 100%; }
.iploc__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text-3); flex: none; }
.ipcell { display: inline-flex; flex-direction: column; gap: 1px; line-height: 1.35; min-width: 0; }
.ipcell__addr { font-size: 13px; white-space: nowrap; }

/* Sortierbare Zeilenliste (web/js/row-list.js) */
.rowlist__row { display: flex; align-items: center; gap: 8px; padding: 6px; border: 1px solid var(--border);
    border-radius: var(--radius-sm); background: var(--surface); margin-bottom: 6px; }
.rowlist__row.is-dragging { opacity: .45; }
.rowlist__grip { cursor: grab; color: var(--text-3); user-select: none; padding: 0 2px; letter-spacing: -2px; }
.rowlist__grip:active { cursor: grabbing; }
.rowlist__num { color: var(--text-3); font-size: 12px; font-weight: 700; min-width: 18px; text-align: right; }
.rowlist__del { appearance: none; border: 0; background: transparent; color: var(--text-3); cursor: pointer;
    font-size: 18px; line-height: 1; padding: 2px 6px; border-radius: 6px; }
.rowlist__del:hover { background: var(--surface-2); color: var(--danger); }
.rowlist__empty { padding: 8px 2px; }

/* ── Blätterleiste ───────────────────────────────────────────────────────────
   ACHTUNG beim Anpassen: hier läuft yii\widgets\LinkPager, NICHT die
   Bootstrap-Variante. Der erzeugt
       ul.pagination > li[.first|.prev|.active|.disabled|.next|.last] > a
   mit KLASSENLOSEM <a>; deaktivierte Buttons haben ein <span> statt <a>.
   Regeln müssen daher am li ansetzen. Ohne diese Regeln steht da eine
   Aufzählung mit Punkten — das Theme bringt kein Bootstrap mit. */
.pager { display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 12px 16px; border-top: 1px solid var(--border); flex-wrap: wrap; }
.pagination { display: flex; align-items: center; gap: 4px; list-style: none; margin: 0; padding: 0; }
.pagination li { display: block; }
.pagination li > a,
.pagination li > span {
  display: grid; place-items: center; min-width: 32px; height: 32px; padding: 0 9px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text-2);
  font-size: 13px; font-weight: 600; line-height: 1; text-decoration: none;
  transition: background .12s, color .12s, border-color .12s;
}
.pagination li > a:hover { background: var(--surface-2); color: var(--navy); text-decoration: none; }
.pagination li.active > a,
.pagination li.active > span { background: var(--navy); border-color: var(--navy); color: #fff; }
/* Deaktiviert (erste/letzte Seite): sichtbar da, aber erkennbar tot. */
.pagination li.disabled > a,
.pagination li.disabled > span { opacity: .45; pointer-events: none; }

/* ── Formulare ───────────────────────────────────────────────────────────── */
.form-group { margin-bottom: 16px; }
.form-group label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 6px; color: var(--text); }
.form-group label.switch { display: inline-flex; margin: 0; }
.input, textarea.input, select.input {
  width: 100%; font-family: inherit; font-size: 14px; color: var(--text);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px 13px; outline: none; transition: border-color .12s, box-shadow .12s; }
input.input, select.input { height: var(--control-h); }
.input:focus { border-color: var(--brand-500); box-shadow: 0 0 0 3px rgba(70,185,114,.25); }
.input::placeholder { color: var(--text-3); }
/* Gesperrte Felder grau: das Kundenkuerzel etwa vergibt das Haus, es steht nur
   da. Ohne diese Regel sieht ein `disabled`-Feld aus wie ein leeres, das man
   ausfuellen soll. `-webkit-text-fill-color`, weil WebKit den Text sonst
   eigenmaechtig aufhellt. */
.input:disabled {
  background: var(--surface-2);
  color: var(--text-3);
  -webkit-text-fill-color: var(--text-3);
  cursor: default;
}
/* ── Schieberegler ───────────────────────────────────────────────────────────
   Für Zahlen mit sinnvollem Bereich: der Regler zeigt die Spanne mit, ein
   Eingabefeld nicht. Der Wert steht daneben im Klartext — ohne ihn wäre die
   genaue Zahl nur zu erraten. */
.rangefield__top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 6px; }
.rangefield__val { font-family: var(--font-head); font-size: 15px; color: var(--navy); white-space: nowrap; }
:root[data-theme="dark"] .rangefield__val { color: var(--text); }
.rangefield__row { display: flex; align-items: center; gap: 10px; }
.rangefield__bound { font-size: 11px; color: var(--text-3); flex: none; }
.range {
  -webkit-appearance: none; appearance: none;
  flex: 1; min-width: 0; height: 4px; padding: 0; margin: 8px 0;
  background: var(--border); border: 0; border-radius: 999px; outline: none; cursor: pointer;
}
.range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--brand-500); border: 2px solid var(--surface);
  box-shadow: 0 1px 4px rgba(0,33,71,.35); cursor: grab;
}
.range::-webkit-slider-thumb:active { cursor: grabbing; }
.range::-moz-range-thumb {
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--brand-500); border: 2px solid var(--surface);
  box-shadow: 0 1px 4px rgba(0,33,71,.35); cursor: grab;
}
.range::-moz-range-track { height: 4px; background: var(--border); border-radius: 999px; }
.range:focus-visible { box-shadow: 0 0 0 3px rgba(70,185,114,.35); }
.range:disabled { opacity: .45; cursor: default; }

/* ── Kleiner HTML-Editor (web/js/html-editor.js) ─────────────────────────── */
.htmled { border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); overflow: hidden; }
.htmled:focus-within { border-color: var(--brand-500); box-shadow: 0 0 0 3px rgba(70,185,114,.25); }
.htmled__bar { display: flex; gap: 2px; padding: 5px 6px; background: var(--surface-2);
  border-bottom: 1px solid var(--border); }
.htmled__btn { min-width: 30px; height: 28px; padding: 0 7px; cursor: pointer;
  font: inherit; font-size: 13px; color: var(--text-2);
  background: transparent; border: 1px solid transparent; border-radius: 5px; }
.htmled__btn:hover { background: var(--surface); border-color: var(--border); color: var(--navy); }
:root[data-theme="dark"] .htmled__btn:hover { color: var(--text); }
.htmled__area { min-height: 110px; padding: 11px 13px; outline: none; font-size: 14px; line-height: 1.6; }
.auftrag-notiz { display: flex; flex-direction: column; height: 100%; }
.auftrag-notiz .htmled { flex: 1 1 auto; display: flex; flex-direction: column; }
.auftrag-notiz .htmled__area { flex: 1 1 auto; min-height: 200px; }
.htmled__area:empty::before { content: attr(data-placeholder); color: var(--text-3); }
.htmled__area p { margin: 0 0 8px; }
.htmled__area ul, .htmled__area ol { margin: 0 0 8px; padding-left: 20px; }
.htmled__area a { color: var(--brand-ink); text-decoration: underline; }

/* ── Hinweisbanner (Layout) ──────────────────────────────────────────────────
   Steht über dem Seiteninhalt, nicht als Toast: ein Toast verschwindet, dieser
   Hinweis soll auf jeder Seite stehen, solange er gilt. */
.notice { display: flex; gap: 12px; align-items: flex-start; padding: 13px 16px;
  border: 1px solid var(--border); border-left-width: 4px; border-radius: var(--radius-sm);
  background: var(--surface); margin-bottom: 20px; }
.notice__ico { flex: none; width: 18px; height: 18px; margin-top: 1px; }
.notice__body { min-width: 0; flex: 1; }
.notice__title { font-weight: 700; margin-bottom: 2px; }
.notice__text { font-size: 13.5px; color: var(--text-2); }
.notice__text > :first-child { margin-top: 0; }
.notice__text > :last-child { margin-bottom: 0; }
.notice--info    { border-left-color: var(--info); }
.notice--info .notice__ico { color: var(--info); }
.notice--success { border-left-color: var(--brand-500); }
.notice--success .notice__ico { color: var(--brand-600); }
.notice--warning { border-left-color: var(--warning); }
.notice--warning .notice__ico { color: #8a6300; }
.notice--danger  { border-left-color: var(--danger); }
.notice--danger .notice__ico { color: var(--danger); }

/* ── Dateiauswahl ────────────────────────────────────────────────────────────
   Der Knopf im Feld gehört dem Browser und sieht in jedem anders aus — grau,
   eckig, mit fremder Schrift. ::file-selector-button gibt ihn frei, damit er
   wie ein .btn-ghost aussieht. Die Regel steht hier und nicht je Formular:
   Dateifelder gibt es an vier Stellen, und drei davon würde man vergessen. */
input[type="file"].input { padding: 0; height: auto; line-height: 1.4;
  display: flex; align-items: center; gap: 10px; }
input[type="file"].input::file-selector-button,
input[type="file"].input::-webkit-file-upload-button {
  margin: 0; padding: 10px 18px; cursor: pointer;
  font-family: inherit; font-size: 13.5px; font-weight: 600; line-height: 1;
  color: var(--navy); background: transparent;
  border: 0; border-right: 1px solid var(--border);
  border-radius: var(--radius-sm) 0 0 var(--radius-sm);
  transition: background .15s, color .15s;
}
input[type="file"].input::file-selector-button:hover,
input[type="file"].input::-webkit-file-upload-button:hover {
  background: var(--navy); color: #fff;
}
:root[data-theme="dark"] input[type="file"].input::file-selector-button { color: var(--text); }
:root[data-theme="dark"] input[type="file"].input::file-selector-button:hover {
  background: var(--surface-2); color: #fff;
}

.help-block { color: var(--danger); font-size: 12.5px; margin-top: 5px; }
.hint { color: var(--text-2); font-size: 12.5px; margin-top: 5px; }
.checkbox { display: flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--text-2); }
.checkbox input[type=checkbox], .checkbox input[type=radio] { accent-color: var(--brand-500); width: 16px; height: 16px; }
.form-group label.checkbox { font-weight: 400; }
.cbx-ico { width: 16px; height: 16px; flex-shrink: 0; color: var(--text-3); }
/* kartik CheckboxX.

   Zwei Eigenheiten des Widgets muss man kennen, sonst baut man es falsch:

   1. `cbx-active` heisst NICHT "angehakt", sondern "bedienbar" — das Gegenstück
      ist `cbx-disabled`. Die Klasse steht also immer da.
   2. Den Zustand zeigt das Widget über den INHALT von .cbx-icon: angehakt
      steht dort das Icon, sonst ist die Spanne leer. Umgeschaltet wird der
      Inhalt, nicht eine Klasse.

   Als Icon setzt das Yii-Widget ein Bootstrap-3-Glyphicon ein. Glyphicons gibt
   es hier nicht — Bootstrap 5 hat sie abgeschafft, und dessen CSS ist ohnehin
   unterdrückt (config/web.php). Der Haken wird deshalb selbst gezeichnet:
   zwei Kanten eines gedrehten Rechtecks, ganz ohne Schriftart.

   Gezeichnet wird auf dem Icon-Element SELBST, nicht auf dem Kästchen. Nur so
   verschwindet der Haken beim Abwählen von allein — das Element ist dann
   nicht mehr da. Die grüne Fläche kommt über :has() dazu; fällt die
   Unterstuetzung weg, sieht man den Haken eben auf Weiß. Richtig bleibt es. */
.cbx-container { display: inline-block; vertical-align: middle; }
.cbx {
  --cbx: 20px;
  position: relative;
  width: var(--cbx); height: var(--cbx);
  border: 1px solid var(--border); border-radius: 5px;
  background: var(--surface);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; transition: background .12s ease, border-color .12s ease;
}
.cbx.cbx-xs { --cbx: 16px; }
.cbx.cbx-sm { --cbx: 18px; }
.cbx.cbx-md { --cbx: 22px; }
.cbx.cbx-lg { --cbx: 26px; }
.cbx:hover { border-color: var(--brand-500); }
.cbx:focus, .cbx:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(70,185,114,.25); }

/* Angehakt = es liegt ein Icon drin. */
.cbx:has(.cbx-icon > *) { background: var(--brand-500); border-color: var(--brand-500); }

.cbx .cbx-icon { position: absolute; inset: 0; margin: 0; }
.cbx .cbx-icon > * { position: absolute; inset: 0; font-size: 0; }
.cbx .cbx-icon > *::before {
  content: ''; position: absolute; box-sizing: border-box;
  left: 36%; top: 15%; width: 24%; height: 48%;
  border: solid var(--navy); border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* Gesperrt: erkennbar, aber ohne Aufforderung zum Klicken. */
.cbx.cbx-disabled { opacity: .5; cursor: not-allowed; }

/* Label rechts neben der Box statt darunter. */
label.cbx-label, .form-group label.cbx-label {
  display: inline-block; margin: 0 0 0 8px; vertical-align: middle;
  font-size: 14px; font-weight: 400; color: var(--text); cursor: pointer;
}

/* ── Auswahl der Mail-Vorlage ────────────────────────────────────────────── */
.vorlagen { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.vorlage {
  display: block; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); overflow: hidden; transition: border-color .12s ease, box-shadow .12s ease;
}
.vorlage:hover { border-color: var(--brand-500); }
.vorlage.is-aktiv { border-color: var(--brand-500); box-shadow: 0 0 0 2px rgba(70,185,114,.25); }

/* Die Bühne zeigt die Vorlage in Originalbreite, aber verkleinert. Ein
   Ausschnitt aus 560px Breite und 620px Höhe reicht bis unter die
   Schaltfläche — mehr braucht es nicht, um die Vorlagen zu unterscheiden. */
.vorlage__buehne { display: block; position: relative; height: 150px; overflow: hidden; background: #fff; }
.vorlage__rahmen {
  position: absolute; top: 0; left: 0;
  width: 560px; height: 620px; border: 0;
  transform: scale(.268); transform-origin: 0 0;
  /* Die Vorschau ist ein Bild, kein Bedienelement: Klicks gehören dem Label. */
  pointer-events: none;
}
.vorlage__fuss {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 10px 12px; border-top: 1px solid var(--border);
}
.vorlage__fuss input[type=radio] { accent-color: var(--brand-500); margin-top: 2px; flex: none; }
.vorlage__name { display: block; font-size: 13.5px; font-weight: 600; color: var(--text); }
.vorlage__hint { display: block; font-size: 12px; color: var(--text-2); line-height: 1.4; margin-top: 2px; }

/* ── Select2 an das eigene Theme angepasst ───────────────────────────────── */
.select2-container { line-height: normal; }

/* ── BREITE NICHT MESSEN, SONDERN SETZEN ────────────────────────────────────
   Select2 misst beim Start die Breite des <select> und schreibt sie fest. Steht
   das Feld in einem geschlossenen Reiter (`display:none`), misst es null — und
   das Feld bleibt auch dann schmal, wenn der Reiter spaeter aufgeht.

   Aufgefallen ist es, als Anschrift und Erreichbarkeit in den Reiter „Kontakt"
   gewandert sind: die Laenderauswahl steht seither beim Laden in einem
   geschlossenen Abschnitt. Die Alternative waere, jedes Feld beim Oeffnen des
   Reiters neu aufzubauen — eine Verabredung zwischen zwei Skripten, die beim
   naechsten Reiter jemand vergisst. Eine Breitenangabe im Stylesheet kann man
   nicht vergessen. */
.form-group > .select2-container { width: 100% !important; }
.select2-container--default .select2-selection--single {
  height: var(--control-h); border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); display: flex; align-items: center;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
  line-height: normal; padding-left: 13px; padding-right: 28px; color: var(--text); font-size: 14px;
  /* Nimmt den Rest der Zeile, damit das Loeschzeichen daneben nicht drueckt. */
  flex: 1 1 auto; min-width: 0;
}
.select2-container--default .select2-selection--single .select2-selection__placeholder { color: var(--text-3); }
.select2-container--default .select2-selection--single .select2-selection__arrow { height: 100%; right: 8px; }
.select2-container--default .select2-selection--single .select2-selection__arrow b { border-color: var(--text-2) transparent transparent; }
.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b { border-color: transparent transparent var(--text-2); }
/* ── DAS LOESCHZEICHEN STAND VOR DEM TEXT ────────────────────────────────
   Die Auswahlflaeche ist ein Flex-Kasten, und Select2 stellt sein „x" als
   ERSTES Kind hinein. Mit `margin-right: 18px` schob es den gewaehlten Namen
   um 33 Pixel nach rechts — gemessen gegen die Textfelder daneben, die alle
   bei 13 Pixel beginnen. Ein Formular, in dem eine Zeile eingerueckt ist und
   die anderen nicht, sieht kaputt aus, und man sucht den Grund im falschen
   Feld.

   `order: 2` stellt es hinter den Text, links vom Pfeil — dort, wo man es bei
   jeder anderen Auswahl auch erwartet. */
.select2-container--default .select2-selection--single .select2-selection__clear {
  color: var(--text-3); font-weight: 700;
  /* Rechts genug fuer den Pfeil: der sitzt absolut bei `right: 8px` und ist
     rund 20 Pixel breit — mit 22 Pixeln Rand lag das „x" 5 Pixel UNTER ihm
     (gemessen). 34 lassen beide frei und geben dem Zeichen Luft zum Text. */
  order: 2; margin: 0 34px 0 12px;
}
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--single {
  border-color: var(--brand-500); box-shadow: 0 0 0 3px rgba(70,185,114,.25);
}
.select2-container--default .select2-dropdown {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-md); overflow: hidden;
}
.select2-container--default .select2-results__option { color: var(--text); padding: 9px 13px; font-size: 13.5px; }
.select2-container--default .select2-results__option--highlighted[aria-selected] { background: var(--navy); color: #fff; }
.select2-container--default .select2-results__option[aria-selected=true] { background: var(--surface-2); color: var(--text); }
.select2-container--default .select2-search--dropdown .select2-search__field {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text); padding: 8px 11px;
}

/* ── Modal (global, wiederverwendbar via yii2kit\Widgets\Modal) ───────────── */
.modal { position: fixed; inset: 0; z-index: 1000; display: none;
  align-items: center; justify-content: center; padding: 20px;
  background: rgba(0, 33, 71, .55); }
.modal.is-open { display: flex; animation: modalFade .12s ease; }
.modal__dialog { background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  width: 520px; max-width: 100%; max-height: calc(100vh - 40px);
  display: flex; flex-direction: column; animation: modalPop .14s ease; }
.modal__dialog--sm { width: 420px; }
.modal__dialog--lg { width: 760px; }
/* Ein Dialog, der eine Tabelle traegt, braucht mehr als die uebliche Breite.
   HIER und nicht weiter oben: `.modal__dialog` setzt 520px, beide Regeln sind
   gleich spezifisch, und dann gewinnt die spaetere. Weiter oben sah die Regel
   aus, als taete sie etwas — der Dialog blieb schmal. */
.modal__dialog--xl { width: min(1240px, 96vw); }
/* ── FESTE HÖHE FÜR DIALOGE MIT REITERN ──────────────────────────────────
   Ohne sie richtet sich der Dialog nach dem Inhalt des offenen Reiters: die
   Einstellungen sind kurz, das Protokoll lang, und beim Umschalten springt das
   Fenster um mehrere hundert Pixel. Der Knopf, den man gerade gedrückt hat,
   liegt danach woanders — man sucht ihn wieder, obwohl man ihn nicht verlassen
   hat.

   Deshalb steht die Höhe von Anfang an fest, und zwar auf dem, was der grösste
   Reiter braucht: 760px, gedeckelt auf das, was der Bildschirm hergibt. Der
   kurze Reiter hat dann unten Luft — das ist der Preis, und er ist kleiner als
   ein Fenster, das unter der Hand die Grösse wechselt.

   Gescrollt wird INNERHALB des Reiters, nicht im ganzen Rumpf: so bleibt die
   Reiterleiste stehen, während hundert Protokollzeilen durchlaufen. Die Regeln
   dafür hängen an `ftabs--js`, das erst das Skript setzt — ohne JavaScript
   stehen beide Abschnitte untereinander, und dann muss der Rumpf scrollen. */
.modal__dialog--fest { height: min(760px, calc(100vh - 40px)); }
.modal__dialog--fest .modal__body { flex: 1 1 auto; min-height: 0; }
.modal__dialog--fest .modal__body.ftabs--js { display: flex; flex-direction: column;
  overflow: hidden; }
.modal__dialog--fest .modal__body.ftabs--js > .ftabs { flex: none; }
.modal__dialog--fest .modal__body.ftabs--js > .ftabs__pane.is-active { flex: 1 1 auto;
  min-height: 0; overflow-y: auto; }
.modal__head { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 16px 20px; background: var(--navy); color: #fff;
  border-top-left-radius: var(--radius); border-top-right-radius: var(--radius); }
.modal__head h3 { font-size: 17px; margin: 0; color: #fff; }
.modal__close { border: 0; background: transparent; cursor: pointer; color: rgba(255,255,255,.7);
  font-size: 24px; line-height: 1; width: 34px; height: 34px; border-radius: 8px; }
.modal__close:hover { background: rgba(255,255,255,.12); color: #fff; }
.modal__body { padding: 20px; overflow: auto; }
.modal__foot { padding: 14px 20px; border-top: 1px solid var(--border);
  display: flex; justify-content: flex-end; align-items: center; gap: 10px;
  flex-wrap: wrap; }
@keyframes modalFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes modalPop { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }

/* ── Fortschrittsbalken ───────────────────────────────────────────────────
   Zwei Zustände, und der Unterschied ist eine Aussage:

   `.progress--laeuft` lässt einen Streifen wandern. Das heisst „es läuft" und
   sonst nichts — richtig für einen Server, der EINE Antwort am Ende schickt und
   unterwegs nicht sagt, wie weit er ist. Ein Balken, der dabei Prozente
   hochzählt, erfindet sie; er sieht genauer aus und ist es nicht.

   Ohne den Zusatz steht der Balken auf der Breite, die im style-Attribut
   gesetzt wird — für den Abschluss (100 %) und für alles, wo eine Zahl
   tatsächlich bekannt ist. */
.progress { height: 8px; border-radius: var(--radius-pill); background: var(--surface-2);
  border: 1px solid var(--border); overflow: hidden; }
.progress__bar { height: 100%; width: 0; border-radius: var(--radius-pill);
  background: var(--brand-500); transition: width .25s ease; }
.progress--laeuft .progress__bar { width: 38%; animation: progressWandern 1.15s ease-in-out infinite; }
.progress--fehler .progress__bar { background: var(--danger); }
/* Kein `width` in der Animation: eine Breite anzufassen laesst den Browser bei
   jedem Bild neu umbrechen, `transform` nicht. */
@keyframes progressWandern {
  from { transform: translateX(-105%); }
  to   { transform: translateX(268%); }
}
@media (prefers-reduced-motion: reduce) {
  .progress--laeuft .progress__bar { animation: none; width: 100%; opacity: .55; }
}

/* ── Auswertung über dem Netzlaufwerk-Protokoll ───────────────────────────
   Drei Blöcke nebeneinander, auf schmalen Fenstern untereinander. Die Balken
   sind reines CSS: eine Diagramm-Bibliothek für drei Zahlenreihen wäre mehr
   Ladezeit als Erkenntnis, und die Farben kommen so aus denselben Variablen
   wie der Rest — hell und dunkel ohne zweite Palette. */
.nlstat { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: 18px; margin: 0 0 18px; }
@media (max-width: 900px) { .nlstat { grid-template-columns: 1fr; } }
.nlstat__block { border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2); padding: 12px 14px; }
.nlstat__kopf { display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; margin-bottom: 10px; }
.nlstat__titel { font-size: 12px; font-weight: 600; color: var(--text-2);
  text-transform: uppercase; letter-spacing: .04em; }
.nlstat__n { font-size: 18px; font-weight: 700; color: var(--text); }

/* Die Säulen je Tag. `align-items: flex-end` ist der ganze Trick — die Säule
   wächst von unten, wie ein Diagramm es tut. */
.nlchart { display: flex; align-items: flex-end; gap: 3px; height: 92px; }
.nlchart__tag { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;
  align-items: stretch; gap: 4px; }
.nlchart__saeule { height: 72px; display: flex; align-items: flex-end; }
.nlchart__wert { width: 100%; border-radius: 3px 3px 0 0; background: var(--brand-500);
  min-height: 2px; }
.nlchart__label { font-size: 9px; color: var(--text-3); text-align: center;
  white-space: nowrap; overflow: hidden; }

/* Waagerechte Balken für „was geschah" und „woher". Das Label steht links in
   fester Breite, damit die Spuren aneinander ausgerichtet sind — sonst fängt
   jeder Balken woanders an und das Verhältnis ist nicht mehr abzulesen. */
.nlbalken { display: grid; grid-template-columns: 96px minmax(0, 1fr) 40px;
  align-items: center; gap: 8px; margin-bottom: 6px; }
.nlbalken__was { font-size: 12px; color: var(--text-2); display: inline-flex;
  align-items: center; gap: 4px; min-width: 0; }
.nlbalken__spur { height: 8px; border-radius: var(--radius-pill);
  background: var(--border); overflow: hidden; }
.nlbalken__wert { display: block; height: 100%; border-radius: var(--radius-pill);
  background: var(--brand-500); min-width: 0; }
.nlbalken__n { font-size: 12px; color: var(--text); text-align: right; }
/* Dieselben Farben wie die Marken in der Liste — eine zweite Zuordnung waere
   eine, die man nebeneinander vergleichen muss. */
.nlbalken__wert--neu { background: var(--success); }
.nlbalken__wert--geaendert { background: var(--brand-ink); }
.nlbalken__wert--verschoben { background: var(--warning); }
.nlbalken__wert--geloescht { background: var(--danger); }
.nlbalken__wert--geraet { background: var(--teal); }
.nlbalken__wert--mensch { background: var(--brand-ink); }
.nlbalken__wert--anwendung { background: var(--text-3); }

/* ── Info-Zeilen (Label ↔ Wert) ──────────────────────────────────────────── */
.info-row { display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 9px 0; border-bottom: 1px solid var(--border); font-size: 14px; }
.info-row:last-child { border-bottom: 0; }
.info-row__label { color: var(--text-2); }
.info-row__value { font-weight: 600; text-align: right; }

/* ── Abschnitts-Kopf (Symbol + Beschriftung + Linie nach rechts) ──────────── */
.section-head { display: flex; align-items: center; gap: 10px; margin: 22px 0 14px; }
.section-head:first-child { margin-top: 0; }
.section-head__icon { width: 26px; height: 26px; border-radius: 7px; background: var(--brand-50);
  color: var(--brand-600); display: grid; place-items: center; flex: none; }
.section-head__icon svg { width: 15px; height: 15px; }
:root[data-theme="dark"] .section-head__icon { background: rgba(70,185,114,.15); color: var(--brand-500); }
.section-head__label { font-family: var(--font-head); font-size: 14px; color: var(--text); white-space: nowrap; }
.section-head__line { flex: 1; height: 1px; background: linear-gradient(90deg, var(--border), transparent); }
.section-head__hint { white-space: nowrap; }

/* ── Detailseiten (ein Mandant) ──────────────────────────────────────────────
   Die Auswahl des Mandanten liegt auf der Listenebene, nicht in einer Leiste
   neben dem Inhalt — deshalb hier nur noch eine Spalte. */
.tenant-view { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; align-items: start; }
.tenant-detail { min-width: 0; }

/* ── Geoblocking ─────────────────────────────────────────────────────────── */
.geo-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; align-items: start; }
/* Datenquelle: Formular links, Testfeld rechts. */
.geo-layout--settings { grid-template-columns: minmax(0, 1fr) 340px; }
.geo-side { position: sticky; top: 20px; }
.geo-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; background: var(--text-3); }
.geo-dot--on { background: var(--success); }
.geo-dot--warn { background: var(--warning); }
.geo-dot--off { background: var(--text-3); }
.geo-badge { display: inline-flex; align-items: center; gap: 7px; font-size: 12px;
  padding: 3px 12px; border-radius: var(--radius-sm); border: 1px solid var(--border); color: var(--text-2); }
.geo-badge--on { color: var(--brand-700); border-color: var(--brand-500); }
:root[data-theme="dark"] .geo-badge--on { color: #7fd3a2; }
.geo-badge--warn { color: #8a6300; border-color: var(--warning); }
.geo-result { display: flex; flex-direction: column; gap: 6px; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); font-size: 14px; }
.geo-picker__toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.geo-item { display: flex; align-items: center; gap: 7px; }
/* ── Laenderauswahl (views/_landfeld.php) ────────────────────────────────── */
/* Flagge, Name, Kuerzel in einer Zeile — das Kuerzel rechts und blass: es hilft
   beim Suchen ("AT"), soll aber nicht mit dem Namen um Aufmerksamkeit ringen. */
.landfeld__zeile { display: flex; align-items: center; gap: 8px; min-width: 0; }
.landfeld__zeile > span:nth-child(2) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.landfeld__code { margin-left: auto; font-size: 12px; color: var(--text-3); letter-spacing: .04em; }
/* In der geschlossenen Auswahl ist kein Platz fuer das Kuerzel — dort steht
   ohnehin genau ein Land, und die Flagge sagt schon, welches. */
.select2-selection__rendered .landfeld__code { display: none; }

/* Textfeld mit eingebettetem Knopf rechts — etwa die Website zum Öffnen. */
.input-knopf { position: relative; display: flex; }
.input-knopf > .input { flex: 1 1 auto; padding-right: 40px; }
.input-knopf__btn { position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
    width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center;
    border: none; background: transparent; color: var(--text-3); cursor: pointer;
    border-radius: var(--radius-sm); padding: 0; }
.input-knopf__btn:hover { color: var(--brand-600); background: var(--surface-2); }
.input-knopf__btn svg { width: 16px; height: 16px; }

.flag { width: 20px; height: 15px; border-radius: 2px; object-fit: cover; flex: none;
  box-shadow: 0 0 0 1px rgba(0,33,71,.12); }

/* ── Anmeldung ───────────────────────────────────────────────────────────── */
.auth { min-height: 100vh; display: grid; grid-template-columns: 1fr 1fr; }
.auth__hero {
  background: linear-gradient(160deg, #312e81 0%, #1e293b 55%, #0f172a 100%);
  color: #cfdcea; padding: 56px; display: flex; flex-direction: column; justify-content: space-between; }
.auth__hero .brand { display: flex; align-items: center; gap: 12px;
  font-family: var(--font-head); font-size: 22px; color: #fff; }
.auth__hero h2 { font-size: 34px; line-height: 1.2; color: #fff; max-width: 460px; }
.auth__hero p { color: #9db3c9; max-width: 430px; font-size: 15px; }
.auth__hero .feat { display: flex; align-items: center; gap: 10px; margin: 10px 0; color: #cfdcea; }
.auth__hero .feat .tick { width: 22px; height: 22px; border-radius: 50%; background: rgba(70,185,114,.22);
  color: var(--brand-500); display: grid; place-items: center; font-size: 12px; flex: none; }
.auth__panel { display: grid; place-items: center; padding: 40px; background: var(--bg); }
.auth__card { width: 100%; max-width: 380px; }
.auth__card h1 { font-size: 26px; }
.auth__card .lead { color: var(--text-2); margin-bottom: 26px; }

/* ── Hilfsklassen ────────────────────────────────────────────────────────── */
.flex { display: flex; } .items-center { align-items: center; } .gap-2 { gap: 8px; } .gap-3 { gap: 12px; }
.mt-0{margin-top:0}.mb-0{margin-bottom:0}
.mt-1{margin-top:4px}.mb-1{margin-bottom:4px}
.mt-2{margin-top:8px}.mb-2{margin-bottom:8px}
.mt-3{margin-top:12px}.mb-3{margin-bottom:12px}
.mt-4{margin-top:20px}.mb-4{margin-bottom:20px}
.mt-5{margin-top:28px}.mb-5{margin-bottom:28px}
.text-2 { color: var(--text-2); } .text-3 { color: var(--text-3); }
.text-sm { font-size: 12.5px; } .fw-600 { font-weight: 600; }
.muted { color: var(--text-2); }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.num { font-variant-numeric: tabular-nums; }
.alert { padding: 12px 16px; border-radius: var(--radius-sm); font-size: 13.5px; margin-bottom: 16px; }
.alert-error { background: rgba(217,83,79,.10); color: #a8322e; border: 1px solid rgba(217,83,79,.25); }
.alert-success { background: rgba(70,185,114,.12); color: var(--brand-700); border: 1px solid rgba(70,185,114,.3); }
.alert-info { background: rgba(0,161,163,.10); color: #007678; border: 1px solid rgba(0,161,163,.25); }
:root[data-theme="dark"] .alert-error { color: #f0918e; }
:root[data-theme="dark"] .alert-success { color: #7fd3a2; }
:root[data-theme="dark"] .alert-info { color: #4fd3d5; }
.empty { text-align: center; color: var(--text-3); padding: 40px 20px; }
.kpi { font-family: var(--font-head); font-size: 26px; letter-spacing: -.02em; }

/* ── Tagesbalken (Anmeldeversuche je Tag) ────────────────────────────────────
   Bewusst reines CSS statt einer Diagramm-Bibliothek: 14 Werte, eine Reihe —
   dafür ein Chart-Paket zu laden wäre ein schlechtes Geschäft.
   Die Höhe allein trägt die Aussage nicht: jede Säule nennt ihren Wert im
   Titel, und die Achse darunter beschriftet Anfang und Ende. */
.daybars { display: flex; align-items: stretch; gap: 3px; height: 94px; }
.daybar { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* Die Säule selbst; die Zahl darunter bekommt eine eigene, feste Zeile.
   Die Zahl IN die farbige Fläche zu setzen ginge nur bei hohen Säulen — bei
   einem Wert von 1 wäre sie halb abgeschnitten oder stünde auf dem hellen
   Untergrund und wäre weiß nicht mehr zu lesen. */
.daybar__stack {
  flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; justify-content: flex-end;
  border-radius: 3px 3px 0 0; overflow: hidden; background: var(--surface-2);
}
.daybar__fail { background: var(--danger); border-radius: 3px 3px 0 0; }
.daybar__ok { background: var(--brand-500); }
/* Ein Tag ganz ohne Versuche bekommt einen Strich statt einer leeren Fläche —
   sonst ließe sich „nichts passiert" nicht von „Balken zu klein" unterscheiden. */
.daybar--leer .daybar__stack { background: none; border-bottom: 2px solid var(--border); border-radius: 0; }
.daybar__n {
  flex: none; height: 16px; line-height: 16px; text-align: center;
  font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--text-2);
}
.daybar--leer .daybar__n { color: var(--text-3); font-weight: 400; }
.daybars__achse { display: flex; justify-content: space-between; margin-top: 6px;
  font-size: 11px; color: var(--text-3); }

/* Kennzahl-Paar in der Auswertung */
.statrow { display: flex; gap: 10px; }
.statbox { flex: 1; min-width: 0; padding: 10px 12px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: var(--surface-2); }
.statbox__val { font-family: var(--font-head); font-size: 21px; line-height: 1.2; color: var(--navy); }
:root[data-theme="dark"] .statbox__val { color: var(--text); }
.statbox__val--warn { color: var(--danger); }
.statbox__lbl { font-size: 11.5px; color: var(--text-2); margin-top: 2px; }
.chartbox { position: relative; height: 260px; }
.chartbox canvas { display: block; }

/* ── Schmale Fenster ─────────────────────────────────────────────────────────
   Die Seitenleiste wird zur Schublade, die über den Inhalt fährt. Sie
   AUSZUBLENDEN wäre der einfachere Weg — dann gäbe es auf dem Telefon aber
   überhaupt keine Navigation mehr. Geöffnet wird über den Knopf in der
   Kopfleiste (.navtoggle), geschlossen über den Schleier, Escape oder einen
   Menüpunkt. */
.navtoggle { display: none; }        /* nur im schmalen Fenster sichtbar */
.navscrim { display: none; }

@media (max-width: 900px) {
  .app { grid-template-columns: 1fr; }

  .navtoggle { display: grid; margin-right: -4px; }

  .sidebar {
    position: fixed; top: 0; bottom: 0; left: 0;
    width: min(290px, 86vw); height: 100%; z-index: 1200;
    display: flex;                    /* nicht none: die Schublade lebt weiter */
    transform: translateX(-100%);
    transition: transform .22s ease;
    box-shadow: 0 0 40px rgba(0,33,71,.35);
  }
  .sidebar.is-open { transform: none; }

  .navscrim {
    display: block; position: fixed; inset: 0; z-index: 1100;
    background: rgba(0, 33, 71, .55);
    animation: modalFade .15s ease;
  }
  /* Solange die Schublade offen ist, soll der Inhalt darunter nicht mitscrollen. */
  body.nav-open { overflow: hidden; }
  /* In der Schublade gibt es nichts zu ziehen: sie ist so breit wie der
     Bildschirm es zulaesst, und der Griff laege ueber dem Inhalt. */
  .sidebar__griff { display: none; }

  .auth { grid-template-columns: 1fr; }
  .auth__hero { display: none; }
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .grid-3, .grid-2 { grid-template-columns: 1fr; }
  .content { padding: 20px 16px; }
  /* Zweispaltige Sonderraster aus den Views mitnehmen. */
  .grid[style*="grid-template-columns"] { grid-template-columns: minmax(0, 1fr) !important; }
  .topbar { padding: 0 14px; gap: 10px; }
  .search--global, .search--global:focus-within { min-width: 0; }
  .tswitch__btn { min-width: 0; max-width: 190px; }
}

@media (max-width: 560px) {
  .grid-4 { grid-template-columns: 1fr; }
  .content .page-head { height: auto; min-height: 64px; flex-wrap: wrap; align-items: flex-start; }
  .content .page-head__actions { flex-wrap: wrap; }
}
@media (max-width: 860px) {
  .geo-layout--settings { grid-template-columns: minmax(0, 1fr); }
  .geo-side { position: static; }
}


/* ── Dateimanager: Baum links, Inhalt rechts ──────────────────────────────────
   Der Baum ist eine Reihe verschachtelter <details>; das Dreieck des Browsers
   wird durch ein eigenes ersetzt, damit es links vor dem Namen steht und nicht
   an der Stelle, die der Browser dafuer vorsieht. */
.fmgr .ftree__zweig > summary { list-style: none; cursor: pointer; }
.fmgr .ftree__zweig > summary::-webkit-details-marker { display: none; }
.fmgr .ftree__kopf, .fmgr .ftree__blatt {
  display: flex; align-items: center; gap: 4px; border-radius: 7px; position: relative; }
.fmgr .ftree__kopf::before {
  content: '▸'; font-size: 10px; color: var(--text-3); width: 12px; flex: none;
  transition: transform .15s ease; }
.fmgr details[open] > .ftree__kopf::before { transform: rotate(90deg); }
.fmgr .ftree__link {
  display: flex; align-items: center; gap: 7px; flex: 1; min-width: 0;
  padding: 6px 8px; border-radius: 7px; font-size: 13px; font-weight: 500;
  color: var(--text-2); text-decoration: none; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.fmgr .ftree__link:hover { background: var(--surface-2); color: var(--navy); text-decoration: none; }
:root[data-theme="dark"] .fmgr .ftree__link:hover { color: var(--text); }
.fmgr .is-active > .ftree__link { background: var(--brand-50); color: var(--brand-700); font-weight: 600; }
:root[data-theme="dark"] .fmgr .is-active > .ftree__link {
  background: rgba(70,185,114,.18); color: #7fd3a2; }
.fmgr .ftree__ico { width: 14px; height: 14px; flex: none; }
.fmgr .ftree__kinder { margin: 0; }

/* Der Upload-Streifen ueber der Liste — er gehoert zum offenen Ordner. */
.fmgr__upload { padding: 12px 18px; border-bottom: 1px solid var(--border); background: var(--surface-2); }
.fmgr__mehr > summary { list-style: none; cursor: pointer; }
.fmgr__mehr > summary::-webkit-details-marker { display: none; }

/* Umbenennen klappt in der Zeile auf. */
.fmgr__inline { display: inline-block; position: relative; }
.fmgr__inline > summary { list-style: none; cursor: pointer; display: inline-flex; }
.fmgr__inline > summary::-webkit-details-marker { display: none; }
.fmgr__inlineform {
  position: absolute; right: 0; top: 100%; z-index: 20; display: flex; gap: 6px;
  padding: 10px; background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: 0 8px 24px rgba(0,33,71,.14); }
.fmgr__inlineform .input { width: 240px; }

/* Die Sammelleiste erscheint erst, wenn etwas angehakt ist. */
.fmgr__bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 18px; border-top: 1px solid var(--border); background: var(--surface-2);
  font-size: 13px; }
.fmgr__box { width: 15px; height: 15px; }


/* ── Ablegeflaeche: Dropzone.js im Hauslook ───────────────────────────────────
   Die Bibliothek bringt ihr eigenes Stylesheet mit (web/css/vendor). Hier steht
   nur, was sie an unsere Farben, Rundungen und das dunkle Thema anpasst — die
   Vorschauen, der Fortschrittsring und die Fehleranzeige bleiben ihre. */
.fmgr .dropzone {
  min-height: 0; padding: 16px; border: 2px dashed var(--border); border-radius: 12px;
  background: var(--surface-2); transition: border-color .15s ease, background .15s ease; }
.fmgr .dropzone:hover { border-color: var(--brand-500); }
.fmgr .dropzone.dz-drag-hover { border-color: var(--brand-500); border-style: dashed;
  background: var(--brand-50); }
:root[data-theme="dark"] .fmgr .dropzone.dz-drag-hover { background: rgba(70,185,114,.14); }
.fmgr .dropzone .dz-message { margin: 0; text-align: left; }
.dropzone__mitte { display: flex; align-items: center; gap: 14px; }
.dropzone__ico { width: 26px; height: 26px; color: var(--brand-600); flex: none; }
.dropzone__titel { display: block; font-weight: 600; font-size: 14px; color: var(--text); }
.dropzone__sub { display: block; font-size: 12.5px; }

/* Die Vorschauen: schmaler als die Vorgabe, damit ein Dutzend Dateien nicht
   die halbe Seite fuellt. */
.fmgr .dropzone .dz-preview { margin: 12px 12px 0 0; }
.fmgr .dropzone .dz-preview .dz-image { border-radius: 10px; }
.fmgr .dropzone .dz-preview .dz-details { font-size: 12px; }
.fmgr .dropzone .dz-preview .dz-progress .dz-upload { background: var(--brand-500); }

/* Steht die Flaeche, tritt der Weg ohne Skript ab. Nicht display:none, sondern
   aus dem Blick genommen: das Dateifeld darin bleibt bedienbar fuer alles, was
   ueber die Tastatur geht. */
.dropzone:not([hidden]) ~ .dropzone__fallback {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }


/* ── Assistent: Schritte und Wegkacheln (web/js/wizard.js) ────────────────────
   Der Kopf zeigt, wo man steht — nicht als Schmuck, sondern als Antwort auf die
   Frage, die jeder Dialog mit mehreren Seiten aufwirft: wie lange noch. Ein
   erledigter Punkt fuehrt zurueck, ein kuenftiger ist stumm; vorspulen ginge an
   der Pruefung vorbei. */
.wiz__schritte { display: flex; align-items: flex-start; margin: 0 0 20px; }
.wiz__schritt { position: relative; flex: 1 1 0; display: flex; flex-direction: column;
  align-items: center; gap: 6px; padding: 0; border: 0; background: transparent;
  font: inherit; color: var(--text-3); cursor: default; }
.wiz__schritt::before { content: ""; position: absolute; top: 13px; height: 2px;
  left: calc(-50% + 17px); right: calc(50% + 17px); background: var(--border); }
.wiz__schritt:first-child::before { content: none; }
.wiz__nr { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%;
  border: 2px solid var(--border); background: var(--surface);
  font-size: 12px; font-weight: 700; line-height: 1; }
.wiz__wort { font-size: 12px; }
.wiz__schritt.is-fertig { color: var(--brand-600); cursor: pointer; }
.wiz__schritt.is-fertig .wiz__nr { border-color: var(--brand-500); color: var(--brand-600); }
.wiz__schritt.is-fertig::before, .wiz__schritt.is-hier::before { background: var(--brand-500); }
.wiz__schritt.is-hier { color: var(--text); }
/* Gruen traegt Navy, nie Weiss — dieselbe Regel wie beim Primaer-Knopf. */
.wiz__schritt.is-hier .wiz__nr { border-color: var(--brand-500); background: var(--brand-500);
  color: var(--navy); }
.wiz__schritt:focus-visible .wiz__nr { box-shadow: 0 0 0 3px rgba(70,185,114,.35); outline: none; }

.wiz__frage { font-family: var(--font-head); font-size: 15px; color: var(--text); margin: 0 0 14px; }

/* Was aus dem Beleg gelesen wurde — die Antwort steht neben dem Feld, das die
   Frage gestellt hat, und nicht als Toast, der wieder verschwindet. */
.probe { margin: -2px 0 14px; padding: 9px 12px; font-size: 12.5px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--text-2); }
.probe.is-fund { border-color: var(--brand-500); background: var(--brand-50); color: var(--text); }
:root[data-theme="dark"] .probe.is-fund { background: rgba(70,185,114,.12); }

/* Der Blick in die Daten einer Quelle. */
.vorschau__kopf { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  padding-bottom: 12px; margin-bottom: 14px; border-bottom: 1px solid var(--border); }
.vorschau__zurueck { margin-bottom: 12px; }
.vorschau__reihe { padding: 10px 12px; margin-bottom: 12px; border-radius: var(--radius-sm);
  background: var(--surface-2); border: 1px solid var(--border); }
.vorschau [aria-busy="true"] { opacity: .5; }
.vorschau .table { margin-bottom: 0; }

/* ── Adapter-Dialog: Suche oben, Baum links, Details rechts ────────────────
   Der Rumpf rollt NICHT: gerollt wird in den beiden Spalten. Sonst wandert die
   Suche beim Blaettern nach oben aus dem Bild, und man sucht sie, statt zu
   suchen. Deshalb hier `overflow: hidden` gegen die Vorgabe von .modal__body. */
/* Sparkline: kein Diagramm, sondern ein Schriftzeichen. Sie erbt die Farbe
   ihres Umfelds und passt sich damit hellem wie dunklem Erscheinungsbild von
   selbst an — steigend und fallend bekommen einen eigenen Ton. */
.spark__zelle { width: 112px; padding-top: 6px; padding-bottom: 4px; line-height: 0; }
.spark { display: block; color: var(--text-3); overflow: visible; }
.spark--auf { color: var(--green-600, #15803d); }
.spark--ab { color: var(--red-600, #b91c1c); }
tr:hover .spark { opacity: 1; }

/* Ein Mandant im Speicherformular: zugeklappt eine Zeile, offen sein Zugang.
   Bei zwanzig Mandanten wäre die aufgeklappte Seite sonst eine Wand aus
   Feldern, von denen neunzehn niemanden interessieren. */
.speicher__mandant { border: 1px solid var(--border); border-radius: var(--radius);
  margin-bottom: 8px; background: var(--surface-2); }
.speicher__kopf { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 11px 14px; cursor: pointer; list-style: none; }
.speicher__kopf::-webkit-details-marker { display: none; }
.speicher__kopf::before { content: '›'; flex: none; width: 10px; color: var(--text-3);
  transition: transform .12s ease; }
.speicher__mandant[open] > .speicher__kopf::before { transform: rotate(90deg); }
.speicher__kopf:hover { background: var(--surface); }
.speicher__name { font-weight: 600; }
.speicher__probe { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; }
.speicher__rumpf { padding: 4px 14px 16px; border-top: 1px solid var(--border); }

/* ── Baumseite ────────────────────────────────────────────────────────────
   Oben etwas, das stehen bleibt; darunter zwei Spalten, die für sich rollen.
   Zweimal im Haus: im Dialog „Aus Datenquelle holen" und im Quellenverzeichnis.
   Deshalb hier einmal — der Unterschied zwischen beiden ist, was drinsteht,
   nicht wie es angeordnet ist. Die Knoten (.baum__*) und die Detailspalte
   (.detail__*) waren schon geteilt; jetzt ist es auch der Rahmen. */
.baumseite { display: flex; flex-direction: column; gap: 14px; overflow: hidden; min-height: 0; }
.baumseite__filter { flex: none; }
.baumseite__filter label { display: block; margin-bottom: 4px; }
.baumseite__filter .hint { margin-top: 4px; }
.baumseite__spalten { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 14px; flex: 1; min-height: 0; }
.baumseite__baum, .baumseite__details { overflow: auto; border: 1px solid var(--border);
  border-radius: var(--radius); background: var(--surface-2); }
.baumseite__baum { padding: 6px 0; }
.baumseite__details { padding: 16px; }

/* Als Seite und nicht im Dialog: die Höhe kommt vom Fenster, nicht vom
   Elterncontainer — sonst wüchse die Karte mit dem Baum und die Spalten
   rollten nie für sich. */
.card.baumseite { height: calc(100vh - 210px); min-height: 420px; padding: 16px; }
.baumseite__nach { display: flex; align-items: center; gap: 8px; }
.baumseite__nach span { white-space: nowrap; }
.baumseite__nach select { margin: 0; }

/* Ein Ast: Kopf zum Klappen, darunter die Quellen. */
.baum__ast + .baum__ast { margin-top: 2px; }
.baum__ico { flex: none; width: 14px; height: 14px; opacity: .7; }
.baum__knoten--satz { text-decoration: none; padding-left: 30px; }
.baum__knoten--satz.is-still .baum__name,
.baum__knoten--satz.is-still .baum__code { opacity: .55; }
.baum__kinder { padding-bottom: 2px; }

.detail__kopf { margin-bottom: 12px; }
.detail__marken { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.detail__text { margin-bottom: 4px; line-height: 1.5; }
.detail__fuss { display: flex; flex-wrap: wrap; gap: 8px; }

@media (max-width: 900px) {
  .baumseite__spalten { grid-template-columns: minmax(0, 1fr); }
  .card.baumseite { height: auto; }
  .baumseite__baum, .baumseite__details { max-height: 60vh; }
}

.adapter { display: flex; flex-direction: column; gap: 14px; overflow: hidden; min-height: 0; }
.adapter__filter { flex: none; }
.adapter__filter label { display: block; margin-bottom: 4px; }
.adapter__filter .hint { margin-top: 4px; }
.adapter__filter .probe { margin-top: 8px; }

/* Gewuenschte Hoehe als flex-basis, nicht als `height`: so bleibt die Liste
   ruhig stehen, statt je nach Trefferzahl zu springen — und auf einem flachen
   Bildschirm schrumpft sie, statt unter den Fuss des Dialogs zu rutschen. */
.adapter__spalten { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 14px; flex: 1 1 min(58vh, 520px); min-height: 200px; }
.adapter__baum, .adapter__details { overflow: auto; border: 1px solid var(--border);
  border-radius: var(--radius); background: var(--surface-2); }
.adapter__baum { padding: 6px 0; }
.adapter__details { padding: 16px; }

.baum__knoten { display: flex; align-items: baseline; gap: 8px; cursor: pointer;
  padding: 6px 12px 6px 10px; border-left: 2px solid transparent; }
.baum__knoten:hover { background: var(--surface); }
.baum__knoten:focus-visible { outline: 2px solid var(--brand-500); outline-offset: -2px; }
.baum__knoten.is-aktiv { background: var(--surface); border-left-color: var(--brand-500); }
.baum__pfeil { flex: none; width: 10px; color: var(--text-3); font-size: 12px;
  transition: transform .12s ease; }
.baum__knoten.is-offen .baum__pfeil { transform: rotate(90deg); }
/* Der Haken in der Zeile: umlegbar, ohne den Eintrag zu oeffnen. Feste Breite,
   damit Zeilen mit und ohne Haken buendig stehen. */
.baum__haken { flex: none; width: 14px; height: 14px; margin: 0 2px; cursor: pointer;
  accent-color: var(--brand-600); }
.baum__knoten.is-gehakt .baum__name { color: var(--text); font-weight: 600; }
/* Ein oberster Ast ist eine Datenquelle und keine Zeile unter vielen. */
.baum__knoten--quelle { font-weight: 600; }
.baum__knoten--quelle .baum__name { font-size: 14px; }
.baum__marke { flex: none; font-size: 11px; padding: 1px 6px; border-radius: 999px;
  background: var(--surface-2); color: var(--text-3); border: 1px solid var(--border); }
.baum__code { flex: none; font-size: 12px; color: var(--brand-600); }
/* DER NAME BRICHT UM, ER WIRD NICHT ABGESCHNITTEN.
   „§ 9 Eignung und Anpassung der Daten; ungewoehnliche oder persoenliche
   Verhaeltnisse; Herkunft der Daten" endete abgeschnitten bei „Eignung und
   Anpa…" — und damit sahen im Baum ein Dutzend Paragrafen gleich aus. Deutsche
   Paragrafentitel sind lang; die Spalte ist schmal. Von beidem laesst sich nur
   der Umbruch aendern. */
.baum__name { flex: 1; min-width: 0; font-size: 13.5px; color: var(--text);
  white-space: normal; overflow-wrap: anywhere; hyphens: auto; line-height: 1.45; }
.baum__zahl { flex: none; font-size: 12px; color: var(--text-3); }
.baum__laedt { padding: 6px 12px 6px 38px; font-size: 12.5px; color: var(--text-3); }

.detail__code { font-family: var(--mono, monospace); font-size: 12px; color: var(--brand-600); }
.detail__name { font-size: 15px; font-weight: 600; color: var(--text); margin: 2px 0 12px; }
/* Gruppenkopf in einer Liste: eine Zeile, die keine Quelle ist. Sie traegt
   deshalb keinen Rahmen wie die anderen, sondern liegt als Band darueber. */
.table__gruppe > td { padding: 14px 12px 6px; background: var(--surface-2);
  border-top: 1px solid var(--border); font-size: 12px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .04em; color: var(--text-2); }
.table tbody tr.table__gruppe:first-child > td { border-top: 0; }
.table__gruppe > td:hover { background: var(--surface-2); }
.table__gruppe-ico { width: 14px; height: 14px; margin-right: 7px;
  vertical-align: -2px; opacity: .7; }
.table__gruppe-zahl { margin-left: 8px; font-weight: 400; text-transform: none;
  letter-spacing: 0; color: var(--text-3); }

.detail__fuss { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); }
.adapter__details .hint { margin-top: 10px; }

/* Die Rechteangaben: klein, aber vollstaendig lesbar — sie sind der Grund,
   warum jemand die Quelle spaeter im Gutachten nennen darf. */
.detail__ueber { margin-top: 16px; font-size: 11px; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-3); }
.detail__recht { margin-top: 4px; font-size: 12.5px; line-height: 1.45; color: var(--text-2); }
.detail__recht--zitat { font-family: var(--mono, monospace); font-size: 12px;
  padding: 8px 10px; border-radius: var(--radius-sm); background: var(--surface-2);
  border: 1px solid var(--border); word-break: break-word; }
.detail__verweis { display: inline-block; margin-top: 4px; font-size: 12.5px; }

@media (max-width: 820px) {
  /* Nebeneinander lohnt sich erst ab einer Breite, in der beides lesbar ist. */
  .adapter { overflow: auto; }
  .adapter__spalten { grid-template-columns: minmax(0, 1fr); flex: none; }
  .adapter__baum { max-height: 40vh; }
}

/* „oder von hier" zwischen zwei gleichwertigen Wegen zum selben Beleg. */
.wiz__oder { display: flex; align-items: center; gap: 12px; margin: 4px 0 14px;
  color: var(--text-3); font-size: 12.5px; }
.wiz__oder::before, .wiz__oder::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.wiz__zurueck { margin-right: auto; }
.wiz__weg-name { color: rgba(255,255,255,.72); font-weight: 400; }
.wiz__weg-name::before { content: "·"; margin: 0 8px; }

/* Die ganze Kachel ist der Weg, nicht ein Knopf darin: wer sich fuer „Bericht
   als Datei" entscheidet, klickt auf das, was er gelesen hat. */
.wiz__wege { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.wiz__weg { display: flex; flex-direction: column; gap: 6px; padding: 14px; text-align: left;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface);
  font: inherit; color: inherit; cursor: pointer; text-decoration: none;
  transition: border-color .15s ease, background .15s ease, box-shadow .15s ease; }
.wiz__weg:hover, .wiz__weg:focus-visible { border-color: var(--brand-500); background: var(--brand-50);
  box-shadow: var(--shadow-sm); outline: none; text-decoration: none; }
.wiz__weg.is-gewaehlt { border-color: var(--brand-500); background: var(--brand-50); }
.wiz__weg__kopf { display: flex; align-items: center; gap: 9px;
  font-family: var(--font-head); font-size: 14px; color: var(--text); }
.wiz__weg__ico { display: grid; place-items: center; width: 26px; height: 26px; flex: none;
  border-radius: 7px; background: var(--brand-50); color: var(--brand-600); }
.wiz__weg__ico svg { width: 15px; height: 15px; }
.wiz__weg .hint { margin-top: 0; }

:root[data-theme="dark"] .wiz__weg:hover,
:root[data-theme="dark"] .wiz__weg:focus-visible,
:root[data-theme="dark"] .wiz__weg.is-gewaehlt { background: rgba(70,185,114,.12); }
:root[data-theme="dark"] .wiz__weg__ico { background: rgba(70,185,114,.15); color: var(--brand-500); }

@media (max-width: 620px) {
  .wiz__wege { grid-template-columns: 1fr; }
  .wiz__wort { display: none; }
}

/* ── Wissensbasis ─────────────────────────────────────────────────────────
   Der Artikel in der rechten Spalte. Oben die Fundstelle, dann der Text:
   was hier steht, wird zitiert, und wer zitiert, braucht zuerst die
   Fundstelle. */
.artikel__kopf { margin-bottom: 14px; }
.artikel__art { display: flex; align-items: center; gap: 6px; font-size: 12px;
  text-transform: uppercase; letter-spacing: .04em; color: var(--text-3); }
.artikel__ico { width: 14px; height: 14px; opacity: .8; }
.artikel__titel { margin: 6px 0 10px; font-size: 20px; line-height: 1.3; }

/* Die Fundstelle in EINER Zeile zum Herauskopieren — sechs einzelne Angaben
   muesste man von Hand zusammensetzen, und dabei faellt jedes Mal etwas weg. */
.artikel__nachweis { display: flex; align-items: flex-start; gap: 8px;
  padding: 10px 12px; background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 8px; }
.artikel__nachweis-text { flex: 1; font-size: 13px; line-height: 1.5; }
.artikel__nachweis .iact.is-fertig { color: var(--gruen, #16a34a); }
.artikel__kurz { margin-top: 10px; color: var(--text-2); }

.artikel__zeile { display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin: 12px 0; font-size: 12px; color: var(--text-3); }
.artikel__zeile svg { width: 12px; height: 12px; vertical-align: -2px; margin-right: 3px; }
.artikel__akte { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px;
  padding-bottom: 14px; border-bottom: 1px solid var(--border); }

/* Der Text. Abschnitte sind die Einheit, mit der gearbeitet wird — sie
   bekommen deshalb sichtbare Grenzen und ihre Ueberschrift. */
.abschnitt { position: relative; padding: 12px 0; }
.abschnitt + .abschnitt { border-top: 1px solid var(--border); }
.abschnitt__ueber { margin: 0 0 6px; font-size: 14px; font-weight: 600; }
.abschnitt__seite { position: absolute; top: 12px; right: 0; font-size: 11px;
  color: var(--text-3); }
.abschnitt__text { margin: 0; font-size: 14px; line-height: 1.65; white-space: pre-wrap; }

/* ── Antwort und Belege ──────────────────────────────────────────────────
   Die Belege stehen UNTER der Antwort, sichtbar und anklickbar. Eine Antwort
   aus einem Sprachmodell liest sich immer ueberzeugend, auch die falsche. */
.frage__antwort { margin: 14px 0; padding: 14px 16px; background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 8px; }
.frage__satz { margin: 0 0 10px; font-size: 14px; line-height: 1.65; }
.frage__satz:last-child { margin-bottom: 0; }
.frage__nr { display: inline-block; padding: 0 5px; margin: 0 1px; font-size: 11px;
  font-weight: 600; background: var(--akzent-schwach, rgba(99,102,241,.14));
  color: var(--akzent, #6366f1); border-radius: 4px; }

.frage__stellen { display: flex; flex-direction: column; gap: 8px; }
.stelle { display: block; padding: 10px 12px; border: 1px solid var(--border);
  border-radius: 8px; text-decoration: none; color: inherit; }
a.stelle:hover { border-color: var(--akzent, #6366f1); background: var(--surface-2); }
.stelle__kopf { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.stelle__nr { font-size: 11px; font-weight: 600; color: var(--akzent, #6366f1); }
.stelle__ueber { font-size: 13px; font-weight: 600; }
.stelle__seite, .stelle__weg { font-size: 11px; color: var(--text-3); }
.stelle__weg { margin-left: auto; padding: 1px 6px; background: var(--surface-2);
  border-radius: 4px; }
.stelle__quelle { margin-top: 2px; font-size: 11px; color: var(--text-3); }
.stelle__anriss { margin: 6px 0 0; font-size: 12px; line-height: 1.55; color: var(--text-2); }

/* ── Wahlkacheln ─────────────────────────────────────────────────────────
   Die ganze Kachel ist die Wahl, nicht nur der Punkt darin: wer sich fuer
   „Urteil" entscheidet, klickt auf das, was er gelesen hat. */
.wahlkacheln { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 8px; }
.wahlkachel { position: relative; display: block; cursor: pointer; }
.wahlkachel input { position: absolute; opacity: 0; width: 0; height: 0; }
.wahlkachel__inhalt { display: block; height: 100%; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: 8px; transition: border-color .12s; }
.wahlkachel:hover .wahlkachel__inhalt { border-color: var(--text-3); }
.wahlkachel input:checked + .wahlkachel__inhalt { border-color: var(--akzent, #6366f1);
  background: var(--akzent-schwach, rgba(99,102,241,.08)); }
.wahlkachel input:focus-visible + .wahlkachel__inhalt { outline: 2px solid var(--akzent, #6366f1);
  outline-offset: 2px; }
.wahlkachel__kopf { display: flex; align-items: center; gap: 6px; font-size: 13px;
  font-weight: 600; }
.wahlkachel__ico { width: 14px; height: 14px; flex: none; opacity: .8; }
.wahlkachel__text { display: block; margin-top: 4px; font-size: 11px; line-height: 1.5;
  color: var(--text-3); }

/* Ein Ordnerknoten im Baum traegt keinen Verweis — er ist Beschriftung. */
.baum__knoten--ordner { display: flex; align-items: center; gap: 8px; padding: 6px 12px;
  font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .03em;
  color: var(--text-3); }

/* Wo es liegt, steht da, wo man es liest — und laesst sich dort umstellen. */
.artikel__ordner { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.artikel__ordner label { flex: none; margin: 0; }
.artikel__ordner .input { max-width: 260px; margin: 0; }
.artikel__ordner-stand { flex: 1; min-width: 0; }

/* ── Knowledge Base: drei Spalten wie ein aufgeschlagener Kommentar ───────
   Links das Verzeichnis, in der Mitte der Wortlaut, rechts die Kommentierung.
   Die beiden Breiten liegen in Variablen, weil das Ziehen sie aendert — eine
   Zuweisung je Mausbewegung statt eines Umbaus des Rasters. */
.kb { --kb-1: 320px; --kb-2: 520px;
  display: grid; grid-template-columns: var(--kb-1) 7px var(--kb-2) 7px minmax(0, 1fr);
  gap: 0; flex: 1; min-height: 0; overflow: hidden;
  border: 1px solid var(--border); border-radius: 10px; }
.kb__spalte { overflow: auto; min-width: 0; }
.kb__baum { padding: 6px 0; }
.kb__text { padding: 16px; border-left: 0; }
.kb__anmerkungen { padding: 16px; background: var(--surface-2); }

/* Der Griff. Schmal, aber mit grosszuegiger Trefferflaeche — eine Leiste von
   sieben Pixeln trifft niemand zuverlaessig, deshalb reicht das Element
   darueber hinaus. */
.kb__griff { position: relative; cursor: col-resize; background: var(--border);
  border: 0; padding: 0; }
.kb__griff::after { content: ''; position: absolute; inset: 0 -4px; }
.kb__griff:hover, .kb__griff:focus-visible { background: var(--akzent, #6366f1); outline: none; }
.kb__griff:focus-visible { box-shadow: 0 0 0 2px var(--akzent-schwach, rgba(99,102,241,.35)); }
body.is-zieht { cursor: col-resize; user-select: none; }

/* Bei schmalem Fenster untereinander: drei Spalten von je zweihundert Pixeln
   sind keine drei Spalten, sondern drei Schaechte. */
@media (max-width: 1100px) {
  .kb { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto auto;
    overflow: auto; }
  .kb__griff { display: none; }
  .kb__spalte { max-height: 60vh; }
  .kb__anmerkungen { border-top: 1px solid var(--border); }
}

/* ── Der Baum: Pfeil neben dem Verweis ───────────────────────────────────
   Zwei Ziele in einer Zeile — das Gesetz aufschlagen ODER seine Paragrafen
   sehen. Mit nur einem muesste man sich zwischen beidem entscheiden. */
.baum__zeile { display: flex; align-items: stretch; }
.baum__zeile .baum__knoten { flex: 1; min-width: 0; }
.baum__pfeil { flex: none; width: 24px; display: flex; align-items: center;
  justify-content: center; background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--text-3); }
.baum__pfeil svg { width: 13px; height: 13px; transition: transform .12s; }
.baum__pfeil[aria-expanded="true"] svg { transform: rotate(90deg); }
.baum__pfeil:hover { color: var(--text-1); }
.baum__pfeil:focus-visible { outline: 2px solid var(--akzent, #6366f1); outline-offset: -2px; }

.baum__paragrafen { padding-left: 24px; }
.baum__leer { padding: 6px 12px; }
.baum__knoten--paragraf { display: flex; align-items: flex-start; gap: 8px;
  padding: 6px 12px; font-size: 12px; text-decoration: none; }
.baum__knoten--paragraf .baum__name { flex: 1; min-width: 0;
  white-space: normal; overflow-wrap: anywhere; line-height: 1.45; }
.baum__marke { flex: none; min-width: 18px; padding: 0 5px; text-align: center;
  font-size: 10px; font-weight: 600; line-height: 16px; border-radius: 8px;
  background: var(--akzent-schwach, rgba(99,102,241,.16)); color: var(--akzent, #6366f1); }

/* ── Der Wortlaut in der Mitte ───────────────────────────────────────────
   Nur Text, kein Beiwerk: aus dieser Spalte wird zitiert. */
.paragraf__kopf { margin-bottom: 14px; }
.paragraf__quelle { display: flex; align-items: center; gap: 6px; font-size: 12px;
  color: var(--text-3); }
.paragraf__titel { margin: 6px 0 10px; font-size: 18px; line-height: 1.35; }
.paragraf__text { font-size: 14px; line-height: 1.7; }
.paragraf__fuss { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--border); }

/* ── Die Kommentierung rechts ────────────────────────────────────────────
   Wer sie geschrieben hat, steht dabei: eine Auslegung ist eine Meinung, und
   eine Meinung hat einen Urheber. */
.anmerkungen__kopf { display: flex; align-items: center; gap: 8px; margin-bottom: 12px;
  font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-3); }
.anmerkung { padding: 10px 0; }
.anmerkung + .anmerkung { border-top: 1px solid var(--border); }
.anmerkung__kopf { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.anmerkung__wer { flex: 1; min-width: 0; }
.anmerkung__akte { display: flex; gap: 2px; opacity: 0; transition: opacity .12s; }
.anmerkung:hover .anmerkung__akte, .anmerkung:focus-within .anmerkung__akte { opacity: 1; }
.anmerkung__text { margin: 6px 0 0; font-size: 13px; line-height: 1.6; white-space: pre-wrap; }

/* Das Feld steht offen und nicht hinter einem Knopf: eine Anmerkung entsteht
   beim Lesen, und ein Klick dazwischen ist einer zu viel. */
.anmerkung__neu { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); }
.anmerkung__neu textarea { margin: 8px 0; }
.anmerkung__arten { display: flex; flex-wrap: wrap; gap: 4px; }
.anmerkung__art { position: relative; cursor: pointer; }
.anmerkung__art input { position: absolute; opacity: 0; width: 0; height: 0; }
.anmerkung__art span { display: inline-flex; align-items: center; gap: 4px; padding: 3px 8px;
  font-size: 11px; border: 1px solid var(--border); border-radius: 999px; color: var(--text-2); }
.anmerkung__art span svg { width: 11px; height: 11px; }
.anmerkung__art input:checked + span { border-color: var(--akzent, #6366f1);
  background: var(--akzent-schwach, rgba(99,102,241,.1)); color: var(--akzent, #6366f1); }
.anmerkung__art input:focus-visible + span { outline: 2px solid var(--akzent, #6366f1);
  outline-offset: 1px; }

/* Eine Anmerkung des Hauses sieht sonst aus wie ein Gesetzestext. Den
   Unterschied muss man SEHEN und nicht lesen muessen. */
.stelle--anmerkung { border-left: 3px solid var(--akzent, #6366f1);
  background: var(--akzent-schwach, rgba(99,102,241,.06)); }
.stelle--anmerkung .stelle__weg { background: var(--akzent-schwach, rgba(99,102,241,.16));
  color: var(--akzent, #6366f1); }

/* ── Rechtstext, gesetzt ──────────────────────────────────────────────────
   Die Abstaende kommen AUS DEM STIL und nicht aus den Umbruechen der Vorlage.
   Vorher stand hier `white-space: pre-wrap` zusammen mit nl2br() — jeder
   Umbruch zaehlte doppelt, und zwischen zwei Absaetzen klafften vier Zeilen. */
.gt { font-size: 14px; line-height: 1.7; }
.gt__satz { margin: 0 0 .7em; }
.gt__satz:last-child { margin-bottom: 0; }

/* Die Gliederungsmarke haengt LINKS im Rand, damit der Text darunter auf einer
   Fluchtlinie steht. Eine Nummer im Textfluss verschoebe jede Folgezeile. */
.gt__satz--abs, .gt__satz--nr, .gt__satz--buchst,
.gt__satz--dbuchst, .gt__satz--roem { position: relative; }
.gt__marke { position: absolute; left: 0; color: var(--text-3); font-variant-numeric: tabular-nums; }

.gt__satz--abs     { padding-left: 2.6em; margin-top: 1.1em; }
.gt__satz--roem    { padding-left: 2.6em; margin-top: 1.1em; }
.gt__satz--nr      { padding-left: 4.2em; }
.gt__satz--buchst  { padding-left: 5.6em; }
.gt__satz--dbuchst { padding-left: 7em; }
.gt__satz--abs .gt__marke     { left: 0; }
.gt__satz--roem .gt__marke    { left: 0; }
.gt__satz--nr .gt__marke      { left: 2.6em; }
.gt__satz--buchst .gt__marke  { left: 4.2em; }
.gt__satz--dbuchst .gt__marke { left: 5.6em; }

/* Der erste Absatz braucht keinen Vorlauf — darueber steht die Ueberschrift. */
.gt .gt__satz:first-child { margin-top: 0; }

/* Zwischenueberschrift innerhalb einer Anlage. */
.paragraf__unter { margin: 1.6em 0 .6em; font-size: 14px; font-weight: 600; }

/* Tabellen im Rechtstext. Eigener Rahmen mit Rollbalken: die NHK-Tabellen der
   ImmoWertV haben bis zu sechs Spalten, und die mittlere Spalte ist schmal —
   ohne ihn schoebe die Tabelle die ganze Seite auseinander. */
.gt__tabrahmen { overflow-x: auto; margin: 1em 0; }
.gt__tab { border-collapse: collapse; font-size: 13px; min-width: 100%; }
/* ZELLEN BRECHEN UM — AUSSER DEN KURZEN.
   Vorher galt `nowrap` fuer alle. Die Modellansaetze fuer Bewirtschaftungskosten
   in Anlage 3 tragen Zellen wie „fuer gewerbliche Nutzung wie z. B. Buueros,
   Praxen, Geschaefte und vergleichbare Nutzungen …" — als eine Zeile schob das
   die Tabelle so weit auseinander, dass die Spalte daneben aus dem Bild lief. */
.gt__tab th, .gt__tab td { padding: 6px 10px; border: 1px solid var(--border);
  text-align: left; vertical-align: top; white-space: normal;
  max-width: 46ch; line-height: 1.5; }
.gt__tab th { background: var(--surface-2); font-weight: 600; }

/* Kurze Angaben bleiben in einer Zeile: „298 Euro" gehoert zusammen, und eine
   Kopfzeile wie „ab einem relativen Alter von" liest sich umbrochen schlecht. */
.gt__tab .gt__eng { white-space: nowrap; }

/* Zahlen rechtsbuendig und auf gleicher Breite — so stehen Kommastellen
   untereinander und lassen sich vergleichen. */
.gt__tab .gt__zahl { white-space: nowrap; text-align: right;
  font-variant-numeric: tabular-nums; }

/* Ein aufgeloester Verweis. Zurueckhaltend: er steht mitten im Wortlaut und
   soll ihn nicht zerreissen. */
.gt__verweis { color: inherit; text-decoration: underline;
  text-decoration-color: var(--akzent, #6366f1); text-underline-offset: 2px; }
.gt__verweis:hover { color: var(--akzent, #6366f1); }

/* Eine Abbildung beim Herausgeber — die Formeln der ImmoWertV liegen dort nur
   als Bild vor. */
.gt__abbildung { display: inline-flex; align-items: center; gap: 5px;
  padding: 1px 8px; font-size: 12px; border: 1px dashed var(--border);
  border-radius: 6px; color: var(--text-2); text-decoration: none; }
.gt__abbildung::before { content: "\2197"; opacity: .7; }
.gt__abbildung:hover { border-color: var(--akzent, #6366f1); color: var(--akzent, #6366f1); }

/* ── Zusammenfassung als Callout ──────────────────────────────────────────
   Steht VOR dem Text: wer eine Entscheidung aufschlaegt, will in zwei Saetzen
   wissen, worum es geht, und erst dann entscheiden, ob er weiterliest. */
.callout { display: flex; gap: 10px; padding: 12px 14px; margin: 12px 0;
  border-radius: 8px; border: 1px solid var(--border); background: var(--surface-2); }
.callout__ico { flex: none; width: 16px; height: 16px; margin-top: 2px; opacity: .7; }
.callout__text { font-size: 13.5px; line-height: 1.6; }
.callout--kurz { border-left: 3px solid var(--akzent, #6366f1); }

/* Zwei Adressen nebeneinander muessen benannt sein, sonst zitiert jemand die
   falsche. */
.artikel__quelle { display: flex; align-items: baseline; gap: 8px; margin-top: 6px; }
.artikel__quelle-was { flex: none; min-width: 72px; font-size: 11px;
  text-transform: uppercase; letter-spacing: .04em; color: var(--text-3); }

/* ── Netzlaufwerk: Zugangsdaten ───────────────────────────────────────────
   Benutzer, Passwort und Befehl stehen als Paare mit Kopierknopf. Sie werden
   von Hand in einen Windows-Dialog uebertragen — dort kostet jedes verlesene
   Zeichen einen Fehlversuch, der wie eine Ablehnung aussieht. */
.zugang { margin: 10px 0 4px; }
.zugang__paar { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.zugang__was { flex: none; min-width: 78px; font-size: 11px; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-3); }
.zugang__wert { flex: 1; min-width: 0; padding: 6px 10px; background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 6px; font-size: 13px;
  word-break: break-all; user-select: all; }
.zugang .iact.is-fertig, .zugang__paar .iact.is-fertig { color: var(--gruen, #16a34a); }

/* Das Passwort steht genau einmal da — das muss man sehen. */
.callout--einmal { border-left: 3px solid var(--gelb, #d97706); }
.callout--warnung { border-left: 3px solid var(--gelb, #d97706);
  background: var(--gelb-schwach, rgba(217,119,6,.07)); }

/* ── Netzlaufwerk-Dialog: zwei Spalten ────────────────────────────────────
   Links, was man an DIESEM Rechner tut (anlegen, verbinden); rechts, was man
   bestaetigt — spaeter, womoeglich von jemand anderem. Untereinander mussten
   die ersten beiden Schritte weggescrollt werden, sobald mehrere Geraete in
   der Liste standen. */
.laufwerk__spalten { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 22px; align-items: start; }
.laufwerk__bestaetigen { border-left: 1px solid var(--border); padding-left: 22px; }

@media (max-width: 900px) {
  .laufwerk__spalten { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .laufwerk__bestaetigen { border-left: 0; padding-left: 0; }
}

/* Eine Zeile, die sich eben gemeldet hat — sie soll auffallen, ohne zu
   blinken: wer gerade woanders hinsah, findet sie beim Zurueckschauen. */
.table tr.is-neu > td { background: var(--gelb-schwach, rgba(217,119,6,.12));
  transition: background 1.2s ease-out; }

/* Ein Fehlversuch am Geraet — die Zeile, die sagt, woran es haengt. */
.geraet__fehler { display: flex; align-items: center; gap: 4px; margin-top: 3px;
  font-size: 11px; color: var(--gelb, #b45309); }
.geraet__fehler-ico { width: 12px; height: 12px; flex: none; }

/* ── Umzugsbefehl ─────────────────────────────────────────────────────────
   Der fertige Befehl je Mandant. Abgeschrieben wird sonst falsch — und ein
   falscher Mandant im Umzugsbefehl ist teuer. */
.umzug { margin: 10px 0; padding: 12px 14px; border: 1px solid var(--border);
  border-radius: 8px; background: var(--surface-2); }
.umzug__wer { font-size: 13px; font-weight: 600; margin-bottom: 6px; }
.umzug__befehl { margin: 0 0 6px; padding: 8px 10px; overflow-x: auto;
  background: var(--surface); border: 1px solid var(--border); border-radius: 6px; }
.umzug__befehl code { font-size: 12.5px; white-space: pre; }

/* Ein Callout, das warnt statt zu erklaeren. */
.callout--warnung { border-left: 3px solid var(--gelb, #d97706); }

/* ── Speicherarten ────────────────────────────────────────────────────────
   Drei Zustaende, die sich unterscheiden muessen: was laeuft, was ueber S3
   mitlaeuft, und was erst installiert werden muesste. */
.adapterliste { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 10px; margin: 10px 0; }
.adapter { padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; }
.adapter--eingebaut { border-left: 3px solid var(--gruen, #16a34a); }
.adapter--ueber_s3 { border-left: 3px solid var(--akzent, #6366f1); }
.adapter--nachruestbar { border-left: 3px solid var(--border); opacity: .82; }
.adapter__kopf { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-bottom: 4px; }
.adapter__name { font-size: 13px; font-weight: 600; }
.adapter__text { font-size: 12px; line-height: 1.55; color: var(--text-3); }
.adapter__paket { display: block; margin-top: 6px; padding: 4px 7px; font-size: 11.5px;
  background: var(--surface-2); border-radius: 5px; overflow-x: auto; white-space: pre; }

/* ── Zugang und Protokoll ─────────────────────────────────────────────────
   Der Client-Kasten: Erklaerung links, Knopf rechts. Der Knopf ist die
   Handlung und gehoert deshalb an den Rand, an dem das Auge aufhoert. */
.client { display: flex; gap: 16px; align-items: flex-start;
  padding: 12px 14px; background: var(--surface-2); border-radius: 8px;
  border: 1px solid var(--border); }
.client__text { flex: 1; min-width: 0; }
.client__laden { flex: none; width: 260px; text-align: right; }

/* Unter 760px fallen sie untereinander — nebeneinander bliebe fuer die
   Erklaerung eine Spalte von vier Woertern Breite. */
@media (max-width: 760px) {
  .client { flex-direction: column; }
  .client__laden { width: 100%; text-align: left; }
}

/* Das Protokoll bekommt eine eigene Hoehe und scrollt in sich: hundert Zeilen
   wuerden den Dialog sonst laenger machen als den Bildschirm, und der Kopf
   mit den Geraeten waere weg. */
.protokoll { max-height: 320px; overflow-y: auto;
  border: 1px solid var(--border); border-radius: 8px; }
.protokoll .table { margin: 0; }
.protokoll thead th { position: sticky; top: 0; z-index: 1;
  background: var(--surface); }

/* Ein Pfad kann sehr lang sein. Er bricht an den Schraegstrichen, statt das
   Fenster zu sprengen oder waagerecht zu scrollen. */
.protokoll__pfad { display: flex; align-items: flex-start; gap: 6px;
  word-break: break-word; overflow-wrap: anywhere; }
.protokoll__ico { width: 14px; height: 14px; flex: none; margin-top: 2px;
  opacity: .6; }
.protokoll__woher { display: inline-flex; align-items: center; gap: 5px; }

/* ── Schluesselfeld ───────────────────────────────────────────────────────
   Ein Dienstkonto von Google ist zwei Kilobyte JSON, ein privater SSH-Schluessel
   ueber zwanzig Zeilen. Festbreite, weil man darin Zeichen unterscheiden
   koennen muss (0/O, 1/l); nur senkrecht zu ziehen, weil ein waagerecht
   gezogenes Feld das Formular sprengt. */
.input--schluessel { font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 12px; line-height: 1.5; resize: vertical; min-height: 72px;
  white-space: pre; overflow-wrap: normal; overflow-x: auto; }

/* ── Dateiwaehler ─────────────────────────────────────────────────────────
   Ein Verzeichnis waehlt man, indem man hineinsieht. */
.waehler__pfad { display: flex; align-items: center; gap: 8px; padding: 8px 10px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 6px; }
.waehler__pfad code { font-size: 12.5px; word-break: break-all; }
.waehler__wurzeln { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0; }
.waehler__wurzel { padding: 3px 8px; font-size: 11.5px; background: none;
  border: 1px solid var(--border); border-radius: 999px; cursor: pointer; color: var(--text-2); }
.waehler__wurzel:hover { border-color: var(--akzent, #6366f1); }
.waehler__liste { max-height: 320px; overflow-y: auto; border: 1px solid var(--border);
  border-radius: 8px; }
.waehler__zeile { display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 7px 12px; background: none; border: 0; text-align: left; cursor: pointer;
  font-size: 13px; color: inherit; }
.waehler__zeile:hover { background: var(--surface-2); }
.waehler__zeile + .waehler__zeile { border-top: 1px solid var(--border); }
.waehler__zeile--hoch { color: var(--text-3); }
.waehler__name { flex: 1; }
.waehler__warnung { font-size: 11px; color: var(--gelb, #d97706); }

/* ── Platz auf der Platte ─────────────────────────────────────────────────
   Als Balken und nicht als Zahlenreihe: „3,7 von 22,7 GB frei" muss man
   rechnen, einen Balken sieht man. */
.platz { margin-top: 14px; }
.platz__balken { display: flex; height: 10px; border-radius: 999px; overflow: hidden;
  background: var(--gruen-schwach, rgba(22,163,74,.18)); }
.platz__anteil--ablage { background: var(--akzent, #6366f1); }
.platz__anteil--fremd { background: var(--text-3); opacity: .45; }
.platz__legende { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
  margin-top: 8px; font-size: 11.5px; color: var(--text-3); }
.platz__punkt { width: 9px; height: 9px; border-radius: 999px; flex: none; }
.platz__punkt--ablage { background: var(--akzent, #6366f1); }
.platz__punkt--fremd { background: var(--text-3); opacity: .45; }
.platz__punkt--frei { background: var(--gruen-schwach, rgba(22,163,74,.18));
  border: 1px solid var(--border); }
.hint--warnung { color: var(--gelb, #d97706); }

/* ── Zeitleiste ───────────────────────────────────────────────────────────
   Der Verlauf eines Gutachtens als Weg: eine Linie, darauf die Schritte in
   ihrer Reihenfolge. Die Pflegezeilen darueber sind zum Eintragen, das hier
   ist zum Lesen — Reihenfolge und Abstaende sieht man einer Liste von
   Eingabefeldern nicht an.

   Die Linie liegt HINTER den Zeichen (::before am Punkt, nicht als eigenes
   Element): so bleibt sie beim Umbruch an der richtigen Stelle, und der
   letzte Punkt schneidet sie sauber ab. */
.tline { list-style: none; margin: 10px 0 0; padding: 0; }
.tline__punkt { position: relative; display: flex; gap: 12px; padding: 0 0 16px 0; }
.tline__punkt::before {
  content: ""; position: absolute; left: 13px; top: 26px; bottom: 0;
  width: 2px; background: var(--border);
}
.tline__punkt:last-child { padding-bottom: 0; }
.tline__punkt:last-child::before { display: none; }
.tline__zeichen {
  flex: none; width: 28px; height: 28px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--brand-600);
}
/* Das Symbol im Kreis — auf das ELEMENT gezielt, nicht auf eine Klasse.
   `Badge::icon()` wird hier mit leerer Klasse aufgerufen, also griff
   `.tline__zeichen .ic` nie: Das SVG nahm seine Eigengroesse und fuellte mit
   26 Pixeln einen 28er Kreis zu 93 Prozent aus — ein Zeichen, das den Kreis
   sprengt, sieht aus wie ein Fehler und nicht wie ein Symbol. */
.tline__zeichen svg,
.tline__zeichen .ic { width: 15px; height: 15px; flex: none; }
.tline__inhalt { flex: 1; min-width: 0; padding-top: 3px; }
.tline__kopf { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.tline__was { font-weight: 600; color: var(--text); }
.tline__wann { font-size: 12.5px; color: var(--text-2); }
.tline__notiz { font-size: 12.5px; color: var(--text-2); margin-top: 2px; }
.tline__stempel { font-size: 11.5px; color: var(--text-3); margin-top: 2px; }

/* Die Leiste als BEDIENUNG: dieselbe Linie, aber in jeder Zeile die Felder.
   Der Weg ist vorgegeben — die Meilensteine stehen da, ob eingetragen oder
   nicht, und man traegt ein Datum ein statt sich den naechsten Schritt
   auszudenken. */
.tline--pflege .tline__punkt { padding-bottom: 14px; }
.tline--pflege .tline__punkt::before { top: 30px; }
.tline__erklaerung { font-size: 12px; color: var(--text-3); margin-top: 1px; }
.tline__felder {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 8fr) 34px;
  gap: 8px; align-items: center; margin-top: 6px;
}
/* Der Zwischenschritt bringt seine eigene Auswahl mit und braucht eine Spalte
   mehr — der Meilenstein nicht, sein Schritt steht ja fest. */
.tline__punkt--zeile:not(.tline__punkt--fest) .tline__felder {
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr) minmax(0, 8fr) 34px;
}
.tline__platz { display: block; width: 34px; }
/* Der kaufmaennische Verlauf traegt eine Spalte mehr: den Betrag. */
.tline__felder--auftrag {
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr) minmax(0, 3fr) minmax(0, 7fr) 34px;
}
/* Ein offener Punkt ist blass, ein erledigter traegt Farbe: so sieht man auf
   einen Blick, wie weit der Vorgang ist. */
.tline__punkt.is-offen .tline__zeichen { color: var(--text-3); background: transparent; }
.tline__punkt.is-offen .tline__was { color: var(--text-2); }
.tline__punkt.is-erledigt .tline__zeichen {
  color: var(--gruen, #16a34a); border-color: var(--gruen, #16a34a);
}
.tline__offen {
  font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-3); border: 1px solid var(--border);
  border-radius: 999px; padding: 0 7px;
}
/* Die Stelle zwischen zwei Punkten, an der sich etwas einfuegen laesst. Sie
   traegt keine eigene Linie: sie IST der Zwischenraum. */
.tline__einfuegen { position: relative; padding: 0 0 14px 40px; }
.tline__einfuegen::before {
  content: ""; position: absolute; left: 13px; top: -14px; bottom: 0;
  width: 2px; background: var(--border);
}
.tline__einfuegen .btn { opacity: .55; }
.tline__einfuegen .btn:hover { opacity: 1; }
@media (max-width: 900px) {
  .tline__felder,
  .tline__felder--auftrag,
  .tline__punkt--zeile:not(.tline__punkt--fest) .tline__felder {
    grid-template-columns: 1fr;
  }
  .tline__platz { display: none; }
}

/* Die Zeichen in der Schrittauswahl (web/js/verlauf-wahl.js). Das Skript
   setzt die Groesse zusaetzlich am Element — hier steht sie fuer den Fall,
   dass jemand das Markup ohne Inline-Stil verwendet. */
.k2__name .ic { width: 15px; height: 15px; flex: none; vertical-align: -2px; }


/* ── SYMBOL VOR EINEM SELECT2-EINTRAG ───────────────────────────────────────
   Zehn Anlaesse und zehn Wertarten sehen als reine Wortliste alle gleich aus;
   das Auge sucht dann Buchstabe fuer Buchstabe. Ein Zeichen davor macht den
   gesuchten Eintrag auffindbar, bevor man ihn gelesen hat.

   Die Zuordnung Wert -> Zeichen steht in app\models\Stammwert::symbol(); hier
   steht nur, wie es sitzt. `flex: none` ist noetig, weil Select2 seine
   Eintraege in einen schmalen Kasten setzt und das SVG sonst gestaucht wird. */
.sel2-eintrag { display: inline-flex; align-items: center; gap: 7px; min-width: 0; }
.sel2-ico { width: 15px; height: 15px; flex: none; opacity: .75; }
/* Im gewaehlten Zustand steht der Eintrag in einem Chip mit wenig Platz. */
.select2-selection__choice .sel2-eintrag { gap: 5px; }
.select2-selection__choice .sel2-ico { width: 13px; height: 13px; }
/* Der Chip erbt vom krajee-bs5-Thema 16px (Bootstrap-Grundgroesse) und faellt
   damit aus dem 14px-Text der App — die Auswahlliste darunter und das
   Eingabefeld daneben stehen in 14px. Gleiche Groesse fuer den gewaehlten
   Eintrag; der spezifische Pfad ist noetig, um die Themenregel zu ueberbieten. */
.select2-container--krajee-bs5 .select2-selection--multiple .select2-selection__choice {
  font-size: 14px;
  line-height: 1.4;
}


/* ── AUFTRAG: STAMMDATEN UND TIMELINE NEBENEINANDER ─────────────────────────
   Sieben Zehntel fuer die Karte mit den Reitern, drei Zehntel fuer die
   Timeline. Als `minmax` und nicht als starre 30 Prozent: die Untergrenze
   haelt die Spalte auch auf schmalen Bildschirmen bedienbar — ein
   `datetime-local` unter 280 Pixeln schneidet die Uhrzeit ab.

   Unter 1100 Pixeln rutscht die Timeline unter die Karte. Nebeneinander
   blieben dort zwei Spalten uebrig, in denen beide zu schmal sind — und die
   Stammdaten sind das, was man zuerst braucht. */
.auftrag-raster {
  grid-template-columns: minmax(0, 7fr) minmax(300px, 3fr);
  gap: 16px;
  /* `stretch` und nicht `start`: beide Karten sollen bis zum unteren Rand
     reichen. Mit `start` blieben sie auf Inhaltshoehe stehen, und die feste
     Hoehe des Rasters darunter waere wirkungslos. */
  align-items: stretch;
}

/* `.card + .card` gibt zwei GESTAPELTEN Karten 16 Pixel Luft — hier stehen sie
   nebeneinander, und der Abstand schob die Timeline um genau diese 16 Pixel
   nach unten. Den Abstand zwischen den Spalten macht `gap`. */
.auftrag-raster > .card + .card { margin-top: 0; }

@media (max-width: 1100px) {
  .auftrag-raster { grid-template-columns: minmax(0, 1fr); }
}

/* Die Timeline-Karte klebt beim Blaettern oben mit: wer unten in den
   Stammdaten arbeitet, soll den Stand nicht aus dem Blick verlieren. */
.auftrag-timeline { position: sticky; top: 12px; }
.auftrag-timeline .card__body { max-height: calc(100vh - 210px); overflow-y: auto; }

@media (max-width: 1100px) {
  .auftrag-timeline { position: static; }
  .auftrag-timeline .card__body { max-height: none; }
}

/* ── EIN PUNKT DER TIMELINE IN DER SCHMALEN SPALTE ──────────────────────────
   Vier Zeilen untereinander statt vier Feldern nebeneinander: in 280 Pixeln
   ist fuer eine Reihe kein Platz. Die Reihenfolge ist die des Lesens — was,
   wann, wie lange her, was dazu zu sagen ist. */
.tline--schmal .tline__punkt { padding-bottom: 14px; }
.tline--schmal .tline__inhalt { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
/* Schrittwahl und Entfernen in einer Zeile: der Knopf gehoert an den Anfang
   dessen, was er entfernt. Am Fuss stand er neben dem Zeitstempel und sah aus,
   als loesche er den. */
.tline--schmal .tline__kopfzeile {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.tline--schmal .tline__wahl { flex: 1 1 auto; min-width: 0; }
/* Select2 ersetzt das `select` durch einen eigenen Kasten — der muss dieselbe
   Breite bekommen, sonst schiebt er den Knopf aus der Zeile. */
.tline--schmal .tline__kopfzeile .select2-container { flex: 1 1 auto; min-width: 0; }
.tline--schmal .tline__weg { flex: none; }

/* Datum und Betrag teilen sich eine Zeile: der Betrag gehoert zu drei von
   vierzehn Schritten und braucht keine eigene. */
.tline--schmal .tline__zeit { display: block; }

/* „vor 3 Tagen" — die Zeile, die man beim Ueberfliegen liest. Sie gehoert
   direkt unter das Datumsfeld und nicht als eigener Absatz daneben: sie sagt
   etwas UEBER dieses Feld, so wie ein Hinweis unter einem Eingabefeld. Der
   negative Abstand hebt den Zwischenraum der Flex-Spalte wieder auf. */
.tline--schmal .tline__relativ {
  font-size: 11px;
  line-height: 1.3;
  color: var(--text-3, #7a8699);
  min-height: 1em;
  margin-top: -4px;
  padding-left: 2px;
}

/* Steht nichts drin (noch kein Datum), nimmt die Zeile auch keinen Platz. */
.tline--schmal .tline__relativ:empty { min-height: 0; margin-top: -6px; }

.tline--schmal .tline__notiz { resize: vertical; min-height: 46px; font-size: 13px; }

.tline--schmal .tline__fuss {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.tline--schmal .tline__stempel { font-size: 11px; color: var(--text-3, #7a8699); }


/* ── DATUMSFELD MIT „HEUTE" ─────────────────────────────────────────────────
   Der Knopf sitzt IM Feld, nicht daneben: neben dem Feld waere er ein zweites
   Bedienelement, das Platz in der Zeile braucht und das Raster verschiebt.
   Eingefasst werden die Felder von web/js/datum-heute.js — an dreissig Stellen
   von Hand gesetzt haette man ihn an den meisten vergessen.

   Rechts bleibt Platz fuer den Kalenderknopf des Browsers (rund 24 Pixel);
   „heute" sitzt davor. Ohne den Abstand lagen beide uebereinander. */
.datumfeld { position: relative; display: block; }
.datumfeld > input { width: 100%; padding-right: 74px; }

.datumfeld__heute {
  position: absolute;
  top: 50%;
  right: 26px;
  transform: translateY(-50%);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text-2);
  font: inherit;
  font-size: 11px;
  line-height: 1;
  padding: 3px 6px;
  cursor: pointer;
}
.datumfeld__heute:hover { background: var(--surface); color: var(--text); }

/* Auf dem Telefon ist im Feld kein Platz fuer beides — dort bleibt der
   Kalenderknopf des Browsers, der dort ohnehin die bessere Bedienung ist. */
@media (max-width: 640px) {
  .datumfeld__heute { display: none; }
  .datumfeld > input { padding-right: 12px; }
}

/* ── AUFTRAG: KARTEN BIS UNTEN, INHALT SCROLLT ──────────────────────────────
   Beide Karten reichen bis zum unteren Rand des Fensters. Der Inhalt scrollt
   in der Karte, nicht die Seite: so bleiben die Reiter oben und der
   Speichern-Knopf unten stehen — und man weiss beim Blaettern immer noch, wo
   man ist.

   `min-height: 0` an der Karte ist die Bedingung dafuer, dass ein Flex-Kind
   ueberhaupt kleiner werden darf als sein Inhalt; ohne sie waechst die Karte
   und scrollt nirgends. */
/* Die Zahl ist der Platz oberhalb: Kopfleiste der Seite, Ueberschrift mit
   Auftragsnummer, plus ein Rand unten. Gemessen, nicht geschaetzt — die Karte
   beginnt bei 178 Pixeln. */
.auftrag-raster { height: calc(100vh - var(--auftrag-oben, 192px)); }

.auftrag-raster > .card {
  display: flex;
  flex-direction: column;
  min-height: 0;
  max-height: 100%;
}

.auftrag-raster > .card > .ftabs,
.auftrag-raster > .card > .card__head,
.auftrag-raster > .card > .card__foot { flex: none; }

.auftrag-raster > .card > .card__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

/* Die Timeline klebte bisher mit `sticky` oben — das braucht sie nicht mehr,
   wenn sie ohnehin steht und nur ihr Inhalt scrollt. */
.auftrag-timeline { position: static; }
.auftrag-timeline .card__body { max-height: none; }

/* Unter 1100 Pixeln stehen die Karten untereinander; dann ist eine feste
   Hoehe falsch — dort scrollt die Seite, wie ueberall sonst. */
@media (max-width: 1100px) {
  .auftrag-raster { height: auto; }
  .auftrag-raster > .card { max-height: none; }
  .auftrag-raster > .card > .card__body { overflow-y: visible; }
}

/* ── TIMELINE EIN- UND AUSKLAPPEN ───────────────────────────────────────────
   Ein Schalter im Timeline-Kopf schiebt die Spalte nach rechts auf eine
   schmale Leiste zusammen; die Stammdaten bekommen den frei werdenden Platz.
   Der Kopf traegt den Schalter, im ausgeklappten Zustand rechts. */
/* Der Kopf steht auf REITERHOEHE. Er trug 16 Pixel Polster und eine
   16px-Ueberschrift und stand dadurch acht Pixel tiefer als die Reiter der
   linken Karte — die beiden Spalten begannen sichtbar versetzt.

   Die Hoehe wird GEMESSEN und nicht gerechnet: ein <button> erbt die
   Zeilenhoehe der Seite nicht (die Reiter sind Schaltflaechen), seine Hoehe
   haengt damit an der Schrift. Eine Zahl im Stylesheet traf daneben, sobald
   die Schrift wechselte. web/js/auftrag-timeline.js liest die Reiterleiste aus
   und setzt `--auftrag-kopfhoehe`; der Wert hier ist der Rueckfall ohne
   JavaScript. */
.auftrag-timeline__kopf {
  min-height: var(--auftrag-kopfhoehe, 41px);
  padding: 0 10px 0 16px;
  display: flex;
  align-items: center;
  gap: 8px;
}
/* Ohne `gap`: „Time" und „line" sind zwei Flex-Kinder und muessen sich
   nebeneinander als EIN Wort lesen — ein Zwischenraum machte „Time line"
   daraus. Den Abstand zum Symbol setzt darum dessen eigener Rand.

   Mit dem Kopf davor, nicht allein ueber die Klasse: `.card__head h3` setzt
   `gap: 9px` und wiegt als Klasse UND Element schwerer als eine Klasse
   allein — die Luecke blieb sonst stehen. */
.auftrag-timeline__kopf .auftrag-timeline__titel {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 0;
  min-width: 0;
}
.auftrag-timeline__kopf .auftrag-timeline__titel .card-title__ico { margin-right: 8px; }

/* Der Schalter: rund, ruhig, und erst unter dem Zeiger farbig. Als `.iact`
   war er ein eckiger Tabellenknopf zwischen lauter Text — hier steht er
   allein im Kopf und darf danach aussehen. */
.auftrag-timeline__schalter {
  flex: none;
  margin-left: auto;
  display: inline-grid;
  place-items: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-3);
  cursor: pointer;
  transition: color .15s, border-color .15s, background .15s;
}
.auftrag-timeline__schalter:hover {
  color: var(--brand-600);
  border-color: var(--brand-500);
  background: var(--surface);
}
.auftrag-timeline__schalter:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 2px; }
/* Der Pfeil wird nicht ausgetauscht, er dreht sich. */
.auftrag-timeline__pfeil { width: 15px; height: 15px; transition: transform .2s ease; }

/* ── DIE LEISTE ─────────────────────────────────────────────────────────────
   Ausgeklappt gibt es sie nicht; sichtbar wird sie allein durch den Zustand
   am Raster. Der Faden liegt hinter den Punkten und endet mit ihnen. */
.tline-rail { display: none; }

.tline-rail__punkt {
  position: relative;
  z-index: 1;
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-3);
  cursor: pointer;
  transition: color .12s, border-color .12s, transform .12s;
}
.tline-rail__punkt svg { width: 14px; height: 14px; }
/* Geschehen ist, was ein Datum hat. Was nur vorgemerkt ist, bleibt gestrichelt. */
.tline-rail__punkt.is-erledigt { color: var(--brand-600); border-color: var(--brand-500); }
.tline-rail__punkt.is-offen { border-style: dashed; }
.tline-rail__punkt:hover,
.tline-rail__punkt:focus-visible {
  color: var(--brand-600);
  border-color: var(--brand-500);
  transform: scale(1.12);
}
.tline-rail__punkt:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 2px; }

/* Die Blase haengt am BODY und wird von web/js/auftrag-timeline.js gestellt —
   in der Leiste selbst schnitte der scrollende Kasten sie ab. */
.tline-blase {
  position: fixed;
  z-index: 60;
  max-width: 260px;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-2);
  /* Sie folgt dem Zeiger nicht und faengt ihn auch nicht ab. */
  pointer-events: none;
}
.tline-blase[hidden] { display: none; }
.tline-blase__kopf { font-size: 13px; font-weight: 700; color: var(--text); }
.tline-blase__zeit { font-size: 11.5px; color: var(--text-3); }
.tline-blase__notiz { margin-top: 6px; color: var(--text); }
.tline-blase__hinweis { margin-top: 6px; color: var(--text-3); }

/* Wer aus der Leiste heraus auf einen Punkt klickt, landet bei seiner Zeile —
   und sieht kurz, welche gemeint ist. */
.tline__punkt.is-hervor { animation: tline-hervor 1.4s ease-out; border-radius: 8px; }
@keyframes tline-hervor {
  from { background: var(--brand-50, rgba(41,112,255,.14)); }
  to   { background: transparent; }
}

/* Eingeklappt nur dort, wo die Spalten nebeneinander stehen. Unter 1100px
   liegen sie untereinander — ein „nach rechts schieben" ergaebe dort nichts,
   und die hoehere Spezifitaet von `.is-timeline-zu` wuerde die Einspaltigkeit
   sonst ueberstimmen. Deshalb steht die ganze Mechanik in dieser Abfrage. */
@media (min-width: 1101px) {
  /* Breit genug fuer einen 28er-Punkt mit Luft — und schmal genug, dass die
     Stammdaten den Platz merklich bekommen. */
  .auftrag-raster.is-timeline-zu { grid-template-columns: minmax(0, 1fr) 64px; }

  .auftrag-raster.is-timeline-zu .auftrag-timeline .card__body { display: none; }

  .auftrag-raster.is-timeline-zu .auftrag-timeline__kopf {
    flex-direction: column;
    justify-content: center;
    gap: 10px;
    min-height: 0;
    padding: 10px 4px;
  }
  /* Schalter nach oben, der Pfeil zeigt jetzt nach links (ausklappen). */
  .auftrag-raster.is-timeline-zu .auftrag-timeline__schalter { order: -1; margin: 0; }
  .auftrag-raster.is-timeline-zu .auftrag-timeline__pfeil { transform: rotate(180deg); }

  /* Fuer das Symbol ist neben dem Wort kein Platz — in der Leiste stehen die
     Schritte, die sagen ohnehin mehr. */
  .auftrag-raster.is-timeline-zu .auftrag-timeline__titel .card-title__ico { display: none; }
  /* Waagerecht und zweizeilig statt gekippt: „Time" ueber „line". Ein
     senkrecht gestelltes Wort liest man nur mit geneigtem Kopf, und in 64
     Pixeln ist fuer „Timeline" am Stueck kein Platz.

     In gewoehnlicher Schreibung und nicht in Versalien: es bleibt dasselbe
     Wort, nur umgebrochen — Grossbuchstaben machten daraus eine Beschriftung,
     die lauter ruft als das, was darunter steht. */
  .auftrag-raster.is-timeline-zu .auftrag-timeline__titel {
    flex-direction: column;
    gap: 0;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.15;
    text-align: center;
    color: var(--text-3);
  }

  .auftrag-raster.is-timeline-zu .tline-rail {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    padding: 16px 0 20px;
    overflow-y: auto;
    overflow-x: hidden;
  }
  /* Der Faden zwischen den Punkten. */
  .auftrag-raster.is-timeline-zu .tline-rail::before {
    content: '';
    position: absolute;
    top: 22px;
    bottom: 26px;
    left: 50%;
    width: 2px;
    margin-left: -1px;
    background: var(--border);
    border-radius: 2px;
  }
  /* Kein Schritt, ein einzelner Schritt: dann ist da nichts zu verbinden. */
  .auftrag-raster.is-timeline-zu .tline-rail:empty::before,
  .auftrag-raster.is-timeline-zu .tline-rail:has(.tline-rail__punkt:only-child)::before {
    display: none;
  }
}

/* Auf schmalen Schirmen stehen die Karten untereinander — der Schalter hat
   dort keinen Sinn und ist verborgen. */
@media (max-width: 1100px) {
  .auftrag-timeline__schalter { display: none; }
}

/* ── Kontakt-Formular: feste Höhe, Inhalt scrollt, Fuß bleibt unten ─────────
   Dieselbe Mechanik wie beim Auftrag (.auftrag-raster), nur ohne das
   Nummernband darüber — deshalb ein etwas kleinerer Abstand oben. */
.formhuelle { height: calc(100vh - var(--kontakt-oben, 192px)); display: flex; flex-direction: column; }
.formhuelle > .card {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.formhuelle > .card > .ftabs,
.formhuelle > .card > .card__head,
.formhuelle > .card > .card__foot { flex: none; }
.formhuelle > .card > .card__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
@media (max-width: 1100px) {
  .formhuelle { height: auto; }
  .formhuelle > .card { max-height: none; }
  .formhuelle > .card > .card__body { overflow-y: visible; }
}


/* ── „+ NEUER KONTAKT" IN DER KONTAKTAUSWAHL ────────────────────────────────
   Steht als erster Eintrag der Liste und ist gruen hinterlegt: er ist kein
   Treffer, sondern ein Handgriff — das soll man sehen, bevor man liest. */
.kw-neu {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 4px;
  margin: -6px -6px 4px;
  border-radius: var(--radius-sm);
  background: var(--ok-50, #e7f5ec);
  color: var(--ok-700, #1c6b3c);
  font-weight: 600;
  border-bottom: 1px solid var(--border);
}

.kw-neu__plus {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  flex: none;
  border-radius: 50%;
  background: var(--ok-700, #1c6b3c);
  color: #fff;
  font-size: 13px;
  line-height: 1;
}

/* Auch hervorgehoben, wenn die Tastatur darauf steht. */
.select2-results__option--highlighted .kw-neu { background: var(--ok-100, #d3ecdd); }

/* ── DER KASTEN „NEUER KONTAKT" ─────────────────────────────────────────────
   Wenige Felder, ein Knopf, eine Meldung. Der Fuss steht nicht am unteren Rand
   des Modals, sondern direkt unter den Feldern: der Kasten ist kurz, und ein
   Knopf, der weiter unten klebt, sieht aus, als fehle etwas dazwischen. */
.kschnell__fuss {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
}
.kschnell__meldung { font-size: 13px; color: var(--text-2); }
.kschnell__meldung.is-fehler { color: var(--danger-600, #a2251b); }


/* ── ERKLAERUNG ZUR GETROFFENEN WAHL ────────────────────────────────────────
   Unter der Mehrfachauswahl, ein Satz je gewaehltem Wert. Klein und grau: sie
   ist Beiwerk, solange man weiss, was man tut — und da, wenn nicht. */
.wahl-erklaerung { margin-top: 6px; }
.wahl-erklaerung:empty { margin-top: 0; }
.wahl-erklaerung__satz {
  font-size: 12px;
  line-height: 1.45;
  color: var(--text-3);
  padding: 3px 0 3px 10px;
  border-left: 2px solid var(--border);
  margin-bottom: 3px;
}
.wahl-erklaerung__satz strong { color: var(--text-2); font-weight: 600; }


/* ── STAMMDATEN DES GEWAEHLTEN KONTAKTS ─────────────────────────────────────
   Das zweite Zeichen neben der Beschriftung. Es sitzt wie das erste, traegt
   aber ein anderes Symbol: das eine zeigt im Vorbeigehen, das andere oeffnet. */
.infoi--stamm { margin-left: 2px; }

.kstamm__kopf {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 10px;
  margin-bottom: 10px;
  border-bottom: 1px solid var(--border);
}
.kstamm__zeichen {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text-2);
}
.kstamm__zeichen svg { width: 17px; height: 17px; }
.kstamm__name { font-weight: 600; }
.kstamm__art { font-size: 12px; color: var(--text-3); }

.kstamm__liste { margin: 0; }
.kstamm__zeile {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr);
  gap: 10px;
  padding: 4px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.kstamm__zeile:last-child { border-bottom: 0; }
.kstamm__zeile dt { color: var(--text-3); }
.kstamm__zeile dd { margin: 0; }

.kstamm__fuss {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}


/* ── ZWEIZEILIGER EINTRAG IN DER AUFGEKLAPPTEN LISTE ────────────────────────
   Name oben, Erklaerung darunter. In der Liste ist dafuer Platz, und dort wird
   sie gebraucht: die Frage „was soll ich waehlen" stellt sich, WAEHREND die
   Liste offen ist. Im Chip der getroffenen Wahl steht weiterhin nur der Name.

   `align-items: flex-start` haelt das Symbol auf der Hoehe der ersten Zeile —
   mittig ausgerichtet ruschte es bei zwei Zeilen zwischen beide. */
.sel2-eintrag--liste { align-items: flex-start; gap: 8px; }
.sel2-eintrag--liste .sel2-ico { margin-top: 2px; }

.sel2-text { display: flex; flex-direction: column; min-width: 0; }
.sel2-name { font-weight: 500; }

.sel2-erklaerung {
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--text-3);
  margin-top: 1px;
  /* Ohne das steht die Erklaerung in einer Zeile und schiebt die Liste breit;
     `white-space: normal` hebt Select2s eigene Vorgabe auf. */
  white-space: normal;

  /* HOECHSTENS ZWEI ZEILEN.
     Die Liste ist so breit wie das Feld — rund 300 Pixel. Ein Satz von 150
     Zeichen bricht darin auf sechs Zeilen um, und ein einziger Eintrag fuellte
     die ganze Klappliste (gemessen: 200 Pixel fuer einen von zehn). Zwei
     Zeilen sagen genug, um zwei Wertarten zu unterscheiden; der vollstaendige
     Satz steht nach der Wahl unter dem Feld. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Der hervorgehobene Eintrag hat einen farbigen Grund — darauf ist Grau zu
   blass. */
.select2-results__option--highlighted .sel2-erklaerung { color: inherit; opacity: .85; }

/* Zwei Zeilen je Eintrag machen die Liste hoch: bei zehn Eintraegen sind das
   470 Pixel. Select2s Vorgabe von 200 zeigt davon vier — zu wenig, um zu
   vergleichen, worum es hier ja geht.

   Mit Container-Klasse UND Kindkombinator, weil Select2 seine Regel genau so
   schreibt. Zweimal gemessen: ohne Kombinator blieb es bei „none", mit
   Kombinator allein bei 200 Pixeln — die Spezifitaet reichte erst mit
   `.select2-container--default` davor. */
body .select2-container--default .select2-results > .select2-results__options { max-height: 340px; }


/* ── ANKLICKBARE SATZZEILE ──────────────────────────────────────────────────
   Der eigene Stundensatz ist eine Vereinbarung und damit etwas, das man
   aendert — die Zeile fuehrt in den Kasten, in dem die ganze Reihe steht. Die
   JVEG-Saetze darunter sind Gesetz und stehen in einer gewoehnlichen Tabelle:
   Was man nicht aendern kann, soll auch nicht so aussehen. */
.satzzeile {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.satzzeile:hover { background: var(--surface-2); border-color: var(--brand-300, var(--border)); }
.satzzeile--fest { cursor: default; }
.satzzeile--fest:hover { background: var(--surface); border-color: var(--border); }

.satzzeile__zeichen {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text-2);
}
.satzzeile__zeichen svg { width: 17px; height: 17px; }
.satzzeile__text { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.satzzeile__name { font-weight: 600; }
.satzzeile__sub { font-size: 12px; color: var(--text-3); }
.satzzeile__betrag { font-size: 17px; font-weight: 600; white-space: nowrap; }
.satzzeile__pfeil { color: var(--text-3); flex: none; }
.satzzeile__pfeil svg { width: 15px; height: 15px; }


/* Ein waehlbarer Preis im Vorschlag: Bei Pauschalen je Objektart stehen
   mehrere nebeneinander, und ein Klick traegt ein. Als Knopf und nicht als
   Text — was man anklicken kann, soll danach aussehen. */
.preiswahl {
  font: inherit;
  font-size: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-2);
  padding: 2px 7px;
  cursor: pointer;
}
.preiswahl:hover { background: var(--surface-2); color: var(--text); }


/* ── EINE LISTE IN DER STAMMDATENUEBERSICHT ─────────────────────────────────
   Je Liste eine Zeile statt einer ausgeschriebenen Tabelle: Wer den
   Bewertungsanlass aendern will, soll nicht an vier anderen Listen
   vorbeiscrollen. Gebaut wie die Satzzeile bei den Preisen — dieselbe Geste
   soll gleich aussehen. */
.stammliste {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 11px 14px;
  margin-bottom: 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.stammliste:hover { background: var(--surface-2); }
.stammliste__zeichen {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex: none;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text-2);
}
.stammliste__zeichen svg { width: 16px; height: 16px; }
.stammliste__text { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.stammliste__name { font-weight: 600; }
.stammliste__sub { font-size: 12px; color: var(--text-3); }
.stammliste__zahl { font-size: 13px; color: var(--text-2); white-space: nowrap; }
.stammliste__marke { flex: none; }
.stammliste__pfeil { color: var(--text-3); flex: none; }
.stammliste__pfeil svg { width: 15px; height: 15px; }


/* ── EINE ZEILE, DIE BEIM SPEICHERN VERSCHWINDET ────────────────────────────
   Sie bleibt stehen und wird durchgestrichen, bis gespeichert wird: Wer sich
   vertut, soll es sehen und zurueckehmen koennen. Ein sofort verschwundener
   Eintrag laesst nur die Frage zurueck, welcher es war. */
tr.is-weg { opacity: .45; }
tr.is-weg input[type="text"] { text-decoration: line-through; }

.stammform__fuss {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}


/* ── Grundstuecke im Auftrag ──────────────────────────────────────────────
   Je Grundstueck eine Karte im Reiter, darin die Flurstuecke als Zeilen. Eine
   Karte und keine blosse Trennlinie: Bei drei Objekten muss auf einen Blick
   erkennbar sein, welche Anschrift zu welchen Flurstuecken gehoert. */
/* ── Karten oder Liste ──────────────────────────────────────────────────────
   Zwei Blicke auf dieselbe Sache: Karten zeigen mehr je Grundstueck, die
   Liste mehr Grundstuecke auf einmal. Umgeschaltet wird oben rechts. */
.gst-kopfzeile {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 10px; min-height: 30px;
}
.gst-ansicht { display: inline-flex; gap: 2px; flex: none; }
.gst-ansicht[hidden] { display: none; }
.gst-ansicht .iact.is-active {
  background: var(--brand-50, var(--surface-2));
  border-color: var(--brand-500); color: var(--brand-600);
}

.gst-liste { margin-bottom: 12px; }
/* Karten: so breit wie noetig, so viele nebeneinander wie passen. */
.gst-liste--karten {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 12px;
}
.gst-liste--liste { display: flex; flex-direction: column; gap: 6px; }

.gst {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface);
}
/* Der Kopf IST die Karte: der Leib steht nur im Dialog offen. Ohne Rahmen
   unten, solange nichts darunter kommt. */
.gst__kopf { display: flex; align-items: stretch; gap: 4px; padding: 4px; }

/* Die ganze Flaeche ist die Schaltflaeche — nicht ein Woertchen darin. */
.gst__flaeche {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; gap: 10px; text-align: left;
  padding: 8px 10px; border: 0; border-radius: var(--radius-sm);
  background: transparent; font: inherit; color: inherit; cursor: pointer;
  transition: background .12s;
}
.gst__flaeche:hover { background: var(--surface-2); }
.gst__flaeche:focus-visible { outline: 2px solid var(--brand-500); outline-offset: -2px; }

.gst__ico { width: 16px; height: 16px; color: var(--brand-600); }
.gst__nr { display: inline-flex; flex: none; }
.gst__text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.gst__titel { font-weight: 600; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
/* Was fuer ein Objekt, wo — die Zeile, die man beim Ueberfliegen liest. */
.gst__unter { font-size: 12.5px; color: var(--text-2); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Rechts das, wonach man sortiert: die Nutzung und die Groesse. */
.gst__rechts { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 3px; }
.gst__nutzung { font-size: 10.5px; }
.gst__nutzung[hidden] { display: none; }

/* Der Kopf eines GEOEFFNETEN Grundstuecks zeigt nur Titel und Anschrift.
   Bodenrichtwert und Grobwert gehoeren auf die Karte: Dort ueberfliegt man
   mehrere Grundstuecke und vergleicht genau diese Zahlen. Steht die Maske
   offen, stehen dieselben Werte wenige Zeilen tiefer in ihren Feldern — und
   ein Kopf, der sie wiederholt, schiebt die Eingabe nach unten. */
.gst.is-offen .gst__boden,
.gst.is-offen .gst__grob { display: none; }
.gst__mass { font-size: 12px; color: var(--text-3); white-space: nowrap; }

.gst__werkzeug { flex: none; display: flex; align-items: center; gap: 2px; }

/* ── Die beiden Knoepfe der Karte ───────────────────────────────────────────
   Rund und zurueckhaltend: sie stehen auf jeder Karte, und zwei kraeftige
   Zeichen je Karte machen aus einer Uebersicht eine Schalttafel. Farbe
   bekommen sie unter dem Zeiger — und der Papierkorb erst dann seine
   Warnfarbe. */
.gst__knopf {
  flex: none; display: inline-grid; place-items: center;
  width: 28px; height: 28px; padding: 0;
  border: 1px solid transparent; border-radius: 999px;
  background: transparent; color: var(--text-3); cursor: pointer;
  transition: color .12s, background .12s, border-color .12s;
}
.gst__knopf svg { width: 15px; height: 15px; }
.gst__knopf:hover { background: var(--surface-2); border-color: var(--border); color: var(--text); }
.gst__knopf:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 1px; }
.gst__knopf--weg:hover {
  color: var(--danger);
  background: rgba(217, 83, 79, .10);
  border-color: rgba(217, 83, 79, .35);
}
/* Geschlossen waere er ein zweiter Knopf fuer dieselbe Karte. */
.gst__zu { display: none; }

.gst__leib { padding: 14px; display: none; flex-direction: column; gap: 12px; }

/* Reiter und Fuss gibt es nur im Dialog — auf der Karte ist alles darunter zu. */
.gst__reiter, .gst__fuss { display: none; }
.gst__seite { display: none; flex-direction: column; gap: 12px; }
.gst__seite.is-active { display: flex; }

/* ── Der Dialog ─────────────────────────────────────────────────────────────
   Dieselbe Karte, nur anders gestellt: die Felder bleiben, wo sie im Formular
   stehen. Verschoebe man sie in einen Dialogkasten, verloeren sie unterwegs
   ihre Select2-Aufsaetze und ihren Zustand. */
.gst-hinter {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(9, 22, 44, .45);
}
.gst-hinter[hidden] { display: none; }

.gst.is-offen {
  position: fixed; z-index: 1001;
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  /* Breiter als ein gewoehnlicher Dialog: hier stehen zwei- und dreispaltige
     Reihen (Amt/Blatt/BV, Gemarkung/Flur/Nummer/Flaeche), und die brauchen
     Platz, sonst rutschen sie untereinander. */
  width: min(1040px, 96vw);
  max-height: min(820px, calc(100vh - 40px));
  display: flex; flex-direction: column;
  box-shadow: var(--shadow-lg);
}
/* Kopf, Reiter und Fuss stehen fest — dazwischen scrollt die Seite. */
.gst.is-offen .gst__kopf {
  flex: none; border-bottom: 1px solid var(--border);
  background: var(--surface-2); border-radius: var(--radius) var(--radius) 0 0;
}
.gst.is-offen .gst__leib { display: flex; flex: 1 1 auto; min-height: 0; overflow-y: auto; }

.gst.is-offen .gst__reiter {
  flex: none; display: flex; gap: 2px; padding: 0 14px;
  border-bottom: 1px solid var(--border); background: var(--surface);
  /* Sechs Reiter umbrechen, statt waagerecht weiterzulaufen. Vorher standen
     sie in einer Spur mit verstecktem Balken — was nicht in die Breite passte,
     verschwand spurlos, und auf einem schmalen Fenster fehlte einfach eine
     Abteilung. Ein Reiter, den man nicht sieht, gibt es nicht. */
  flex-wrap: wrap;
}
/* Kein Zusammenquetschen: „Bestandsverzeichnis" bleibt lesbar. */
.gst.is-offen .gst__reiter-knopf { flex: none; white-space: nowrap; }

/* ── Was auf einer Seite des Blattes steht ──────────────────────────────────
   Ein Satz ueber jeder Seite, bevor die Felder kommen. „Aufschrift" und
   „Bestandsverzeichnis" sind die amtlichen Namen (§ 3 GBV) und genau deshalb
   erklaerungsbeduerftig: Wer sie kennt, ueberliest den Satz; wer sie nicht
   kennt, braucht ihn — und sucht sonst im falschen Reiter. */
.gst__einleitung {
  margin: 0 0 4px; font-size: 12.5px; line-height: 1.55; color: var(--text-2);
  /* Als abgesetzter Kasten und nicht als Fliesstext ueber den Feldern: So ist
     auf einen Blick zu sehen, dass hier erklaert und nicht ausgefuellt wird —
     und das Auge findet den ersten Eingabepunkt darunter, statt ihn im Text
     zu suchen. */
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
}
.gst__einleitung b { color: var(--text); font-weight: 600; }

/* ── Die Karte im Dialog ────────────────────────────────────────────────────
   Sie fuellt, was die Seite uebriglaesst: Eine Karte, die man nur durch einen
   Schlitz sieht, taugt zum Anschauen und nicht zum Zeichnen. Die Mindesthoehe
   ist die Untergrenze, unter der auch das Anschauen aufhoert. */
.gst__karte { display: flex; flex-direction: column; gap: 10px; min-height: 0; }
.karte__map {
  flex: 1 1 auto; min-height: 340px; height: 46vh;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-2);
  /* Ein eigener Stapelzusammenhang: Leaflet zaehlt darin bis 1000, ohne dass
     davon etwas ueber den Kopf des Dialogs geraet. `isolation` sagt genau
     das — `z-index: 0` allein taete es hier auch, erklaert aber nicht, warum
     es dasteht, und faellt beim naechsten Aufraeumen als „wirkungslos" weg. */
  position: relative; isolation: isolate; z-index: 0;
}
/* Beim Zeichnen ist das Fadenkreuz die Ansage: Hier wird gesetzt, nicht
   geschoben. */
.karte__map.ist-zeichnen { cursor: crosshair; }

.karte__stand { font-size: 12px; color: var(--text-3); min-height: 1em; }

/* Hinfinden, bevor gezeichnet wird: Das Feld nimmt die Breite, die Knoepfe
   nur ihren Text. */
.karte__suche { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.karte__suche .input { flex: 1 1 220px; min-width: 0; }
.karte__suche .btn { flex: none; }
.karte__suche .btn svg { width: 14px; height: 14px; }

/* ── Grundstuecke und ihre Lage nebeneinander ───────────────────────────────
   Links die Grundstuecke, rechts alles Eingezeichnete uebereinander. 60 zu 40:
   Die Karten links tragen Text und brauchen die Breite, die Karte rechts
   braucht vor allem Hoehe. */
.gst-zwei {
  display: grid; grid-template-columns: minmax(0, 3fr) minmax(280px, 2fr);
  gap: 16px; align-items: start;
}
@media (max-width: 1200px) {
  /* Untereinander waere die Karte nach den Grundstuecken kaum noch zu sehen —
     dort steht sie oben, wo sie den Ueberblick gibt, den sie verspricht. */
  .gst-zwei { grid-template-columns: minmax(0, 1fr); }
  .gst-zwei > .gst-uebersicht { order: -1; }
}

.gst-uebersicht {
  position: sticky; top: 0;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); padding: 10px; display: flex;
  flex-direction: column; gap: 8px;
}
.gst-uebersicht__kopf {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; font-size: 13px; font-weight: 600;
}
.gst-uebersicht__kopf .text-3 { font-weight: 400; font-size: 12px; }
.gst-uebersicht .karte__map { min-height: 300px; height: 42vh; }
.gst-uebersicht__leer { margin: 0; }
.gst-uebersicht__leer[hidden] { display: none; }

/* ── Die laufende Nummer ────────────────────────────────────────────────────
   Sie kommt aus einem Zaehler des Stylesheets und nicht aus dem Markup: Beim
   Hinzufuegen und Entfernen stimmt sie damit von selbst — eine im HTML
   eingetragene Nummer muesste nach jedem Handgriff nachgezogen werden, und
   genau das vergisst man. */
.gst-liste { counter-reset: gstnr; }
.gst-liste > .gst { counter-increment: gstnr; }
/* Die Nummer als Kreis — so, wie man Punkte auf einer Liste nummeriert und
   wie sie gleich darauf in der Karte wieder auftaucht. Erst dadurch ist die
   Verbindung zwischen Zeile und Flaeche ohne Erklaerung zu sehen. */
.gst-liste > .gst .gst__nr {
  display: grid; place-items: center; flex: none;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--brand-500); color: #fff;
  font-size: 13px; font-weight: 700; line-height: 1;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 1px 3px rgba(9, 18, 33, .18);
}
.gst-liste > .gst .gst__nr::after { content: counter(gstnr); }
/* Das Sinnbild weicht der Nummer — beides nebeneinander waere in dem
   kleinen Feld eine Ansammlung. */
.gst-liste > .gst .gst__nr .gst__ico { display: none; }

/* Dieselbe Nummer auf der Uebersichtskarte, als Marke auf der Flaeche. */
.gst-nummer {
  display: grid; place-items: center;
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--brand-500); color: #fff;
  font: 700 12px/1 system-ui, sans-serif; font-variant-numeric: tabular-nums;
  border: 2px solid #fff; box-shadow: 0 1px 4px rgba(9, 18, 33, .35);
}

/* ── Die Werkzeuge, in der Karte ────────────────────────────────────────────
   Sie stehen dort, wo gezeichnet wird — beim Setzen von Punkten schaut
   niemand vom Blatt weg. Aufbau wie Leaflets eigene Leisten (`leaflet-bar`),
   damit sie sich nicht wie ein Fremdkoerper anfuehlen. */
.karte__werkzeuge { background: var(--surface); }
.karte__wz {
  display: grid !important; place-items: center;
  width: 30px; height: 30px; color: var(--text-2); background: var(--surface);
}
.karte__wz svg { width: 17px; height: 17px; }
.karte__wz:hover { background: var(--surface-2); color: var(--text); }
/* Das gewaehlte Werkzeug bleibt sichtbar gedrueckt — sonst weiss nach dem
   ersten Klick niemand mehr, ob er noch zeichnet. */
.karte__wz.is-an { background: var(--brand-500); color: #fff; }
.karte__wz.is-an:hover { background: var(--brand-600); color: #fff; }
.karte__wz[data-karte-werkzeug="leeren"]:hover { color: var(--danger); }

/* ── Die Zahlen auf der Karte ───────────────────────────────────────────────
   Flaeche und Streckenlaengen. Leaflets eigener Zeigerkasten waere hier
   falsch: Er hat Spitze, Rahmen und Schlagschatten und wuerde bei zehn Zahlen
   zur Tapete. Hier zaehlt Lesbarkeit auf einem Luftbild — dunkler Grund,
   heller Text, sonst nichts. */
.karte__mass.leaflet-tooltip {
  background: rgba(16, 24, 40, .82); color: #fff;
  border: 0; border-radius: 5px; box-shadow: none;
  padding: 2px 7px; font-size: 11.5px; font-weight: 600;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Leaflet setzt die Spitze als eigenes Element — die faellt weg. */
.karte__mass.leaflet-tooltip::before { display: none; }
/* Die Flaeche ist die Hauptzahl und darf groesser stehen. */
.karte__mass--flaeche.leaflet-tooltip {
  font-size: 12.5px; background: rgba(16, 24, 40, .88);
}
/* Die Kantenlaengen sind Beiwerk — leiser, damit die Flaeche vorn bleibt. */
.karte__mass--kante.leaflet-tooltip {
  background: rgba(16, 24, 40, .68); font-weight: 500; font-size: 11px;
}

/* KEIN z-index an `.leaflet-top`/`.leaflet-bottom`.
   Ein Deckel dort war der Versuch, die Bedienelemente im Dialog zu halten —
   er legte sie unter die Karte: Leaflets Kartenebenen liegen auf 400, die
   Elemente lagen dann auf 2. Was sie im Kasten haelt, ist der eigene
   Stapelzusammenhang der Karte (siehe `.karte__map`); innerhalb davon darf
   Leaflet seine Zahlen behalten. */
.karte__map .leaflet-control-layers, .karte__map .leaflet-bar {
  border-radius: var(--radius-sm); border: 1px solid var(--border);
  box-shadow: 0 2px 8px rgba(9, 18, 33, .12);
}
.karte__map .leaflet-control-layers-list { font-size: 12.5px; padding: 4px 2px; }

/* Die laufende Nummer ist eine Nummer, kein Satz — sie bekommt die Breite
   einer Nummer und nicht die halbe Zeile. */
.gst__bvnr { max-width: 190px; }
.gst__reiter-knopf {
  appearance: none; border: 0; background: transparent; font: inherit;
  font-size: 13.5px; font-weight: 600; color: var(--text-3); cursor: pointer;
  padding: 9px 12px; border-bottom: 2px solid transparent; margin-bottom: -1px;
  border-radius: 7px 7px 0 0;
  display: inline-flex; align-items: center; gap: 7px;
}
.gst__reiter-ico { width: 15px; height: 15px; flex: none; }
.gst__reiter-knopf:hover { color: var(--text); background: var(--surface-2); }
.gst__reiter-knopf.is-active { color: var(--brand-600); border-bottom-color: var(--brand-500); }
.gst__reiter-knopf:focus-visible { outline: 2px solid var(--brand-500); outline-offset: -2px; }

.gst.is-offen .gst__fuss {
  flex: none; display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; border-top: 1px solid var(--border);
  background: var(--surface-2); border-radius: 0 0 var(--radius) var(--radius);
}
/* „Speichern" links, „Entfernen" rechts aussen — die gefaehrliche Handlung
   nicht neben die, die man staendig drueckt. */
.gst__fuss-weg { margin-left: auto; }
.gst__fuss-weg:hover { color: var(--danger); }
.gst__fuss .btn svg { width: 15px; height: 15px; margin-right: 7px; }
/* Im Dialog steht das Entfernen im Fuss; im Kopf waere es dasselbe zweimal. */
.gst.is-offen .gst__kopf .gst__weg { display: none; }
.gst.is-offen .gst__zu { display: inline-grid; }
/* Im Dialog gehoert die Nutzung nicht in den Kopf — sie steht dort im
   Auswahlfeld, aus dem sie kommt. */
.gst.is-offen .gst__rechts { display: none; }
/* Im Dialog ist die Flaeche die Ueberschrift; der Zeiger bleibt, weil ein
   zweiter Klick darauf wieder schliesst. */
.gst.is-offen .gst__flaeche:hover { background: transparent; }

/* Woher die Anschrift kommt — vor den Feldern, die es betrifft. */
.gst__herkunft {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 18px;
  padding: 8px 10px; border-radius: var(--radius-sm); background: var(--surface-2);
  font-size: 13px;
}
.gst__herkunft-label { font-weight: 600; }

/* Ein uebernommenes Feld sieht aus wie ein Feld — nur eben nicht beschreibbar.
   Ausgegraut und nicht versteckt: Wer „wie Auftraggeber" waehlt, soll sehen,
   WAS damit gemeint ist. */
.input.is-uebernommen { background: var(--surface-2); color: var(--text-2); }

.gst__flur { border-top: 1px dashed var(--border); padding-top: 12px; }
.gst__flur-kopf {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin-bottom: 8px; font-size: 13px; font-weight: 600;
}
.gst__summe { font-weight: 400; color: var(--text-2); font-size: 12.5px; }
.gst__flur-liste { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; }
.gst__flur-fuss {
  display: grid;
  grid-template-columns: minmax(0, 2fr) 80px minmax(0, 1fr) 130px 28px;
  gap: 6px; align-items: center; margin-bottom: 8px;
}
.gst__flur-fuss > .btn { grid-column: 1 / 4; justify-self: start; }
.gst__flur-summe {
  grid-column: 4; text-align: right; white-space: nowrap;
  font-size: 12.5px; font-weight: 600; color: var(--text-2); padding-right: 9px;
}
@media (max-width: 720px) {
  .gst__flur-fuss { grid-template-columns: 1fr auto; }
  .gst__flur-fuss > .btn { grid-column: 1; }
  .gst__flur-summe { grid-column: 2; padding-right: 0; }
}

/* Vier Felder in EINER Zeile, in der Reihenfolge des Grundbuchauszugs. Eine
   Karte je Flurstueck machte aus dieser einen Bewegung vier Kaesten und
   brauchte fuer dieselbe Angabe die doppelte Hoehe. */
.flur {
  display: grid;
  grid-template-columns: 22px minmax(0, 2fr) 80px minmax(0, 1fr) 130px 26px;
  gap: 6px; align-items: center;
}
/* Die laufende Nummer: Anzeige, kein Feld — sie ergibt sich aus der Stellung
   in der Liste. Sie ersetzt die Ueberschrift ueber der Liste. */
.flur__nr {
  font-size: 12px; color: var(--text-3); text-align: right;
  font-variant-numeric: tabular-nums;
}
.flur .input { font-size: 13px; }
.flur__flaeche { position: relative; display: block; }
.flur__flaeche .input { padding-right: 30px; width: 100%; }
.flur__einheit {
  position: absolute; right: 9px; top: 50%; transform: translateY(-50%);
  font-size: 12px; color: var(--text-3); pointer-events: none;
}
.flur__weg {
  flex: none; display: inline-grid; place-items: center;
  width: 24px; height: 24px; padding: 0;
  border: 1px solid transparent; border-radius: 999px;
  background: transparent; color: var(--text-3); cursor: pointer;
  transition: color .12s, background .12s, border-color .12s;
}
.flur__weg svg { width: 13px; height: 13px; }
.flur__weg:hover {
  color: var(--danger); background: rgba(217, 83, 79, .10);
  border-color: rgba(217, 83, 79, .35);
}

@media (max-width: 720px) {
  .flur { grid-template-columns: 22px minmax(0, 1fr) minmax(0, 1fr) 26px; }
}

/* ── RECHTE UND LASTEN ──────────────────────────────────────────────────────
   Eine Zeile je Recht — sie sind zaehlbar, und gezaehlt werden sie: Die
   Preistafel fuehrt je Recht einen Zuschlag. Abteilung III hat eine Spalte
   mehr (den Nennbetrag), sonst sind beide gleich gebaut. */
.gst__abt { margin-top: 4px; }
.recht-liste { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; }
.recht {
  display: grid;
  grid-template-columns: 58px minmax(0, 1.4fr) minmax(0, 1.2fr) minmax(0, 1.4fr) 26px;
  gap: 6px; align-items: center;
}
/* Mit Nennbetrag (Abteilung III). */
.recht:has(.recht__betrag) {
  grid-template-columns: 58px minmax(0, 1.3fr) 130px minmax(0, 1.1fr) minmax(0, 1.2fr) 26px;
}
.recht .input { font-size: 13px; }
/* Das reiche Select traegt die Klasse `input` am versteckten `select`, nicht
   an der sichtbaren Huelle — die Schriftgroesse muss ihr eigens gelten,
   sonst steht das Recht groesser da als der Berechtigte daneben. */
.recht .select2-container--default .select2-selection--single .select2-selection__rendered {
  font-size: 13px;
}
.recht__rang { text-align: center; }
.recht__betrag { position: relative; display: block; }
.recht__betrag .input { padding-right: 24px; width: 100%; text-align: right; }
.recht__einheit {
  position: absolute; right: 9px; top: 50%; transform: translateY(-50%);
  font-size: 12px; color: var(--text-3); pointer-events: none;
}

@media (max-width: 720px) {
  .recht,
  .recht:has(.recht__betrag) { grid-template-columns: 48px minmax(0, 1fr) 26px; }
}

/* ── GRUNDBUCH ──────────────────────────────────────────────────────────────
   Was rechtlich gemeint ist — Blatt, laufende Nummer, Lasten, der Auszug. */
.gst__buch { border-top: 1px dashed var(--border); padding-top: 12px; }
.gst__erbbau { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; margin: 2px 0 10px; }
.gst__spaeter { margin: 0; }

/* Der abgelegte Auszug — eine Zeile, kein Kasten: es ist genau eine Datei. */
.gbdatei { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.gbdatei__da { display: flex; align-items: center; gap: 10px; min-width: 0; }
.gbdatei__da[hidden] { display: none; }

/* ══ BESONDERHEITEN DES OBJEKTS ══════════════════════════════════════════════
   Drei Kaestchen in einem Rahmen mit Ueberschrift. Sie gehoeren zusammen, weil
   sie dieselbe Art von Frage stellen — nicht WIE das Objekt beschaffen ist,
   sondern was an ihm besonders ist —, und alle drei haben Folgen ausserhalb
   dieser Seite. Ein Rahmen sagt „das gehoert zusammen", die Ueberschrift sagt,
   wozu. Als `fieldset` und nicht als `div`: Genau dafuer gibt es das Element,
   und Vorleseprogramme kuendigen die Gruppe damit an. */
.gst__merkmale {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px 14px 12px; margin: 0;
}
/* Zwei Spalten. Bei drei Merkmalen steht das dritte allein in der zweiten
   Reihe — das ist richtig so: Es fuellt die Breite, statt eine dritte Spalte
   zu erzwingen, in der die Erklaerungen zu Woerterbuechern werden. */
.gst__merkmale-raster {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px 20px;
}
@media (max-width: 760px) {
  .gst__merkmale-raster { grid-template-columns: minmax(0, 1fr); }
}
.gst__merkmale > legend {
  padding: 0 6px; margin-left: -6px;
  font-size: 12.5px; font-weight: 600; color: var(--text-2);
}
/* Die Zwischenzeile trennt die zwei Gruppen im Raster: erst, was ueber den
   WERT des Objekts etwas sagt, dann, was die ARBEIT daran teurer macht. Sie
   laeuft ueber beide Spalten, damit die Grenze nicht von der Anzahl der
   Merkmale abhaengt — bei ungerader Anzahl saesse sie sonst mitten in einer
   Zeile. */
.gst__merkmale-trenn {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 9px;
  margin: 10px 0 2px;
  font-size: 12px; font-weight: 600; color: var(--text-3);
}
.gst__merkmale-trenn::after {
  content: ""; flex: 1 1 auto; height: 1px; background: var(--border);
}

.gst__merkmale-wozu {
  margin: 0 0 6px; font-size: 12px; line-height: 1.5; color: var(--text-3);
}

/* Ein Merkmal: Kaestchen, Name, darunter die Folge. Der Name traegt das
   Gewicht, die Folge steht leiser darunter — man liest die Namen und haelt
   erst dort an, wo man zweifelt. */
.gst__merkmal {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  align-items: start; gap: 2px 9px; padding: 8px 0;
  /* `align-content: start` ist der Punkt: Die Zellen des Rasters sind so hoch
     wie das hoechste Merkmal der Zeile, und ohne diese Zeile streckt das Grid
     seine beiden auto-Zeilen auf die volle Hoehe — die Folge stand dann mittig
     in ihrer zu hohen Zeile statt unter dem Namen. */
  align-content: start;
}
/* Keine Trennlinien mehr: Nebeneinander trennten sie die Spalten quer statt
   laengs und zerschnitten die Gruppe. Der Abstand genuegt. */
.gst__merkmal > input[type="checkbox"] { margin-top: 2px; grid-row: span 2; }
.gst__merkmal-name { font-size: 13.5px; font-weight: 600; color: var(--text); }
.gst__merkmal-was { font-size: 12px; line-height: 1.5; color: var(--text-3); }
.gst__merkmal-was b { color: var(--text-2); font-weight: 600; }
/* Angehakt tritt das Merkmal hervor — man sieht auf einen Blick, was an
   diesem Objekt besonders ist, ohne die Kaestchen einzeln abzusuchen. */
.gst__merkmal:has(input:checked) .gst__merkmal-name { color: var(--brand-700); }

/* ── Der Nagel ──────────────────────────────────────────────────────────────
   Die erste Seite des Auszugs, klein. Hochkant wie das Papier, das sie zeigt —
   ein querer Rahmen um ein hochkantes Bild waere zwei Drittel Leere. Der Klick
   macht sie gross (web/js/dateiblick.js). */
.gbdatei__nagel {
  position: relative; flex: none; width: 54px; height: 74px; padding: 0;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-2); cursor: pointer; overflow: hidden;
  display: grid; place-items: center;
}
.gbdatei__nagel:hover { border-color: var(--brand-500); }
.gbdatei__nagel:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 2px; }
/* Das Bild liegt UEBER dem Sinnbild; faellt es aus, kommt darunter das
   Sinnbild zum Vorschein — ohne dass jemand etwas umschalten muss. */
.gbdatei__bild {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: top center; background: var(--surface);
}
.gbdatei__bild.ist-weg, .gbdatei__bild:not([src]), .gbdatei__bild[src=""] { display: none; }
.gbdatei__ersatz { display: grid; place-items: center; color: var(--text-3); }
.gbdatei__ersatz svg { width: 22px; height: 22px; }

.gbdatei__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }

/* Das Kreuz gehoert zum Auszug und steht bei ihm — nicht am Ende der Zeile,
   wo es aussaehe, als raeume es die ganze Zeile weg. */
.gbdatei__weg {
  flex: none; display: grid; place-items: center; width: 26px; height: 26px;
  padding: 0; border: 1px solid transparent; border-radius: 7px;
  background: transparent; color: var(--text-3); cursor: pointer;
}
.gbdatei__weg svg { width: 14px; height: 14px; }
.gbdatei__weg:hover { color: var(--danger); border-color: var(--border); background: var(--surface-2); }
.gbdatei__weg:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 1px; }
.gbdatei__ico { width: 15px; height: 15px; flex: none; color: var(--brand-600); }
.gbdatei__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gbdatei__gr { font-size: 12px; color: var(--text-3); flex: none; }

/* Das Dateifeld selbst ist unsichtbar: sein Aussehen laesst sich nicht
   gestalten, und der Text darin steht in der Sprache des Browsers. */
.gbdatei__wahl > input[type="file"] { position: absolute; width: 1px; height: 1px;
  opacity: 0; pointer-events: none; }
.gbdatei__wahl[hidden] { display: none; }
.gbdatei__wahl > span {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 12px; border: 1px dashed var(--border); border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--text-2); font-size: 13px; cursor: pointer;
  transition: border-color .12s, color .12s;
}
.gbdatei__wahl > span svg { width: 15px; height: 15px; }
.gbdatei__wahl:hover > span { border-color: var(--brand-500); color: var(--brand-600); }
.gbdatei__wahl > input:focus-visible + span { outline: 2px solid var(--brand-500); outline-offset: 2px; }

.gbdatei__stand { font-size: 12px; color: var(--text-3); }

/* ── Die Datei gross ────────────────────────────────────────────────────────
   Ein PDF zeigt der Browser selbst; hier steht nur der Rahmen darum. Deshalb
   nimmt der Kasten fast das ganze Fenster: Ein Auszug, den man auf halber
   Hoehe liest, ist keiner. */
.blick { position: fixed; inset: 0; z-index: 90; display: flex; }
.blick[hidden] { display: none; }
.blick__grund { position: absolute; inset: 0; background: rgba(9, 18, 33, .62); }
.blick__kasten {
  position: relative; margin: auto; display: flex; flex-direction: column;
  width: min(1100px, 94vw); height: min(88vh, 1000px);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: 0 24px 60px rgba(9, 18, 33, .35);
  overflow: hidden;
}
.blick__kopf {
  flex: none; display: flex; align-items: center; gap: 12px;
  padding: 10px 12px 10px 16px; border-bottom: 1px solid var(--border);
}
.blick__name {
  font-weight: 600; font-size: 14px; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Der Weg nach draussen: Wer drucken oder speichern will, ist im eigenen Tab
   besser aufgehoben als in einem Rahmen. */
.blick__laden { margin-left: auto; font-size: 12.5px; flex: none; }
.blick__zu {
  flex: none; display: grid; place-items: center; width: 30px; height: 30px;
  padding: 0; border: 1px solid var(--border); border-radius: 7px;
  background: var(--surface-2); color: var(--text-2); cursor: pointer;
}
.blick__zu svg { width: 15px; height: 15px; }
.blick__zu:hover { color: var(--text); border-color: var(--brand-500); }
.blick__rahmen { flex: 1 1 auto; width: 100%; border: 0; background: var(--surface-2); }
/* Hinter dem Dialog wird nicht geblaettert. */
body.hat-blick { overflow: hidden; }

/* Die Ergaenzung im Reiter — „Abt. II (Lasten)". Leiser als der Name selbst:
   Sie sagt, was drinsteht, ist aber nicht der Name. */
.gst__reiter-zu { font-weight: 500; color: var(--text-3); }
.gst__reiter-knopf.is-active .gst__reiter-zu { color: var(--text-2); }
.gbdatei__stand.is-fehler { color: var(--danger); }


/* ── Pauschalen als Regler ───────────────────────────────────────────────────
   Die Preistafel fuehrt je Objektart eine Pauschale, und sie steigen mit dem
   Umfang: ein Objekt, ein groesseres, ein Portfolio. Das ist eine Skala und
   gehoert an einen Regler — als Reihe von Knoepfen in einer Zeile Fliesstext
   las man den Satz zu Ende und hatte den Anfang vergessen. */
.preiswahl-regler { margin: 8px 0 4px; max-width: 520px; }
.preiswahl-regler__was { font-size: 13px; color: var(--text-2); min-width: 0; }
.preiswahl-regler__herkunft { font-size: 11.5px; color: var(--text-3); }
.preiswahl-regler__abseits { margin-top: 6px; }


/* Das Budget als Stundenregler: Ein Budget ist eine Anzahl Stunden, und die
   Zahl im Feld ist nur ihr Preis. */
.budgetregler { margin-bottom: 8px; }
.budgetregler__stunden { font-size: 12.5px; color: var(--text-2); }


/* ── Kategorien: die Strecke als Umschalter ──────────────────────────────────
   Ohne Qualifizierung -> Interessent -> Kunde. Ein Zustand, kein Satz Haken:
   Ein Kunde ist kein Interessent mehr. Was daneben zutrifft (Makler, Notar,
   Bank), steht in der Auswahl darunter — beide schreiben in dasselbe Feld.

   Gebaut mit `.facet`, demselben Umschalter wie ueber den Listen. */
.katstufe { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
/* Wertermittlungsstichtage: Bezeichnung breit, Datum schmal, Kreuz am Rand. */
.stichtag-zeile {
  display: grid;
  /* Bezeichnung · Beschreibung · Datum · Kreuz. Die Beschreibung bekommt mehr
     Platz als die Bezeichnung: Jene ist ein Wort aus einer Liste, diese ein
     halber Satz — „Tag der Rechtshaengigkeit (Zustellung) des
     Scheidungsantrags, § 1384 BGB". */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr) 190px auto;
  gap: 8px;
  align-items: center;
  margin-bottom: 8px;
}
.stichtag-was { font-size: 13px; }
@media (max-width: 900px) {
  /* Untereinander, sobald die Beschreibung sonst zum Schlitz wird. */
  .stichtag-zeile { grid-template-columns: minmax(0, 1fr) 150px auto; }
  .stichtag-was { grid-column: 1 / -1; }
}
.stichtag-zeile .icon-btn { flex: none; }
.stichtag-fest { display: flex; align-items: center; gap: 8px; padding: 8px 11px;
  background: var(--surface-2); color: var(--text-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); font-size: 13.5px; min-width: 0; }
.stichtag-fest svg { width: 16px; height: 16px; flex: none; }
@media (max-width: 560px) {
  .stichtag-zeile { grid-template-columns: 1fr auto; }
  .stichtag-zeile .num { grid-column: 1 / 2; }
}
/* Interessent ist die Vorstufe zum Kunden — orange (amber) statt gruen, damit
   der Blick den Noch-nicht-Kunden vom Kunden unterscheidet. „Kunde" bleibt
   gruen (etabliert), „keine Qualifizierung" neutral. */
.katstufe [data-stufe="Interessent"].is-active {
  background: #fdf0e1;
  color: #b4530a;
  border-color: var(--warning);
}
:root[data-theme="dark"] .katstufe [data-stufe="Interessent"].is-active {
  background: rgba(224, 168, 0, .18);
  color: #e5bd4c;
  border-color: rgba(224, 168, 0, .5);
}
/* „Keine Qualifizierung" ist kein Zustand, den man erreicht — es ist der
   Ausgangspunkt. Deshalb neutral grau statt gruen; nur Variablen, damit es im
   dunklen Erscheinungsbild von selbst mitgeht. */
.katstufe [data-stufe=""].is-active {
  background: var(--surface-2);
  color: var(--text-2);
  border-color: var(--border);
}


/* ── Stammdaten in zwei Spalten: Person 60, Einordnung 40 ────────────────────
   Wer einen Kontakt anlegt, entscheidet beides zusammen — wer er ist und was
   er fuer uns ist. Untereinander lag dazwischen eine Bildschirmhoehe.

   60/40 und nicht die Haelfte: Links stehen Reihen zu vier Feldern (Anrede,
   Titel, Vorname, Nachname), rechts drei und die Kategorien. Bei halber Breite
   braechen die Reihen links um, waehrend rechts Platz frei bliebe. */
.kontaktraster { grid-template-columns: minmax(0, 60fr) minmax(0, 40fr); gap: 0 28px; align-items: start; }
.kontaktspalte { min-width: 0; }

/* Unter 1100 Pixeln untereinander: 40 Prozent von 900 sind 360, und darin ist
   ein Auswahlfeld mit Symbol nicht mehr zu bedienen. */
@media (max-width: 1100px) {
    .kontaktraster { grid-template-columns: minmax(0, 1fr); gap: 0; }
}

/* ── Unterlagenbaum als Tabelle ──────────────────────────────────────────────
   Der Baum steht als Tabelle: eine Zeile je Knoten, die Gliederung liegt in der
   Nummer und im Einzug des Namens. Die Eigenschaften stehen als Kästchen in der
   Zeile und lassen sich dort umlegen (js/ubaum-tabelle.js). Rubriken sind
   hinterlegt und fetter, ausgeschaltete Zeilen treten zurück, ohne zu
   verschwinden. */
.ubaum-tab { font-variant-numeric: tabular-nums; }
.ubaum-tab td { vertical-align: middle; }

.ubaum-tab__nr { white-space: nowrap; color: var(--text-2); font-size: 12.5px; }

.ubaum-tab__name { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ubaum-tab__ico { display: inline-grid; place-items: center; color: var(--text-2); flex: none; }
.ubaum-tab__ico svg { width: 16px; height: 16px; }
.ubaum-tab__label { font-weight: 600; overflow-wrap: anywhere; }
.ubaum-tab__hinweis { margin-top: 3px; font-size: 12px; color: var(--text-2); }

.ubaum-tab__zeile--rubrik > td { background: var(--surface-2); }
.ubaum-tab__zeile--rubrik .ubaum-tab__label { font-weight: 700; }
.ubaum-tab__zeile--rubrik .ubaum-tab__ico { color: var(--brand-600, var(--brand-500)); }

/* Ausgeschaltet: der Name tritt zurück, die Kästchen bleiben voll bedienbar —
   sonst liesse sich das eine, das die Zeile wieder anschaltet, kaum treffen. */
.ubaum-tab__zeile.is-aus .ubaum-tab__label { color: var(--text-3); font-weight: 500; }
.ubaum-tab__zeile.is-aus .ubaum-tab__nr,
.ubaum-tab__zeile.is-aus .ubaum-tab__ico,
.ubaum-tab__zeile.is-aus .ubaum-tab__quelle { opacity: .55; }

/* Wahr/Falsch-Kästchen, mittig in ihrer Spalte. */
.ubaum-tab__c { text-align: center; white-space: nowrap; }
.ubaum-tab__flag { display: inline-grid; place-items: center; cursor: pointer; margin: 0; }
.ubaum-tab__cb { width: 17px; height: 17px; accent-color: var(--brand-500); cursor: pointer; }
.ubaum-tab__cb:disabled { cursor: default; }

/* Nutzungsart: drei kleine Kästchen, die einander ausschliessen; keins = immer. */
.ubaum-tab__nutz { white-space: nowrap; }
.ubaum-tab__nutz-opt { display: inline-flex; align-items: center; gap: 3px; margin-right: 8px;
    font-size: 12px; color: var(--text-2); cursor: pointer; user-select: none; }
.ubaum-tab__nutz-opt:last-child { margin-right: 0; }
.ubaum-tab__nutz-opt input { accent-color: var(--brand-500); width: 14px; height: 14px; cursor: pointer; }
.ubaum-tab__nutz-opt input:checked + span { color: var(--navy); font-weight: 700; }

.ubaum-tab__quelle { color: var(--text-2); font-size: 13px; }

.ubaum-tab__aktionen { text-align: right; }
.ubaum-tab__aktionen-in { display: inline-flex; gap: 2px; justify-content: flex-end; align-items: center; }

/* ── Unterlagenbaum-Tabelle: Inline-Textfelder, Griff, Ziehen, Merkzettel ─────
   Nachtrag zum Tabellen-Block weiter oben: Quelle und Hinweis werden an Ort und
   Stelle bearbeitet, der Griff sortiert per Ziehen, und die Erklärung „Wie der
   Baum gemeint ist" steckt im Fragezeichen des Kopfes. */

/* Bearbeitbare Textfelder — als Text getarnt, beim Berühren als Feld erkennbar. */
.ubaum-tab__edit { display: inline-block; min-width: 44px; border-radius: 6px; padding: 2px 6px;
    outline: none; transition: background .12s, box-shadow .12s; overflow-wrap: anywhere; }
.ubaum-tab__edit[contenteditable] { cursor: text; }
.ubaum-tab__edit[contenteditable]:hover { background: var(--surface-2); }
.ubaum-tab__edit[contenteditable]:focus { background: var(--surface);
    box-shadow: 0 0 0 2px var(--brand-100, rgba(70, 185, 114, .35)); }
.ubaum-tab__edit.is-busy { opacity: .5; }
/* Platzhalter nur, wenn leer UND bearbeitbar — und dezent, erst beim Überfahren
   der Zeile oder im Fokus, damit nicht in jeder Zeile ein „Hinweis …" blasst. */
.ubaum-tab__edit[contenteditable]:empty::before { content: attr(data-empty); color: var(--text-3);
    pointer-events: none; opacity: 0; transition: opacity .12s; }
.ubaum-tab__zeile:hover .ubaum-tab__edit[contenteditable]:empty::before,
.ubaum-tab__edit[contenteditable]:focus:empty::before { opacity: 1; }
.ubaum-tab__hinweis.ubaum-tab__edit { display: block; }

/* Griff zum Ziehen: fasst die ganze Zeile samt Unterbaum an. */
.ubaum-tab__griff { display: inline-grid; place-items: center; width: 26px; height: 30px;
    color: var(--text-3); cursor: grab; touch-action: none; border-radius: 7px; }
.ubaum-tab__griff:hover { color: var(--text-2); background: var(--surface-2); }
.ubaum-tab__griff svg { width: 15px; height: 15px; }
.ubaum-dragging, .ubaum-dragging * { cursor: grabbing !important; user-select: none !important; }
.ubaum-tab__zeile.is-dragging > td { opacity: .45; }

/* Wohin es fällt: eine Linie oben bzw. unten an der Zielzeile. */
.ubaum-tab__zeile.is-drop-before > td { box-shadow: inset 0 2px 0 0 var(--brand-500); }
.ubaum-tab__zeile.is-drop-after > td { box-shadow: inset 0 -2px 0 0 var(--brand-500); }

/* Merkzettel im Kopf (Fragezeichen-Popover). */
.ubaum-info { display: inline-flex; }
.ubaum-info .infoi { margin-bottom: 0; }
.ubaum-info .infoi__pop { max-width: 380px; }
.ubaum-info__liste { margin: 0; padding-left: 18px; }
.ubaum-info__liste li { margin: 5px 0; }
.ubaum-info__liste li:first-child { margin-top: 0; }
.ubaum-info__liste li:last-child { margin-bottom: 0; }

/* ── Unterlagenbaum-Tabelle: Zeile öffnet den Dialog ─────────────────────────
   Kein „Bearbeiten"-Knopf mehr — die ganze Zeile ist anklickbar. Die
   interaktiven Teile behalten ihren eigenen Zeiger, damit klar bleibt, was ein
   Feld ist und was den Dialog öffnet. */
.ubaum-tab__zeile { cursor: pointer; }
.ubaum-tab__zeile .ubaum-tab__edit[contenteditable] { cursor: text; }
.ubaum-tab__zeile .ubaum-tab__griff { cursor: grab; }

/* ── Unterlagenbaum-Tabelle: Sortieren und Filtern ───────────────────────────
   Solange sortiert oder gefiltert wird, steht der Baum flach — der Griff ruht,
   damit niemand an einer Zeile zieht, die gerade nicht an ihrem Platz steht. */
.ubaum-tab.is-flach .ubaum-tab__griff { visibility: hidden; }
.th-sort__pf { font-size: 10px; }

/* ── Knoten-Dialog: Abhängigkeit von Wertart und Anlass ──────────────────────
   Je Wert eine Dreistufe (–/nötig/Pflicht) in einem kompakten Feld; eingeklappt,
   damit der Dialog kurz bleibt. Leer = gilt für alle. */
.ubtag { margin-top: 12px; border: 1px solid var(--border); border-radius: 8px; padding: 0 12px; }
.ubtag > summary { cursor: pointer; padding: 10px 2px; font-weight: 600; font-size: 13.5px;
    display: flex; align-items: center; gap: 8px; list-style: none; }
.ubtag > summary::-webkit-details-marker { display: none; }
.ubtag > summary::before { content: "▸"; color: var(--text-3); font-size: 11px; }
.ubtag[open] > summary::before { content: "▾"; }
.ubtag__zahl { margin-left: auto; font-weight: 400; font-size: 12px; color: var(--text-2); }
.ubtag__hint { font-size: 12px; color: var(--text-3); padding: 0 2px 8px; }
.ubtag__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 5px 16px; padding-bottom: 12px; }
.ubtag__row { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 13px; }
.ubtag__name { color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ubtag__sel { flex: none; height: 26px; font-size: 12px; padding: 2px 6px; border-radius: 6px;
    border: 1px solid var(--border); background: var(--surface-2); color: var(--text); }
.ubtag__sel:focus { border-color: var(--brand-500); background: var(--surface); outline: none; }

/* ── Vorschau der benötigten Unterlagen (Auftragsseite) ──────────────────────
   Was der gewählte Anlass und die Wertarten an Unterlagen verlangen, nach
   Rubrik gegliedert, Pflicht markiert. Reine Anzeige, füllt sich per AJAX. */
.uvor { margin-top: 16px; border: 1px solid var(--border); border-radius: 10px;
    padding: 12px 14px; background: var(--surface-2); }
.uvor__kopf { font-weight: 700; font-size: 13.5px; display: flex; align-items: baseline;
    gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.uvor__note { font-weight: 400; font-size: 12px; color: var(--text-2); }
.uvor.is-laedt { opacity: .55; }
.uvor__zahl { font-size: 12px; color: var(--text-2); margin-bottom: 6px; }
.uvor__rubrik { font-weight: 700; font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em;
    color: var(--text-2); margin: 10px 0 3px; }
.uvor__pos { display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 3px 0; font-size: 13.5px; }
.uvor__name { overflow-wrap: anywhere; }
.uvor__leer { font-size: 13px; color: var(--text-3); padding: 6px 0; }

/* ── Knoten-Dialog: Body scrollt, statt den Dialog zu sprengen ───────────────
   Zwischen Dialog (Flex-Spalte, auf Bildschirmhöhe gedeckelt) und Body steht
   das <form>. Ohne eigene Flex-Angaben wächst das Formular über den Dialog
   hinaus, sobald die Wertart-/Anlass-Listen aufgeklappt sind — und der Inhalt
   läuft unten heraus. Also das Formular selbst zur gedeckelten Flex-Spalte
   machen und den Body darin scrollen lassen. Kopf und Fuß bleiben stehen. */
.modal__dialog--tags > form {
    display: flex; flex-direction: column; min-height: 0; max-height: 100%;
    flex: 1 1 auto;
}
.modal__dialog--tags .modal__head,
.modal__dialog--tags .modal__foot { flex: none; }
.modal__dialog--tags .modal__body { flex: 1 1 auto; min-height: 0; overflow: auto; }

/* ══ BENOETIGTE UNTERLAGEN ═══════════════════════════════════════════════════
   Ein Baum aus Rubriken und Unterlagen, jede mit zwei Entscheidungen und einer
   Anmerkung. Die Nummern kommen aus Zaehlern des Stylesheets: „3.2" muss nach
   dem Ausblenden einer Rubrik stimmen, ohne dass jemand nachtraegt. */
.ubaum { display: flex; flex-direction: column; gap: 14px; }

.uliste { counter-reset: urubrik; list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 14px; }
.urubrik { counter-increment: urubrik; }
/* Der Kopf ist die Schaltflaeche: die ganze Zeile, nicht nur ein Pfeilchen. */
.urubrik__kopf {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px 6px 4px; border-bottom: 1px solid var(--border);
  font-weight: 600; font-size: 13.5px; cursor: pointer;
  border-radius: 6px 6px 0 0; list-style: none;
}
.urubrik__kopf::-webkit-details-marker { display: none; }
.urubrik__kopf:hover { background: var(--surface-2); }
.urubrik__kopf:focus-visible { outline: 2px solid var(--brand-500); outline-offset: -2px; }
/* Der Pfeil dreht sich beim Aufklappen — dieselbe Sprache wie im Ordnerbaum
   und in der Speicherverwaltung. */
.urubrik__kopf::after {
  content: ''; flex: none; width: 8px; height: 8px; margin-left: 2px;
  border: solid var(--text-3); border-width: 0 2px 2px 0;
  transform: rotate(-45deg); transition: transform .12s;
}
.urubrik__box[open] > .urubrik__kopf::after { transform: rotate(45deg); }
.urubrik__box[open] > .urubrik__kopf { background: var(--surface-2); }

/* Was drinsteht, ohne aufzuklappen. */
.urubrik__pflicht, .urubrik__eigen {
  font-weight: 500; font-size: 11px; border-radius: 20px; padding: 1px 8px;
  white-space: nowrap; flex: none;
}
.urubrik__pflicht { color: var(--brand-700); background: rgba(70, 185, 114, .14); }
.urubrik__eigen { color: #8a6300; background: rgba(224, 168, 0, .18); }

.ubaum__leiste { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ubaum__leiste .text-3 { margin-right: auto; }
.urubrik__kopf::before {
  content: counter(urubrik) "."; color: var(--brand-700); font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.urubrik__ico { width: 15px; height: 15px; color: var(--text-3); flex: none; }
/* Wie viele darin stehen — die Zahl beantwortet „habe ich alles?", bevor man
   aufklappt. */
.urubrik__zahl {
  font-weight: 400; font-size: 11.5px; color: var(--text-3);
  border: 1px solid var(--border); border-radius: 20px; padding: 1px 8px;
  flex: none;
}
/* Der Name nimmt den Platz — die Marken danach behalten ihre Groesse. */
.urubrik__name { min-width: 0; flex: 1 1 auto; }

.uliste__kinder { counter-reset: upos; list-style: none; margin: 0; padding: 0; }
.uzeile {
  counter-increment: upos; padding: 9px 0; border-bottom: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 6px;
}
.uzeile:last-child { border-bottom: 0; }
.uzeile__kopf { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
.uzeile__name {
  display: flex; align-items: baseline; gap: 8px; min-width: 0; flex: 1 1 240px;
  font-size: 13.5px;
}
.uzeile__name::before {
  content: counter(urubrik) "." counter(upos);
  color: var(--text-3); font-variant-numeric: tabular-nums; font-size: 12px;
  flex: none; min-width: 26px;
}
/* Woher sie kommt (Grundbuchamt, Bauamt) — leiser als der Name. */
.uzeile__quelle { font-size: 11.5px; color: var(--text-3); }
/* Wie lange die Beschaffung dauert — aenderbar, mit dem Erfahrungswert des
   Katalogs als Platzhalter. Leer heisst „wie im Katalog", nicht „null Tage". */
.uzeile__dauer {
  display: inline-flex; align-items: center; gap: 5px; flex: none;
  font-size: 11px; color: var(--text-3); white-space: nowrap;
}
.uzeile__tage {
  width: 46px; height: 28px; padding: 2px 6px; text-align: center;
  font-size: 12px; font-variant-numeric: tabular-nums;
}
.uzeile__tage::placeholder { color: var(--text-3); opacity: .7; }

/* ══ ZEITPLAN DER BESCHAFFUNG ═══════════════════════════════════════════════
   Ein Balken je Unterlage, alle bei null beginnend: Die Beschaffung laeuft
   nebeneinander her. Die Gesamtdauer ist deshalb das LAENGSTE Stueck und nicht
   die Summe — sie steht gross oben. */
/* Kopf und Fuss stehen, die Zeilen rollen dazwischen. Bei fuenfzig Zeilen war
   die Gesamtdauer nach zwei Umdrehungen aus dem Bild — und der
   Speichern-Knopf erst recht. Die Hoehe kommt vom Dialog, deshalb `min-height:
   0`: Ohne das waechst ein Flex-Kind mit seinem Inhalt und rollt nirgends. */
#unterlagenPlanModal .modal__dialog {
  width: min(1560px, 97vw);
  height: min(880px, calc(100vh - 40px));
}
#unterlagenPlanModal .modal__body {
  display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto;
}
.uplan { display: flex; flex-direction: column; gap: 12px; min-height: 0; flex: 1 1 auto; }
.uplan__fest { flex: none; display: flex; flex-direction: column; gap: 4px; }
.uplan__rollen {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 4px; padding-top: 4px;
}
/* Der Fuss gehoert zum Dialog und nicht zum rollenden Teil. */
#unterlagenPlanModal .uplan__fuss { flex: none; margin-top: 0; }
.uplan__kopf {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  padding-bottom: 12px; border-bottom: 1px solid var(--border);
}
.uplan__gross { font-size: 15px; color: var(--text-2); }
.uplan__gross b {
  font-size: 30px; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums; margin-right: 4px;
}
.uplan__wozu { flex: 1 1 240px; font-size: 12.5px; color: var(--text-3); line-height: 1.5; }
/* Die Bedienhinweise: einmal lesen, dann nie wieder — deshalb klein und grau. */
.uplan__wie { font-size: 11.5px; color: var(--text-3); opacity: .85; }

.uplan__zahlen { display: flex; flex-wrap: wrap; gap: 8px; font-size: 12px; }
.uplan__zahlen > span {
  border: 1px solid var(--border); border-radius: 20px; padding: 2px 10px;
  color: var(--text-2);
}
.uplan__offen { color: #8a6300; border-color: rgba(224, 168, 0, .45); }

.uplan__liste { display: flex; flex-direction: column; gap: 4px; }
/* Nr. · Bedarf · AG · GA · Bezeichnung · Quelle · Balken · Tage
   Erst „brauche ich das", dann „wer holt es", dann was und woher — die
   Reihenfolge, in der die Fragen kommen. */
.uplan__zeile {
  display: grid;
  grid-template-columns: 38px 96px 30px 30px 42px minmax(140px, 1.5fr) minmax(80px, .8fr)
    minmax(120px, 1.8fr) 64px;
  align-items: center; gap: 8px; font-size: 12.5px;
}
/* Woher sie kommt — leiser als der Name, sie ist ein Hinweis und kein Titel. */
.uplan__quelle {
  color: var(--text-3); font-size: 11.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── Filterzeile ────────────────────────────────────────────────────────────
   Unter der Spaltenzeile, wie in den Listen der Anwendung — und mit derselben
   Erwartung: Man tippt, und die Zeilen verschwinden. Die Felder heissen NICHT
   `input`: Sonst baute reiches-select.js sie zu Select2 um, und eine
   Filterzeile aus vier Select2-Kaesten waere hoeher als die Liste darunter. */
.uplan__zeile--filter { padding-bottom: 6px; border-bottom: 1px solid var(--border); }
.uplanfilter {
  width: 100%; min-width: 0; height: 26px; padding: 2px 7px;
  font: inherit; font-size: 11.5px; color: var(--text);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 6px; outline: none;
}
.uplanfilter:focus { border-color: var(--brand-500); }

/* ── Der Bedarf als Knopf mit drei Stufen ───────────────────────────────────
   Ein Klick schaltet weiter: Pflicht, Optional, Entfaellt. Eine Auswahlliste
   verlangte zwei Klicks und einen Blick in ein Menue — die Frage hat drei
   Antworten, und man sieht die aktuelle im Knopf stehen. Die Farbe ist
   dieselbe wie im Schalter der Liste darunter. */
.uplanstufe {
  width: 100%; min-width: 0; height: 26px; padding: 1px 8px;
  font: inherit; font-size: 11.5px; font-weight: 600;
  border-radius: 20px; border: 1px solid var(--border);
  background: var(--surface); cursor: pointer; outline: none;
  white-space: nowrap; text-align: center;
}
.uplanstufe:hover { filter: brightness(.97); }
.uplanstufe:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 1px; }
.uplanstufe--pflicht {
  color: #9b2226; border-color: rgba(155, 34, 38, .40); background: rgba(155, 34, 38, .09);
}
.uplanstufe--optional {
  color: #8a6300; border-color: rgba(224, 168, 0, .45); background: rgba(224, 168, 0, .14);
}
.uplanstufe--entfaellt { color: var(--text-3); background: var(--surface-2); }

/* Der Filter fuer die Zustaendigkeit steht ueber den beiden Spalten, zu denen
   er gehoert — vorher stand er unter „Quelle", wo ihn niemand sucht. */
.uplan__werfilter { grid-column: span 2; }
.uplan__werfilter .uplanfilter { text-align: center; padding: 2px 2px; }

/* Auf den Punkt druecken heisst: auf die andere Seite. Deshalb zeigt er das
   auch — der Zeiger wird zur Hand, und die leere Spalte daneben laedt ein. */
.uplan__wer[data-uplan-wer] { cursor: pointer; border-radius: 6px; }
.uplan__wer[data-uplan-wer]:hover { background: var(--surface-2); }
.uplan__wer[data-uplan-wer]:hover .uplan__marke { transform: scale(1.15); }
.uplan__marke { transition: transform .1s; }

/* Was entfaellt, bleibt stehen — sonst liesse sich der Knopf nicht
   zurueckdrehen. Es zaehlt aber bei nichts mit und sieht auch so aus. */
.uplan__zeile.ist-entfaellt { opacity: .5; }
.uplan__zeile.ist-entfaellt .uplan__name { text-decoration: line-through; }
.uplan__weg { color: var(--text-3); }

.uplan__leer { padding: 14px 2px; color: var(--text-3); font-size: 12.5px; }
.uplan__gefiltert { color: var(--navy-mid); border-color: rgba(12, 58, 110, .35); }

/* ── Der Balken laesst sich ziehen ──────────────────────────────────────────
   Die Spur ist der Massstab, nicht der Balken: Sonst liesse sich ein Balken,
   den man auf null gezogen hat, nicht wieder fassen. */
.uplan__spur { cursor: ew-resize; }
.uplan__balken { position: relative; }
.uplan__griff {
  position: absolute; right: 0; top: 0; bottom: 0; width: 6px;
  border-radius: 0 4px 4px 0; background: rgba(255, 255, 255, .55);
}
.uplan__spur:hover .uplan__griff { background: #fff; }
/* Ueber die Spur hinausgezogen: Der Balken ist voll, die Zahl daneben laeuft
   weiter. Der angeschraegte Rand sagt, dass es rechts weitergeht. */
.uplan__balken.ist-ueber {
  border-radius: 4px 0 0 4px;
  background-image: linear-gradient(105deg, transparent 92%, rgba(255,255,255,.45) 92%);
}

/* ── Der Fuss des Dialogs ───────────────────────────────────────────────────
   „Speichern" schickt das ganze Auftragsformular ab — was hier umgestellt
   wurde, steht in denselben Feldern wie im Reiter darunter. */
.uplan__fuss {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border);
}
.uplan__stand { font-size: 12px; color: #8a6300; }
.uplan__zeile--kopf {
  font-size: 11px; font-weight: 600; color: var(--text-3);
  text-transform: uppercase; letter-spacing: .04em;
  padding-bottom: 4px; border-bottom: 1px solid var(--border);
}
.uplan__nr { color: var(--text-3); font-variant-numeric: tabular-nums; }
/* Zwei schmale Spalten, in denen genau eine Marke steht. Man liest sie
   hinunter und sieht, was auf der eigenen Liste steht und was man anmahnen
   muss — das ist mit einer Farbe am Balken allein nicht zu sehen. */
.uplan__wer { display: grid; place-items: center; }
.uplan__marke {
  width: 11px; height: 11px; border-radius: 50%; display: block;
}
.uplan__marke--auftraggeber { background: var(--navy-mid); }
.uplan__marke--gutachter { background: #00a1a3; }
/* Die andere Seite steht als blasser Ring da. Eine leere Zelle sieht aus, als
   gaebe es dort nichts zu holen — der Ring sagt: Hier kann er auch stehen,
   klick mich. Beim Ueberfahren wird er kraeftiger und nimmt schon die Farbe
   an, die er nach dem Klick haette. */
.uplan__marke.ist-aus {
  background: transparent; border: 1px solid var(--border); box-sizing: border-box;
}
.uplan__wer[data-uplan-wer]:hover .uplan__marke--auftraggeber.ist-aus {
  border-color: var(--navy-mid); background: rgba(12, 58, 110, .18);
}
.uplan__wer[data-uplan-wer]:hover .uplan__marke--gutachter.ist-aus {
  border-color: #00a1a3; background: rgba(0, 161, 163, .20);
}

/* ── Sieht der Auftraggeber sie? ────────────────────────────────────────────
   Ein Auge, kein Haken: Die Frage ist nicht „stimmt das", sondern „steht das
   auf SEINER Liste". Durchgestrichen heisst intern — die Zeile bleibt im Plan
   stehen, denn beschafft werden muss sie ja doch, nur eben vom Haus. */
.uplan__sichtz { display: grid; place-items: center; cursor: pointer; }
.uplan__auge { color: var(--navy-mid); transition: transform .1s, color .1s; }
.uplan__auge.ist-aus { color: var(--text-3); opacity: .65; }
.uplan__sichtz:hover .uplan__auge { transform: scale(1.12); }
.uplan__sichtz:hover .uplan__auge.ist-aus { color: var(--navy-mid); opacity: 1; }
.uplan__sichtz:focus-visible { outline: 2px solid var(--brand-500); outline-offset: -2px;
  border-radius: 5px; }
/* Der Kopf dieser Spalte hat wenig Platz — er darf nicht umbrechen. */
.uplan__sicht { text-align: center; font-size: 11.5px; }

/* ── Sortieren am Spaltenkopf ───────────────────────────────────────────────
   Statt zweier Knoepfe „sortiert nach …" ist jede Spalte selbst der Schalter —
   dort, wo man hinsieht, wenn man nach ihr ordnen will. Ein zweiter Klick
   dreht die Richtung; der Pfeil sagt, wie herum es steht. */
.uplan__kopf-sort {
  cursor: pointer; border-radius: 5px; padding: 1px 4px; margin: 0 -4px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.uplan__kopf-sort:hover { background: var(--surface-2); color: var(--text-2); }
.uplan__kopf-sort:focus-visible { outline: 2px solid var(--brand-500); outline-offset: -1px; }
.uplan__kopf-sort.ist-an { color: var(--brand-700); }
.uplan__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-2); }
.uplan__zeile.ist-pflicht .uplan__name { color: var(--text); font-weight: 600; }
/* Die Spur zeigt, wie viel vom Ganzen dieser Balken einnimmt — ohne sie
   schwebten die Balken im Nichts. */
.uplan__spur { height: 16px; background: var(--surface-2); border-radius: 4px;
  overflow: hidden; display: flex; align-items: center; }
.uplan__balken { height: 100%; border-radius: 4px; min-width: 3px; }
/* Dieselben zwei Farben wie am Schalter: Wer wartet auf wen. */
.uplan__balken--auftraggeber { background: var(--navy-mid); }
.uplan__balken--gutachter { background: #00a1a3; }
.uplan__ohne { font-size: 11px; color: var(--text-3); padding-left: 6px; }
.uplan__tage { text-align: right; color: var(--text-2); font-variant-numeric: tabular-nums; }

@media (max-width: 900px) {
  /* Die Quelle faellt zuerst weg — sie ist der Hinweis, nicht die Sache. */
  .uplan__zeile { grid-template-columns: 30px 88px 26px 26px 34px minmax(0, 1fr) 56px; }
  .uplan__quelle { display: none; }
  .uplan__spur { grid-column: 1 / -1; }
}
.uzeile__anmerkung { font-size: 12.5px; margin-left: 34px; }

/* „Entfaellt" bleibt lesbar und tritt zurueck: Die Zeile ist nicht weg, es ist
   entschieden worden. Ein Ausblenden verstecke genau diese Entscheidung. */
.uzeile.ist-entfaellt .uzeile__name { color: var(--text-3); text-decoration: line-through; }
.uzeile.ist-entfaellt { opacity: .72; }
.uzeile.ist-entfaellt .uzeile__anmerkung { display: none; }

/* ── Der Schalter aus Radiofeldern ──────────────────────────────────────────
   Drei Zustaende, kein Haekchen: „Pflicht", „Optional", „Entfaellt" sind drei
   Antworten. Radiofelder tragen ihren Zustand selbst und gehen ohne Skript mit
   dem Formular mit — ein Fremd-Widget rendert dafuer ein Textfeld, und ein
   Abwaehlen kann darin verlorengehen. */
.uschalter { display: inline-flex; flex: none; border: 1px solid var(--border);
  border-radius: 8px; overflow: hidden; background: var(--surface-2); }
.uschalter__feld { position: absolute; opacity: 0; pointer-events: none; }
.uschalter__wahl {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 10px; font-size: 12px; font-weight: 500; color: var(--text-3);
  cursor: pointer; user-select: none; white-space: nowrap;
  border-right: 1px solid var(--border); margin: 0;
}
.uschalter__wahl:last-child { border-right: 0; }
.uschalter__wahl:hover { background: var(--surface); color: var(--text-2); }
/* Das Zeichen der NICHT gewaehlten Seite tritt zurueck — sonst leuchten in
   einer Zeile sechs Symbole gleich stark, und keines sagt mehr etwas. */
.uschalter__ico { width: 13px; height: 13px; flex: none; opacity: .55; }
.uschalter__feld:checked + .uschalter__wahl .uschalter__ico { opacity: 1; }

.uschalter__feld:checked + .uschalter__wahl {
  background: var(--surface); color: var(--text); font-weight: 600;
  box-shadow: inset 0 -2px 0 currentColor;
}

/* ── Die drei Zustaende tragen ihre eigene Farbe ────────────────────────────
   Sie sind nicht gleichwertig, und in einer Liste aus fuenfzig Zeilen liest
   man die Woerter nicht mehr — man sieht die Farbe. Pflicht ist dunkelrot
   (ohne sie geht es nicht), Optional gelb (waere gut), Entfaellt grau
   (erledigt sich). Gruen waere hier falsch: Es hiesse „in Ordnung", und
   nichts davon ist ein Zustand, den man abhaken kann. */
.uschalter__feld:checked + .uschalter__wahl--pflicht {
  color: #9b2226; background: rgba(155, 34, 38, .10);
}
.uschalter__feld:checked + .uschalter__wahl--optional {
  color: #8a6300; background: rgba(224, 168, 0, .16);
}
.uschalter__feld:checked + .uschalter__wahl--entfaellt {
  color: var(--text-3); background: var(--surface-2);
}
:root[data-theme="dark"] .uschalter__feld:checked + .uschalter__wahl--pflicht { color: #f08a8d; }
:root[data-theme="dark"] .uschalter__feld:checked + .uschalter__wahl--optional { color: #e8c260; }

/* Wer sie beibringt: zwei Rollen, zwei Farben — aber leiser als der Bedarf.
   Die Frage „brauche ich das ueberhaupt" kommt vor „wer holt es". */
.uschalter__feld:checked + .uschalter__wahl--auftraggeber {
  color: var(--navy-mid); background: rgba(12, 58, 110, .08);
}
.uschalter__feld:checked + .uschalter__wahl--gutachter {
  color: #007678; background: rgba(0, 161, 163, .12);
}
.uschalter__feld:focus-visible + .uschalter__wahl { outline: 2px solid var(--brand-500);
  outline-offset: -2px; }

@media (max-width: 700px) {
  /* Nebeneinander bliebe fuer den Namen nichts uebrig. */
  .uzeile__kopf { flex-direction: column; align-items: stretch; }
  .uzeile__anmerkung { margin-left: 0; }
}

/* Untertitel je Obergruppe im Objekttyp-Abschnitt des Knoten-Dialogs. */
.ubtag__gruppe { font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
    color: var(--text-3); font-weight: 700; margin: 10px 0 2px; }

/* Objekttyp-Wähler in der Unterlagen-Vorschau (Auftragsseite). */
.uvor__wahl { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.uvor__wahl-label { font-size: 12px; color: var(--text-2); }
.uvor__sel { height: 30px; font-size: 13px; padding: 3px 8px; border-radius: 7px;
    border: 1px solid var(--border); background: var(--surface); color: var(--text); max-width: 340px; }

/* Beschaffer und Bankarbeitstage je Zeile in der Unterlagen-Vorschau. */
.uvor__pos { justify-content: flex-start; }
.uvor__name { flex: 1 1 auto; min-width: 0; }
.uvor__meta { flex: none; font-size: 11.5px; color: var(--text-3); white-space: nowrap; }

/* ── Tabelle: Spalte „Beschaffung" (Beschaffer + Bankarbeitstage) ────────────
   Nur Anzeige; geändert wird im Dialog. AG = Auftraggeber (neutral),
   GU = Gutachter (grün, weil er öffentliche Auskünfte selbst zieht). */
.ubaum-tab__bt { white-space: nowrap; text-align: right; font-size: 12.5px; color: var(--text-2); }
.ubaum-tab__bt-in { display: inline-flex; align-items: center; gap: 6px; justify-content: flex-end; }
.ubaum-tab__wer { font-size: 10px; font-weight: 700; letter-spacing: .03em; padding: 1px 5px;
    border-radius: 5px; border: 1px solid var(--border); color: var(--text-2); background: var(--surface-2); }
.ubaum-tab__wer--gutachter { color: var(--brand-700, var(--brand-600)); border-color: var(--brand-500);
    background: rgba(70, 185, 114, .12); }

/* Beschaffer-Schalter im Knoten-Dialog: Auftraggeber ⟷ Gutachter.
   Die aktive Seite wird hervorgehoben (per :has, sonst neutral). */
.bschalter { gap: 9px; margin-top: 4px; }
.bschalter__seite { font-size: 13px; color: var(--text-3); font-weight: 500; }
.bschalter:has(.switch__input:not(:checked)) .bschalter__ag,
.bschalter:has(.switch__input:checked) .bschalter__gu { color: var(--navy); font-weight: 700; }

/* Stammlisten-Sortiergriff (Ziehen statt Auf/Ab-Buttons). */
.stammgriff { cursor: grab; touch-action: none; }
.stamm-dragging, .stamm-dragging * { cursor: grabbing !important; user-select: none !important; }
tr.is-stammdrag > td { opacity: .45; }

/* Sonderbedingungen im Knoten-Dialog (Vollgutachten, Neubau, Bundesland). */
.ubsonder { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 16px; align-items: start; padding-bottom: 12px; }
.ubsonder__bl { grid-column: 1 / -1; }
.ubsonder__sel { height: auto; padding: 4px 6px; }

/* ── Zahlenfeld mit Einheit im Feld (Bankarbeitstage, Max. Alter) ───────────
   Die Hülle sieht aus wie .input; das Ziffernfeld darin ist randlos und schmal,
   die Einheit steht als stiller Zusatz direkt dahinter und wechselt zwischen
   Ein- und Mehrzahl (ubaum-tabelle.js). Gespeichert wird nur die Zahl. */
.feld-maske {
  display: flex; align-items: center; gap: .35em; width: 100%;
  height: var(--control-h); font-size: 14px; color: var(--text);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 0 13px; cursor: text;
  transition: border-color .12s, box-shadow .12s; }
.feld-maske:focus-within {
  border-color: var(--brand-500); box-shadow: 0 0 0 3px rgba(70,185,114,.25); }
.feld-maske__zahl {
  flex: 0 0 auto; width: 3.5ch; border: 0; background: transparent; padding: 0;
  margin: 0; outline: none; font: inherit; color: inherit; text-align: right; }
.feld-maske__zahl::placeholder { color: var(--text-3); }
.feld-maske__einheit { flex: 0 0 auto; color: var(--text-2); white-space: nowrap; }
.feld-maske__einheit:empty { display: none; }

/* Eine Unterlage, die der Kunde nicht sieht — er koennte sie nicht liefern.
   Im Auftrag steht sie weiter, nur leise gekennzeichnet. */
/* Es steht immer im Markup und wird von der Klasse an der Zeile gezeigt:
   Das Umschalten im Zeitplan muesste sonst HTML nachbauen. */
.uzeile__intern { display: none; }
.uzeile.ist-intern .uzeile__intern {
  display: inline-block; margin-left: 8px; padding: 1px 6px;
  font-size: 11px; line-height: 1.5; white-space: nowrap;
  color: var(--text-2); background: var(--surface-2, rgba(127,127,127,.12));
  border: 1px solid var(--border); border-radius: 999px; }

/* Die Länderliste. Eine abgewählte Zeile muss man SEHEN — sonst sieht ein
   Klick auf das Kästchen aus, als wäre nichts geschehen. `is-aus` gab es
   bisher nur im Unterlagenbaum und blieb hier ohne jede Wirkung. */
.geo-tab tr.is-aus td { opacity: .45; }
.geo-tab tr.is-aus td:last-child { opacity: 1; }
.geo-tab .checkbox { margin: 0; }
.geo-tab tbody tr:hover td { background: var(--surface-2, rgba(127,127,127,.06)); }

/* Länderliste: Griff, Flagge, Stern. */
.geo-tab__griff-c { width: 1%; padding-right: 0 !important; }
.geo-tab__griff { display: inline-flex; align-items: center; color: var(--text-3);
  cursor: grab; touch-action: none; opacity: 0; transition: opacity .12s; }
.geo-tab tbody tr:hover .geo-tab__griff, .geo-tab tr.wird-gezogen .geo-tab__griff { opacity: 1; }
.geo-tab__griff:active { cursor: grabbing; }
.geo-tab tr.wird-gezogen { background: var(--surface-2, rgba(127,127,127,.10)); }
.geo-tab tr.ist-klickbar { cursor: pointer; }
.geo-tab__flagge-c { width: 1%; padding-right: 0 !important; }
.geo-tab .flag { width: 20px; height: 15px; border-radius: 2px; display: block;
  box-shadow: 0 0 0 1px rgba(0,0,0,.08); }
/* Der Stern: aus = nur Umriss und blass, an = gefüllt. */
.geo-stern { background: none; border: 0; padding: 2px; cursor: pointer; line-height: 0;
  color: var(--text-3); opacity: .45; transition: opacity .12s, color .12s; }
.geo-stern:hover { opacity: 1; }
.geo-stern svg path { fill: none; }
.geo-stern.ist-an { color: #e0a800; opacity: 1; }
.geo-stern.ist-an svg path { fill: currentColor; }
.geo-stern:disabled { cursor: default; opacity: .3; }
/* Der Strich im Auswahlfeld zwischen „oben" und dem Rest. */
.landfeld-strich { color: var(--text-3); }

/* Das erschlossene Bundesland unter der Anschrift des Grundstücks. */
.gst__bundesland { margin: -4px 0 12px; min-height: 20px; }
.gst__bundesland-text { display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--text-2); }
.gst__bundesland-ico { width: 14px; height: 14px; color: var(--text-3); }

/* Die Flagge des Bundeslandes im Seitenkopf — größer als in der Liste. */
.flag--gross { width: 34px; height: 26px; border-radius: 3px; }

/* ── Bodenrichtwert im Grundstück ──────────────────────────────────────────
   Die erste belastbare Zahl eines Auftrags. Sie steht abgesetzt, weil sie
   etwas anderes ist als die Felder darüber: keine Erfassung, sondern eine
   Schätzung — und die soll man als solche sehen. */
.gst-boden { margin: 14px 0 8px; padding: 12px 14px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: var(--surface-2, rgba(127,127,127,.04)); }
.gst-boden__kopf { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.gst-boden__titel { display: inline-flex; align-items: center; gap: 6px;
  font-weight: 600; font-size: 13.5px; }
.gst-boden__ico { width: 15px; height: 15px; flex: none; color: var(--text-3); }
.gst-boden__meldung { font-size: 12.5px; color: var(--text-2); margin-bottom: 10px; }

/* Die Zonen: je eine Schaltfläche, weil jede eine Wahl ist. */
.gst-boden__zonen { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
.brw-zone { display: grid; grid-template-columns: 110px minmax(0,1fr) auto; gap: 2px 12px;
  text-align: left; padding: 7px 10px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: var(--surface); cursor: pointer;
  font: inherit; color: inherit; }
.brw-zone:hover { border-color: var(--brand-500); }
.brw-zone.ist-gewaehlt { border-color: var(--brand-500);
  box-shadow: 0 0 0 2px rgba(70,185,114,.20); }
.brw-zone__wert { grid-row: 1 / 3; align-self: center; font-weight: 700; font-size: 15px; }
.brw-zone__name { font-size: 13px; }
.brw-zone__meta { font-size: 11.5px; color: var(--text-3); }
/* Das Wort am rechten Rand sagt, was ein Klick auf die Zeile tut: Der Wert
   wandert in die Felder darunter. Es sieht aus wie ein Knopf, ist aber keiner —
   die Zeile selbst ist der Knopf, und ein Knopf im Knopf waere ungueltig. */
.brw-zone__nehmen { grid-row: 1 / 3; grid-column: 3; align-self: center;
  padding: 3px 10px; border: 1px solid var(--border); border-radius: 999px;
  font-size: 12px; font-weight: 600; color: var(--text-2); white-space: nowrap; }
.brw-zone:hover .brw-zone__nehmen { border-color: var(--brand-500); color: var(--brand-700); }
.brw-zone.ist-gewaehlt .brw-zone__nehmen { border-color: var(--brand-500);
  background: var(--brand-500); color: #fff; }

/* Die Hochrechnung — Fläche × Satz = Größenordnung. */
.gst-boden__rechnung { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 4px; padding-top: 10px; border-top: 1px dashed var(--border); font-size: 13px; }
.gst-boden__formel { color: var(--text-2); }
.gst-boden__summe { font-size: 16px; }
.gst-boden__fuss { margin: 10px 0 0; font-size: 11.5px; }

/* Das Bundesland unter dem Auswahlfeld: was die Anschrift ergibt. */
.gst__bl-hinweis { margin-top: 4px; font-size: 11.5px; color: var(--text-3); }

/* Der Bodenrichtwert auf der Kartenfläche des Grundstücks — unter der
   Anschrift, weil er zur Lage gehört und nicht zum Objekt. */
.gst__boden { display: block; margin-top: 2px; font-size: 11.5px; color: var(--text-2); }
.gst__boden b { color: var(--text); }

/* Der Bodenwert des ganzen Auftrags — die Summe unter den Grundstückskarten.
   Abgesetzt und ruhig: Sie ist eine Schätzung, keine Erfassung. */
.gst-gesamt { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 14px; padding: 10px 14px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: var(--surface-2, rgba(127,127,127,.05)); }
.gst-gesamt__titel { font-weight: 600; font-size: 13px; }
.gst-gesamt__zahlen { display: inline-flex; align-items: baseline; gap: 6px;
  font-size: 13px; color: var(--text-2); }
.gst-gesamt__summe { font-size: 17px; color: var(--text); }
.gst-gesamt__fuss { flex: 1 1 100%; margin: 2px 0 0; font-size: 11.5px; }

/* ── Grobbewertung im Grundstück ───────────────────────────────────────────
   Drei Blöcke untereinander, darunter die Summe. Ruhig gehalten: Es ist eine
   Schätzung, keine Erfassung — und schon gar kein Gutachten. */
.schaetz__block { margin: 14px 0; padding: 12px 14px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); }
.schaetz__kopf { display: flex; align-items: center; gap: 10px; margin-bottom: 10px;
  font-size: 13px; }
.schaetz__titel { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; }
.schaetz__ico { width: 15px; height: 15px; flex: none; color: var(--text-3); }
/* Ein gerechnetes Ergebnis sieht aus wie ein Feld, ist aber keins. */
.schaetz__ergebnis { height: var(--control-h); display: flex; align-items: center;
  padding: 0 13px; font-size: 15px; font-weight: 600;
  background: var(--surface-2, rgba(127,127,127,.06));
  border: 1px dashed var(--border); border-radius: var(--radius-sm); }

.schaetz__summe { margin-top: 16px; padding: 12px 14px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: var(--surface-2, rgba(127,127,127,.05)); }
.schaetz__tabelle { width: 100%; font-size: 13.5px; }
.schaetz__tabelle td { padding: 5px 0; }
.schaetz__betrag { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.schaetz__zeile-grob td { padding-top: 9px; border-top: 1px solid var(--border); font-size: 16px; }
.schaetz__fuss { margin: 10px 0 0; font-size: 11.5px; }

/* Die zweite Reiterzeile (Teile des Grundbuchblatts). */
.gst__reiter--unter { margin-top: -2px; padding-left: 14px; opacity: .95; }

/* Grobwert und Besonderheiten auf der Grundstückskarte.

   Die Zeichen hiessen `gst__merkmale`/`gst__merkmal` — genau wie der Rahmen
   mit den Haken und dessen Zeilen. Zwei Dinge unter einem Namen: Die spaetere
   Regel machte aus dem Rahmen eine Inline-Reihe, und die fruehere gab den
   Zeichen ein Raster mit acht Pixeln Polster. Deshalb heissen sie jetzt
   `gst__chips`/`gst__chip`. */
.gst__grob { display: block; margin-top: 2px; font-size: 12px; }
.gst__grob b { font-size: 13.5px; }
.gst__chips { display: inline-flex; gap: 5px; flex-wrap: wrap; align-items: center;
  vertical-align: middle; }
/* Kompakter als ein gewoehnliches Badge: Hier stehen bis zu acht davon in einer
   Kopfzeile, und jedes ist eine Randnotiz zum Objekt — kein Status. */
.gst__chip { font-size: 10.5px; font-weight: 600; line-height: 1.5;
  padding: 1px 8px; border-radius: 999px; letter-spacing: .01em; }
.gst-boden__herkunft { margin-left: 4px; }

/* ── Honorartafel: eine Leistungsart je Klappblock ────────────────────────────
   Die BVS-Tafel bringt 75 Positionen mit — dreimal dieselbe 25-stufige Staffel,
   nur unter anderem Namen. In EINER Tabelle heisst das: an fuenfzig Zeilen
   vorbeiscrollen, die man schon gesehen hat. Der zugeklappte Block traegt das
   Wesentliche (Stufen, Spanne) in seiner Kopfzeile; aufgeklappt wird nur, was
   gerade gebraucht wird. */
.htaf__zahlen { margin-bottom: 16px; flex-wrap: wrap; }
.htaf__zahlen .statbox { min-width: 132px; }
.htaf__zahlen .statbox__val { font-size: 18px; white-space: nowrap;
  font-variant-numeric: tabular-nums; }

.htaf__grp { border-bottom: 1px solid var(--border); }
.htaf__grp:last-of-type { border-bottom: 0; }
.htaf__kopf { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 20px; cursor: pointer; list-style: none; }
.htaf__kopf::-webkit-details-marker { display: none; }
.htaf__kopf::before { content: "▸"; color: var(--text-3); font-size: 11px; flex: none; }
.htaf__grp[open] > .htaf__kopf::before { content: "▾"; }
.htaf__kopf:hover { background: var(--surface-2); }
.htaf__name { font-weight: 600; font-size: 14px; }
.htaf__gleich { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px;
  color: var(--text-3); background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 999px; padding: 2px 9px; white-space: nowrap; }
.htaf__gleich svg { width: 12px; height: 12px; flex: none; }
.htaf__meta { margin-left: auto; font-size: 12.5px; color: var(--text-2);
  white-space: nowrap; font-variant-numeric: tabular-nums; }
.htaf__grp > .table { border-top: 1px solid var(--border); }
.htaf__fuss { margin: 0; padding: 10px 20px; font-size: 12px; color: var(--text-3);
  background: var(--surface-2); }

/* Enge Fassung der Tabelle: 25 Staffelstufen mit 13px Innenabstand ergeben
   allein 700px Hoehe, ohne dass eine Zeile mehr sagt. */
.table--eng td { padding: 8px 16px; }

/* ── Eingabeformular, das nicht dauernd im Weg steht ─────────────────────────
   Ein siebenspaltiges Raster unter jeder Liste kostet mehr Platz als die
   Liste selbst — gebraucht wird es beim Pflegen, nicht beim Nachsehen. */
.klappform { border-top: 1px solid var(--border); }
.klappform__kopf { display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  list-style: none; padding: 12px 20px; font-size: 13px; font-weight: 600;
  color: var(--brand-600); }
.klappform__kopf::-webkit-details-marker { display: none; }
.klappform__kopf svg { width: 15px; height: 15px; flex: none; }
.klappform__kopf:hover { color: var(--brand-700); }
.klappform__leib { padding: 0 20px 18px; }

@media (max-width: 700px) {
  .htaf__meta { margin-left: 0; width: 100%; }
}

/* ── Karten in einem Einstellungsbereich ──────────────────────────────────────
   Den Abstand zwischen Karten traegt sonst `.card + .card`. Hier trug ihn
   niemand: Zwischen zwei Karten steht das Modal-Markup ihres Nachbarn —
   `Modal::begin()` rendert an Ort und Stelle —, und damit sind die Karten keine
   unmittelbaren Geschwister mehr. Der Abstand fiel weg, die Karten klebten
   aneinander. Er haengt deshalb an der Karte selbst und nicht an ihrer
   Nachbarschaft; ein Modal, ein Kommentar oder ein Formular dazwischen aendert
   daran nichts mehr. Etwas grosszuegiger als die 16px der uebrigen Anwendung:
   Was hier untereinander steht, sind eigenstaendige Bereiche und nicht
   Abschnitte einer Liste. */
.stg-card__custom > .card,
.stg-custom > .card { margin-top: 20px; }
.stg-card__custom > .card:first-child,
.stg-custom > .card:first-child { margin-top: 0; }

/* ── Honorar: der Rechenweg im Auftrag ───────────────────────────────────────
   Die Posten stehen als Tabelle im grossen Formular. Ihre Saetze sind Felder,
   keine Anzeige — die Spanne der BVS-Richtlinie ist eine Ermessensentscheidung,
   und wer sie nicht aendern kann, uebernimmt eine Zahl, die er nicht gewaehlt
   hat. */
.honorarposten td { vertical-align: middle; }
.honorarposten__summe td {
  border-top: 2px solid var(--border); background: var(--surface-2);
  padding-top: 12px; padding-bottom: 12px; font-size: 14px;
}
.honorarposten tr.text-3 .fw-600 { font-weight: 500; text-decoration: line-through; }

/* Satzfeld: Zahl und Einheit in einem Kaestchen, damit „35" nicht als Betrag
   gelesen wird. */
.satzfeld { display: flex; align-items: center; gap: 6px; }
.satzfeld input { width: 84px; text-align: right; padding-right: 8px; }
.satzfeld input:disabled { background: var(--surface-2); color: var(--text-3); }
.satzfeld__einheit { font-size: 12.5px; color: var(--text-2); flex: none; }

.honorar__leiste {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 0 4px;
}
.honorar__leiste .hint { flex: 1 1 220px; min-width: 0; }

/* ── Honorar: die Grundlagen-Liste ───────────────────────────────────────────
   Was in die Rechnung eingeht, steht hier als ANZEIGE — eingetragen wird es in
   dem Reiter, in dem es hingehoert. Der Knopf rechts springt dorthin: Eine
   Angabe zweimal einzutragen hiesse, sie an einer der beiden Stellen zu
   vergessen. */
.hgrund { border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-2); overflow: hidden; margin-top: 4px; }
.hgrund__zeile { display: grid; grid-template-columns: 150px minmax(0, 1fr) auto;
  gap: 12px; align-items: baseline; padding: 9px 14px;
  border-bottom: 1px solid var(--border); }
.hgrund__zeile:last-child { border-bottom: 0; }
.hgrund__label { font-size: 12.5px; color: var(--text-2); }
.hgrund__wert { font-size: 13.5px; font-weight: 600; min-width: 0; }
.hgrund__wert--leer { font-weight: 500; color: var(--danger); }
.hgrund__zusatz { display: block; font-size: 11.5px; font-weight: 400;
  color: var(--text-3); margin-top: 2px; }
.hgrund__sprung { background: none; border: 0; padding: 0; cursor: pointer;
  font-size: 12px; color: var(--brand-600); white-space: nowrap; }
.hgrund__sprung:hover { color: var(--brand-700); text-decoration: underline; }

@media (max-width: 700px) {
  .hgrund__zeile { grid-template-columns: minmax(0, 1fr) auto; }
  .hgrund__label { grid-column: 1 / -1; }
}

/* ── Symbol in einer Beschriftung ────────────────────────────────────────────
   `.checkbox` richtet seine Teile mit `align-items: center` aus — zentriert
   also zur ZEILE. Der sichtbare Text liegt aber tiefer als deren Mitte: Die
   Zeilenbox reicht unten bis zu den Unterlaengen (g, p, y), oben nur bis zur
   Oberlaenge. Ein Symbol, das geometrisch mittig sitzt, steht damit ueber der
   Mitte der Kleinbuchstaben und wirkt zu hoch. Ein Pixel nach unten gleicht
   das aus — `relative` und nicht `margin`, damit die Zeile ihre Hoehe behaelt.

   Und mehr Luft zum Wort als zum Kaestchen: Kaestchen und Symbol sind beide
   Zeichen, Symbol und Wort sind Zeichen und Sprache. Bei 8 Pixel ringsum
   klebte die Beschriftung am Symbol. */
.cbx-ico { position: relative; top: 1.5px; }
.cbx-ico + * { margin-left: 3px; }


/* ── Auftragsgegenstand ──────────────────────────────────────────────────────
   Derselbe Rahmen wie bei den „Besonderheiten des Objekts", aus demselben
   Grund: Was darin steht, beantwortet EINE Frage — was ist zu tun? Erst daraus
   folgt, was es kostet.

   Drei Spalten: Was gemeint ist, was gilt, und wo es gepflegt wird. Die
   mittlere traegt mal eine Auskunft, mal ein Feld — beides gehoert in dieselbe
   Flucht, sonst liest sich die Liste wie zwei Listen. */
.agegen { border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px 14px 12px; margin: 0; }
.agegen > legend { padding: 0 6px; margin-left: -6px;
  font-size: 12.5px; font-weight: 600; color: var(--text-2); }
.agegen__wozu { margin: 0 0 10px; font-size: 12px; line-height: 1.5; color: var(--text-3); }

.agegen__liste { margin-top: 12px; border-top: 1px solid var(--border); }
.agegen__zeile { display: grid; grid-template-columns: 190px minmax(0, 1fr) auto;
  gap: 12px; align-items: center; padding: 8px 0;
  border-bottom: 1px solid var(--border); }
.agegen__zeile:last-child { border-bottom: 0; }
.agegen__label { font-size: 12.5px; color: var(--text-2); }
/* Ein Feldlabel in der ersten Spalte bringt eigene Abstaende mit — hier ist es
   die Beschriftung einer Zeile und keine Ueberschrift eines Blocks. */
.agegen__label .form-label, .agegen__label label { margin: 0; font-weight: 400;
  font-size: 12.5px; color: var(--text-2); }
.agegen__wert { font-size: 13.5px; font-weight: 600; min-width: 0; }
.agegen__wert--leer { font-weight: 500; color: var(--danger); }
.agegen__zusatz { display: block; font-size: 11.5px; font-weight: 400;
  color: var(--text-3); margin-top: 2px; }
.agegen__sprung { background: none; border: 0; padding: 0; cursor: pointer;
  font-size: 12px; color: var(--brand-600); white-space: nowrap; }
.agegen__sprung:hover { color: var(--brand-700); text-decoration: underline; }

@media (max-width: 700px) {
  .agegen__zeile { grid-template-columns: minmax(0, 1fr) auto; }
  .agegen__label { grid-column: 1 / -1; }
}

/* ── Fahrt und Termine im Kasten ─────────────────────────────────────────────
   Links die Strecke, rechts was dort geschieht. Nebeneinander, weil das eine
   das andere erklaert: Wer drei Termine ansetzt, faehrt die Strecke dreimal. */
.besich { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 18px; }
.besich__map { height: 300px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); overflow: hidden; background: var(--surface-2); }
.besich__leer { display: grid; place-items: center; height: 100%; padding: 20px;
  text-align: center; font-size: 12.5px; color: var(--text-3); }
.besich__tabelle { margin-top: 12px; }
.besich__tabelle .input { padding: 5px 8px; font-size: 13px; }
.besich__tabelle td { padding: 5px 6px; }
.besich__tabelle th { padding-left: 6px; padding-right: 6px; }

@media (max-width: 860px) {
  .besich { grid-template-columns: minmax(0, 1fr); }
  .besich__map { height: 220px; }
}

/* Abschnitte im Honorar-Reiter: Der Auftragsgegenstand endet mit einem Rahmen,
   und was danach kommt, faengt einen neuen Gedanken an. `mt-3` reichte dafuer
   nicht — die Ueberschrift klebte am Rahmen darueber. */
.honorar__trenner { margin-top: 28px; }

/* ── Auftragsgegenstand: Abstand unten und Symbole vor den Zeilen ────────────
   Der Rahmen schliesst mit Luft ab — die letzte Zeile klebte sonst am Rand,
   und ein Auswahlfeld direkt auf der Linie sieht aus wie herausgerutscht. */
.agegen { padding-bottom: 16px; margin-bottom: 8px; }

/* Das Symbol ordnet, es erklaert nicht: Beim Ueberfliegen findet man die Zeile
   am Zeichen schneller als am Wort. `align-items: center` und nicht `start` —
   die Beschriftungen sind einzeilig, und bei einem Feldlabel mit Fragezeichen
   sitzt das Zeichen sonst ueber der Schrift. */
.agegen__label { display: flex; align-items: center; gap: 8px; }
.agegen__ico { width: 15px; height: 15px; flex: none; color: var(--text-3); }
/* Die Beschriftung daneben bringt eigene Abstaende mit — in einer Zeile
   stoeren sie. */
.agegen__label .labelzeile { margin: 0; gap: 4px; }
.agegen__label .labelzeile label, .agegen__label > label { margin: 0; }
.agegen__label .infoi { margin-bottom: 0; }

/* ── Vorgutachten in der Gegenstandszeile ────────────────────────────────────
   Nummer und darunter, woran man es erkennt: Art, Objekt, Stichtag, Wert. Die
   Nummer allein sagt nach zwei Jahren niemandem etwas. */
.vorgut { display: flex; flex-direction: column; min-width: 0; }
.vorgut__nummer { font-weight: 600; }
.vorgut__mehr { font-size: 11.5px; font-weight: 400; color: var(--text-3); margin-top: 2px; }
.vorgut__leer { font-weight: 400; color: var(--text-3); }
.vorgut__knoepfe { display: inline-flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; }

/* ── Gutachtenansicht ────────────────────────────────────────────────────────
   Der Platz für das PDF steht schon; erzeugt wird es noch nicht. Die Flaeche
   sagt deshalb, was fehlt — ein leerer Rahmen sieht nach einem Fehler aus. */
.gpdf__kopf { display: flex; flex-direction: column; gap: 2px; margin-bottom: 10px; }
.gpdf__blatt { border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-2); min-height: 320px; display: grid; place-items: center; }
.gpdf__leer { text-align: center; padding: 30px 20px; }
.gpdf__ico { width: 34px; height: 34px; color: var(--text-3); }

/* ── Der Satz als Regler in seiner Spanne ────────────────────────────────────
   Wo die Richtlinie eine Spanne nennt (Erbbaurecht 20 bis 50 %), ist der Satz
   eine Ermessensentscheidung INNERHALB von Grenzen. Ein Regler zeigt beides
   zugleich: den gewaehlten Wert und den Rahmen, in dem er sich bewegen darf —
   ein Zahlenfeld zeigt nur die Zahl und laesst offen, ob 60 % noch zulaessig
   waeren. */
.satzregler { display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: 6px; }
.satzregler .range { width: 100%; margin: 0; }
.satzregler__grenze { font-size: 10.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.satzregler__wert { grid-column: 1 / -1; text-align: center; font-size: 12px;
  font-weight: 600; color: var(--text-2); font-variant-numeric: tabular-nums; }

/* Steuer und Bruttobetrag stehen leiser als die Summe: Sie sind Auskunft und
   nicht Teil der Ermittlung. */
.honorarposten__ust td { padding-top: 4px; padding-bottom: 4px;
  border-bottom: 0; color: var(--text-2); font-size: 12.5px; }
.honorarposten__ust:last-child td { padding-bottom: 12px; color: var(--text); }

/* Objektart und Baujahr nebeneinander: vier Fuenftel zu einem Fuenftel. Die
   Art traegt eine gegliederte Liste mit 52 Eintraegen, das Baujahr vier
   Ziffern — gleich breit stuenden beide falsch. Sie gehoeren in eine Zeile,
   weil erst beide zusammen die Alterswertminderung ergeben: die
   Gesamtnutzungsdauer aus dem Typ, das Alter aus dem Jahr. */
.gst__artzeile { grid-template-columns: minmax(0, 4fr) minmax(120px, 1fr); gap: 12px;
  align-items: start; }
.gst__alter { margin-top: 4px; line-height: 1.45; }
@media (max-width: 620px) {
  .gst__artzeile { grid-template-columns: minmax(0, 1fr); }
}

/* Eine Zeile, deren Grundlage der Auftrag nicht mehr traegt: Sie steht noch da,
   rechnet noch mit — und faellt auf. Nicht ausgrauen: Wer sie uebersieht,
   verschickt ein Angebot mit einem Zuschlag, den es nicht mehr gibt. */
:root[data-theme="dark"] 
/* ── Der Erbbaurechtsvertrag ─────────────────────────────────────────────────
   Ein eigener Rahmen wie bei den Besonderheiten: Was darin steht, gehoert
   zusammen und erscheint nur, wenn eine der beiden Erbbau-Seiten bewertet
   wird. */
.gst__erbbau { border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px 14px 14px; margin: 0 0 4px; }
.gst__erbbau > legend { padding: 0 6px; margin-left: -6px;
  font-size: 12.5px; font-weight: 600; color: var(--text-2); }
.gst__erbbau-wozu { margin: 0 0 10px; font-size: 12px; line-height: 1.5; color: var(--text-3); }
.gst__erbbau-raster { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; }

/* ── Was die Rechtsposition nach sich zieht ──────────────────────────────────
   Ein Rahmen je Position, ueber die volle Breite und nicht in einer Spalte:
   Was darin steht, gehoert zum Gegenstand und nicht zu den Stammdaten daneben.
   Sichtbar ist immer nur einer. Volleigentum braucht keinen — dort ist der
   Gegenstand das Grundstueck, und mehr ist dazu nicht zu sagen. */
.gst__rahmen { border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px 14px 14px; margin: 0 0 14px; }
.gst__rahmen[hidden] { display: none; }
.gst__rahmen > legend { padding: 0 6px; margin-left: -6px;
  font-size: 12.5px; font-weight: 600; color: var(--text-2); }
.gst__rahmen-wozu { margin: 0 0 10px; font-size: 12px; line-height: 1.5; color: var(--text-3); }
.gst__rahmen-raster { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; }

/* Feld und abgeleitete Groesse nebeneinander: der Erbbauzins mit seiner
   Vergleichsgroesse je m² und Monat, das Endjahr mit der Restlaufzeit. Die
   zweite Zahl ist keine Eingabe — sie steht daneben und nicht darunter, weil
   sie dasselbe sagt wie das Feld, nur in der Groesse, in der man es prueft. */
.gst__zinszeile { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
/* Der Kasten so breit wie sein Inhalt. `.feld-maske` steht sonst auf
   `width: 100%` — dann fuellt ein Rahmen die ganze Spalte, in dem eine
   zweistellige Prozentzahl und ein Zeichen stehen. */
.gst__zinszeile .feld-maske { width: auto; flex: 0 0 auto; }
.gst__zinszeile .input.num { flex: 0 0 auto; }
/* Zwei Rasterspalten fuer ein Feld, dessen abgeleitete Groesse danebensteht.
   In der Grundbreite (180px) waere sie umgebrochen und haette unter dem Feld
   gestanden — dort liest man sie nicht als dieselbe Zahl in anderer Einheit. */
.gst__rahmen-breit { grid-column: span 2; }
@media (max-width: 640px) {
  .gst__rahmen-breit { grid-column: auto; }
}
.gst__zinsum { font-size: 12px; color: var(--text-3); white-space: nowrap; }

/* Ein Bruch, wie er im Grundbuch steht: zwei Zahlen und ein Strich. */
.gst__bruch { display: flex; align-items: center; gap: 6px; }
.gst__bruch .input { width: 8ch; }
.gst__bruch-strich { color: var(--text-3); font-size: 15px; }

/* Die Fundstelle unter einem Zuschlag: leise, aber anklickbar. Sie sieht
   bewusst nicht wie ein Knopf aus — sie fuehrt nur zu einer Auskunft und
   nicht zu einer Handlung. */
.honorarposten__quelle {
  display: inline-flex; align-items: center; gap: 5px; margin-top: 3px;
  padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; font-size: 12px; color: var(--text-3);
  text-decoration: underline; text-decoration-style: dotted;
  text-underline-offset: 2px;
}
.honorarposten__quelle:hover { color: var(--brand-700); }
.honorarposten__quelle svg { width: 13px; height: 13px; flex: 0 0 13px; }

/* Der Kasten dahinter. */
.hquelle__kat { font-size: 12px; color: var(--text-3); text-transform: uppercase;
  letter-spacing: .04em; }
.hquelle__name { font-size: 16px; font-weight: 600; margin-top: 2px; }
.hquelle__spanne { font-size: 15px; color: var(--brand-700); font-weight: 600;
  margin-top: 6px; }
.hquelle__bem { font-size: 13px; line-height: 1.55; margin: 10px 0 0; }

/* Wovon und was daraus wurde — zwei Zeilen, Begriff links, Zahl rechts. */
.hquelle__rechnung { margin: 12px 0 0; padding: 10px 12px; border-radius: 8px;
  background: var(--surface-2, rgba(0,0,0,.03)); }
.hquelle__zeile { display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; }
.hquelle__zeile + .hquelle__zeile { margin-top: 6px; padding-top: 6px;
  border-top: 1px solid var(--border); }
.hquelle__zeile dt { font-size: 12px; color: var(--text-3); flex: 0 0 auto; }
.hquelle__zeile dd { margin: 0; font-size: 13px; text-align: right; }
.hquelle__zeile dd b { margin-left: 6px; white-space: nowrap; }

/* Die Bemessungsgrundlage unter dem Satz: klein, damit sie den Regler nicht
   verdraengt — aber da, weil „+ 25 %" ohne sie eine halbe Angabe ist. */
.satzregler__von { margin-top: 3px; font-size: 11.5px; color: var(--text-3);
  white-space: nowrap; }
.hquelle__tafel { margin: 12px 0 0; }

/* ── Die Postentabelle: Ordnen, Vorbehalt, Summen ──────────────────────────
   Gezogen wird nur innerhalb der Zu- und Abschlaege; die Zeile zeigt das mit
   dem Zeiger an, nicht mit einem Griff — ein zusaetzliches Symbol in einer
   Tabelle mit sechs Spalten waere die siebte Sache, die um Aufmerksamkeit
   bittet. */
/* Alle Betraege an EINER Kante. `.num` setzt nur `tabular-nums` — gleiche
   Ziffernbreite, aber keine Ausrichtung; damit standen 6.164,70 EUR und
   147,20 EUR linksbuendig untereinander und trafen sich nirgends. Rechts
   ausgerichtet stehen Tausender ueber Tausendern, und die Spalte laesst sich
   von oben nach unten nachrechnen. */
.honorarposten th.num, .honorarposten td.num { text-align: right; }

/* Eine Tabelle, die ganz zu sehen ist. `.tablewrap` deckelt auf 560 Pixel und
   scrollt — richtig fuer eine lange Liste in einer Karte, falsch fuer eine
   Rechnung: Deren Summe steht unten, und sie gehoert ins Bild. */
.tablewrap--frei { overflow: visible; max-height: none; }
.tablewrap--frei .table thead th { position: static; }

/* Die Ermittlung als eigener Kasten: Sie ist eine Rechnung mit Kopf, Posten
   und Summe — ein Rahmen darum sagt, wo sie anfaengt und wo sie aufhoert.
   Die unterste Zeile traegt schon den doppelten Strich; ihre Trennlinie
   darunter waere eine Linie zu viel. */
.honorarkasten {
  border: 1px solid var(--border); border-radius: var(--radius-sm, 8px);
  overflow: hidden;
}
.honorarkasten .table { margin: 0; }
.honorarkasten .table thead th { background: var(--surface-2, rgba(0,0,0,.02)); }
.honorarkasten .table tfoot tr:last-child > td { border-bottom: 0; }

/* KEIN `table-layout: fixed` hier: Es verteilt die Breiten strikt nach den
   Vorgaben und stauchte damit die Kopfzeile — die Spalten sollen sich wie
   zuvor nach ihrem Inhalt richten. */

.honorarposten tr[data-ziehbar] { cursor: grab; }
.honorarposten tr[data-ziehbar]:active { cursor: grabbing; }
.honorarposten__zieht { opacity: .45; }
.honorarposten__ziel > td { box-shadow: inset 0 2px 0 var(--brand-500); }

/* Ein Posten unter Vorbehalt: Er steht da, rechnet aber nicht mit. Gesagt
   wird das mit einem WORT ueber dem Namen und nicht mit Kursivsatz — der las
   sich wie eine Betonung, und in einer Zeile aus Zahlen und Eingabefeldern
   ging er ohnehin unter. Durchgestrichen waere falsch: Das hiesse „gilt
   nicht", hier heisst es „noch nicht entschieden". */
.honorarposten__optwort { display: none; }
.honorarposten__opt .honorarposten__optwort {
  display: block; margin-bottom: 1px;
  font-size: 11px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--brand-700, #1d4ed8);
}

/* Die Fahrt in ihren Teilen: was gefahren wird, darunter wie oft. */
.honorarposten__strecke {
  margin-top: 2px; font-size: 12px; color: var(--text-3);
}
.honorarposten__strecke b { color: var(--text-2); margin-left: 4px; }
.honorarposten__termine { margin-top: 4px; max-width: 230px; }
.honorarposten__termine .satzregler__wert { min-width: 88px; }
.honorarposten__opt [data-betrag] { color: var(--text-3); }

/* Das Feld fuer die Bemerkung: unauffaellig, bis man hineinschreibt. */
.honorarposten__bem {
  width: 100%; height: 30px; padding: 0 8px; font-size: 12.5px;
  background: transparent; border-color: transparent;
}
.honorarposten__bem:hover { border-color: var(--border); }
.honorarposten__bem:focus { background: var(--surface); border-color: var(--brand-500); }

/* Die Zwischenstufen im Fuss: Honorar, Rabatt, Nebenkosten. Sie tragen keine
   Linie — die gehoert der Summe. */
.honorarposten__zwischen > td, .honorarposten__rabatt > td {
  border-top: 1px solid var(--border); padding-top: 8px; padding-bottom: 8px;
}
.honorarposten__rabatt .satzregler { max-width: 260px; }
/* Ein Rabatt, der greift, ist ein Abzug — und Abzuege stehen in Rot. Bei 0 %
   bleibt die Zeile still: Sie ist dann eine Moeglichkeit und kein Vorgang. */
.honorarposten__rabatt--aktiv td[data-rabattbetrag],
.honorarposten__rabatt--aktiv .satzregler__wert { color: var(--danger, #b91c1c); font-weight: 600; }

/* Ein Regler, der eine ganze Zeile bekommt — fuer die Zahl der Ortstermine. */
.satzregler--breit { width: 100%; }
.satzregler--breit .range { flex: 1 1 auto; }

/* Die letzte Zahl der Aufstellung: doppelt unterstrichen, wie es sich fuer
   eine Endsumme gehoert. */
.honorarposten__endsumme > td {
  border-bottom: 3px double var(--text-2); padding-bottom: 6px;
}

/* Die Spanne steht nach der Endsumme und gehoert nicht mehr zur Rechnung —
   sie beantwortet die naechste Frage: Womit muss der Auftraggeber rechnen? */
.honorarposten__spanne > td { padding-top: 10px; color: var(--text-2); }
.honorarposten__spanne:first-of-type > td { border-top: 1px solid var(--border); }

/* ── Gibt es den Kontakt schon? ────────────────────────────────────────────
   Ein Hinweis unter dem Namen, kein Popover: Er bleibt stehen, waehrend man
   weitertippt, und verdeckt kein Feld. Bernstein und nicht Rot — es ist eine
   Auskunft und kein Fehler; angelegt werden darf trotzdem. */
.dublett {
  margin: 0 0 14px; padding: 11px 13px;
  background: var(--amber-50, #fffbeb);
  border: 1px solid var(--amber-200, #fde68a);
  border-radius: var(--radius-sm, 8px);
}
.dublett__kopf {
  display: flex; align-items: center; gap: 7px;
  font-size: 13px; font-weight: 600; color: var(--amber-700, #b45309);
}
.dublett__ico { width: 15px; height: 15px; flex: 0 0 15px; }
.dublett__liste { margin-top: 7px; display: flex; flex-direction: column; gap: 1px; }

/* Jede Zeile ein Sprung in den vorhandenen Datensatz — in einem neuen
   Fenster, damit das halb ausgefuellte Formular nicht verloren geht. */
.dublett__zeile {
  display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap;
  padding: 5px 7px; border-radius: 6px;
  color: inherit; text-decoration: none;
}
.dublett__zeile:hover { background: rgba(0, 0, 0, .05); }
.dublett__name { font-size: 13.5px; font-weight: 600; }
.dublett__zusatz { font-size: 12px; color: var(--text-3); }
.dublett__zeile--ruht .dublett__name { font-weight: 400; color: var(--text-3); }
.dublett__fuss { margin-top: 7px; font-size: 12px; color: var(--text-3); }

/* WhatsApp hinter der Mobilnummer: ein Haken und ein Sprung in den Chat.
   Klein und unter dem Feld — es ist eine Randnotiz zur Nummer und nicht die
   Nummer selbst. */
.telfeld__wa {
  display: flex; align-items: center; gap: 12px; margin-top: 5px;
  font-size: 12.5px;
}
.telfeld__wa .checkbox { font-size: 12.5px; }
.telfeld__walink {
  color: #128c7e; text-decoration: underline; text-decoration-style: dotted;
  text-underline-offset: 2px; white-space: nowrap;
}
.telfeld__walink:hover { color: #075e54; }

/* Der Schalter für die Kantenmaße — unter der Werkzeugleiste in der Karte.
   Er sieht aus wie die Leiste darüber (leaflet-bar), damit er dazugehört und
   nicht wie ein Fremdkörper auf dem Kartenbild sitzt. */
.karte__massschalter {
  background: var(--surface, #fff);
  border-radius: 4px; overflow: hidden;
}
.karte__massfeld {
  display: flex; align-items: center; gap: 6px;
  padding: 5px 8px; margin: 0; cursor: pointer;
  font-size: 12px; color: var(--text-2); white-space: nowrap;
}
.karte__massfeld input { width: 14px; height: 14px; margin: 0; accent-color: var(--brand-500); }
.karte__massfeld:hover { background: rgba(0, 0, 0, .04); }
/* Zwei Kaestchen untereinander: eine feine Linie dazwischen, damit sie als
   zwei Entscheidungen lesbar sind und nicht als ein Block. */
.karte__massfeld + .karte__massfeld { border-top: 1px solid var(--border); }

/* ── Der Gegenstand in der Auftragsliste ───────────────────────────────────
   Drei Zeilen in einer Zelle: Objektart, Anschrift, Stichtage. Jede mit
   ihrem Zeichen — beim Ueberfliegen einer Liste sucht das Auge die Form und
   nicht das Wort. Die erste Zeile traegt das Gewicht, die anderen stehen
   leiser darunter. */
.gegen { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.gegen__zeile {
  display: flex; align-items: center; gap: 5px; min-width: 0;
  font-size: 12.5px; color: var(--text);
}
.gegen__zeile--leise { font-size: 12px; color: var(--text-3); }
.gegen__ico { width: 13px; height: 13px; flex: 0 0 13px; opacity: .65; }

/* „+2" hinter der Objektart: Der Auftrag umfasst mehr als ein Grundstueck.
   Die uebrigen aufzuzaehlen sprengte die Zelle — die Zahl sagt, dass man
   hineinsehen muss. */
.gegen__mehr {
  flex: 0 0 auto; padding: 0 5px; border-radius: 8px;
  background: var(--surface-2, rgba(0,0,0,.06)); color: var(--text-3);
  font-size: 11px; font-weight: 600;
}

/* Die Eingabereihe der Wohnungsschätzung: vier schmale Felder nebeneinander,
   die Ergebnisse stehen in der Aufstellung darunter. Bricht auf schmalen
   Fenstern um, statt die Felder zu quetschen. */
.schaetz__reihe {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  margin-bottom: 10px;
}
.schaetz__reihe--zwei { grid-template-columns: 190px minmax(0, 1fr); }
@media (max-width: 620px) {
  .schaetz__reihe--zwei { grid-template-columns: minmax(0, 1fr); }
}

/* ── Einheiten in der Schätzung an einer Kante ─────────────────────────────
   Die Felder trugen feste Zeichenbreiten (7ch, 8ch, 6ch …). Dadurch stand
   jede Einheit dort, wo ihre Zahl aufhoerte — und keine unter der anderen.
   Jetzt fuellt die Zahl den Kasten, die Einheit sitzt an seinem rechten Rand,
   und weil das Raster gleich breite Spalten macht, fluchten sie.

   Nur in der Schätzung: Am Erbbauvertrag sind die Kaesten absichtlich schmal
   (`.gst__zinszeile`), dort steht eine Erlaeuterung daneben. */
.schaetz .feld-maske { width: 100%; }
.schaetz .feld-maske__zahl {
  flex: 1 1 auto; width: auto; min-width: 0;
}
/* Der Platzhalter folgt der Zahl — beide rechtsbuendig, sonst springt der
   Text beim ersten Anschlag von links nach rechts. */
.schaetz .feld-maske__zahl::placeholder { text-align: right; }

/* Der Zeiger im Fang-Modus: ein Fadenkreuz. Beim Zeichnen setzt ein Klick
   einen Punkt, hier trifft er eine Fläche — und das soll man ihm ansehen. */
.karte.ist-fangen, .karte.ist-fangen .leaflet-container { cursor: crosshair; }

/* ── Adressvorschläge unter dem Straßenfeld ────────────────────────────────
   Eine Liste, die am Feld hängt und mit ihm wandert. Über allem anderen, aber
   unter den Kästen: Wer in einem Kasten tippt, soll die Vorschläge sehen —
   ein Kasten, der darüber liegt, ist die Ausnahme und gewinnt. */
.adrvor {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 900;
  margin-top: 3px; padding: 3px;
  background: var(--surface, #fff);
  border: 1px solid var(--border); border-radius: var(--radius-sm, 8px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .14);
  max-height: 260px; overflow-y: auto;
}
.adrvor__zeile {
  display: flex; flex-direction: column; gap: 1px; width: 100%;
  padding: 6px 9px; border: 0; border-radius: 6px; background: none;
  font: inherit; text-align: left; cursor: pointer;
}
.adrvor__zeile:hover, .adrvor__zeile.is-an { background: var(--brand-50, rgba(70,185,114,.12)); }
.adrvor__strasse { font-size: 13.5px; font-weight: 600; color: var(--text); }
.adrvor__ort { font-size: 12px; color: var(--text-3); }




/* ── Scoring: Node-Tree ─────────────────────────────────────────────────────
   Echte Baumoptik (Fuehrungslinien je Ebene, Typ-Icon) fuer Themenbaum und
   Scorecard-Knoten. Bewusst ohne Drag&Drop: Sortierung ausschliesslich ueber
   Hoch/Runter-Buttons -- die Fuehrungslinien sind reines CSS, kein Framework. */
.node-tree {
  display: flex; flex-direction: column;
}
.node-row {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 4px; border-bottom: 1px solid var(--border);
  transition: background .12s ease;
}
.node-row:hover { background: var(--brand-50, rgba(70,185,114,.08)); }
.node-row:last-child { border-bottom: 0; }
.node-row[data-open-modal] { cursor: pointer; }
.node-row[draggable="true"] { cursor: grab; }
.node-row.is-dragging { opacity: .35; }
.node-row__handle { flex: 0 0 auto; color: var(--text-3); cursor: grab; letter-spacing: -2px; user-select: none; }
.node-row__handle:active { cursor: grabbing; }
.node-row--head {
  font-size: 11.5px; font-weight: 700; color: var(--text-3);
  text-transform: uppercase; letter-spacing: .04em;
  background: var(--bg); cursor: default;
}
.node-row--head:hover { background: var(--bg); }
.node-row__indent {
  display: inline-block; align-self: stretch;
  width: calc(var(--depth, 0) * 22px);
  flex: 0 0 auto;
  background-image: repeating-linear-gradient(
    to right,
    var(--border) 0, var(--border) 1.5px,
    transparent 1.5px, transparent 22px
  );
  background-position: 10px 0;
}
.node-row__type {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 6px;
  font-size: 11px; font-weight: 700; color: #fff;
  background: var(--text-3);
}
.node-row__type--module   { background: var(--navy-mid, #0c3a6e); }
.node-row__type--group    { background: var(--teal, #00a1a3); }
.node-row__type--criterion,
.node-row__type--topic    { background: var(--brand-600, #2f7f5c); }
.node-row__name { flex: 1 1 auto; min-width: 0; font-weight: 500; }
.node-row__meta { flex: 0 0 auto; font-size: 12.5px; }
.node-row__acts { flex: 0 0 auto; display: flex; align-items: center; gap: 4px; }
.node-row__inline { display: inline-flex; margin: 0; }

/* ── Wert-Regler (Skalenstufen, Gewichte) ───────────────────────────────────
   Range-Input + Zahlenfeld gegenseitig synchronisiert per data-Attribut,
   siehe scoring.js. Kein Slider-Plugin, nativer <input type="range">. */
.value-slider { display: flex; align-items: center; gap: 8px; min-width: 160px; }
.value-slider input[type="range"] {
  flex: 1 1 auto; accent-color: var(--brand-500);
  height: 4px; cursor: pointer;
}
.value-slider input[type="number"] {
  flex: 0 0 64px; width: 64px; text-align: right;
  padding: 4px 6px; font-size: 13px;
}

/* ── Filterzeile (Scorecard-Liste) ──────────────────────────────────────── */
.filter-row { display: flex; gap: 8px; flex-wrap: wrap; }
.filter-row .input { width: auto; min-width: 160px; }

/* ── Scorecard-Builder: zweispaltig, Baum links / Formular rechts ─────────── */
.builder { display: grid; grid-template-columns: minmax(280px, 380px) 1fr; gap: 16px; align-items: start; }
@media (max-width: 900px) { .builder { grid-template-columns: 1fr; } }
.builder__tree, .builder__detail { min-width: 0; }
.tree-toolbar { display: flex; gap: 6px; padding: 8px; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.node-row.is-selected { background: var(--brand-50, rgba(70,185,114,.14)); }
.node-row__add {
  flex: 0 0 auto; width: 20px; height: 20px; border-radius: 5px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px dashed var(--border); color: var(--text-3); font-size: 13px; line-height: 1;
  background: none; cursor: pointer;
}
.node-row__add:hover { border-color: var(--brand-500); color: var(--brand-600); }
.weight-badge {
  flex: 0 0 auto; font-size: 11px; font-weight: 600; padding: 1px 7px; border-radius: 999px;
  background: var(--bg); color: var(--text-3);
}
.weight-badge--warn { background: #fdecea; color: #b3261e; }
.weight-badge--ok { background: var(--brand-50, #eaf6ef); color: var(--brand-700, #24634a); }

/* ── Scoring-Ansicht ─────────────────────────────────────────────────────── */
.scoring { display: grid; grid-template-columns: 1fr 300px; gap: 16px; align-items: start; }
@media (max-width: 900px) { .scoring { grid-template-columns: 1fr; } }
.scoring__main { min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.scoring__side { position: sticky; top: 16px; }

.scoring-head { display: flex; align-items: center; gap: 10px; padding: 10px 12px;
  border-radius: var(--radius-sm, 8px); margin-top: 6px; }
.scoring-head--module { background: var(--navy); color: #fff; }
.scoring-head--module .node-row__type { background: rgba(255,255,255,.2); }
.scoring-head--group { background: var(--bg); margin-left: 12px; }
.scoring-head__name { flex: 1 1 auto; font-weight: 600; }
.scoring-head__score { flex: 0 0 auto; font-variant-numeric: tabular-nums; font-weight: 700; }

.crit-card { border: 1px solid var(--border); border-radius: var(--radius-sm, 8px);
  padding: 12px 14px; margin-left: 24px; background: var(--surface);
  border-left: 3px solid var(--border); }
.crit-card.is-scored { border-left-color: var(--brand-500); }
.crit-card.is-na { border-left-color: var(--text-3); opacity: .8; }
.crit-card__q { font-weight: 600; margin-bottom: 8px; }
.crit-card__help { margin: 4px 0 8px; font-size: 13px; }
.crit-card__help summary { cursor: pointer; color: var(--brand-600); }
.crit-card__help > div { padding: 6px 0; color: var(--text-2); }
.crit-card__refs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 8px; }
.crit-card__refs img { height: 56px; width: auto; border-radius: 6px; border: 1px solid var(--border); }

.scale-bar { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 8px; }
.scale-btn { border: 1.5px solid var(--lvl, #8a94a6); color: var(--text);
  background: var(--surface); border-radius: 7px; padding: 6px 12px; cursor: pointer;
  font-weight: 600; font-size: 13.5px; min-width: 40px; transition: all .1s ease; }
.scale-btn:hover:not(:disabled) { background: color-mix(in srgb, var(--lvl) 15%, transparent); }
.scale-btn.is-active { background: var(--lvl, #8a94a6); color: #fff; border-color: var(--lvl, #8a94a6); }
.scale-btn:disabled { cursor: default; opacity: .55; }
.scale-btn--na { --lvl: #8a94a6; margin-left: auto; }

.crit-card__comment { width: 100%; resize: vertical; min-height: 34px; margin-bottom: 8px; }
.crit-card__evidence { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.evidence-chip { display: inline-flex; align-items: center; gap: 4px; font-size: 12.5px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 999px; padding: 2px 10px; }
.evidence-chip__del { border: 0; background: none; cursor: pointer; color: #b3261e; font-size: 15px; line-height: 1; }
.evidence-up { display: inline; }

/* ── Zusammenfassung / Sidebar ───────────────────────────────────────────── */
.scoring-sum { border: 1px solid var(--border); border-radius: var(--radius, 12px);
  background: var(--surface); padding: 16px; }
.scoring-sum__label { font-size: 11.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-3); margin-bottom: 6px; }
.progress { height: 8px; background: var(--bg); border-radius: 999px; overflow: hidden; }
.progress__bar { height: 100%; background: var(--brand-500); border-radius: 999px; transition: width .2s ease; }
.scoring-sum__prog { font-size: 13px; color: var(--text-2); margin-top: 6px; }
.scoring-sum__total { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); }
.scoring-sum__score { font-size: 26px; font-weight: 700; font-family: var(--font-head); }
.scoring-sum__ko { margin-top: 8px; }
.scoring-sum__modules { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); }
.scoring-sum__mod { display: flex; justify-content: space-between; gap: 10px; font-size: 13.5px; padding: 3px 0; }
.scoring-sum__mod span:last-child { font-variant-numeric: tabular-nums; font-weight: 600; }

/* ── Ergebnisansicht ─────────────────────────────────────────────────────── */
.result-head__grid { display: flex; gap: 32px; flex-wrap: wrap; align-items: center; }
.result-head__total { font-size: 34px; font-weight: 700; font-family: var(--font-head); }
.result-head__meta { font-size: 13.5px; line-height: 1.7; }
.result-tree { display: flex; flex-direction: column; }
.result-row { border-bottom: 1px solid var(--border); padding: 8px 4px; padding-left: calc(var(--depth, 0) * 22px + 4px); }
.result-row:last-child { border-bottom: 0; }
.result-row__head { display: flex; align-items: center; gap: 10px; }
.result-row__name { flex: 1 1 auto; min-width: 0; }
.result-row--group .result-row__name { font-weight: 600; }
.result-row__score { flex: 0 0 auto; }
.result-row__detail { margin-top: 6px; padding-left: 32px; font-size: 13px; color: var(--text-2);
  display: flex; flex-direction: column; gap: 4px; }
.result-row__comment { white-space: pre-line; }
.lvl-chip { display: inline-block; color: #fff; font-weight: 700; font-size: 12.5px;
  padding: 2px 10px; border-radius: 999px; font-variant-numeric: tabular-nums; }

@media print {
  .sidebar, .topbar, .page-head__actions { display: none !important; }
  .main, .content, .app { display: block !important; margin: 0 !important; }
  .card { break-inside: avoid; box-shadow: none; }
  .result-row { break-inside: avoid; }
}

/* ── KI-Vorschlag (Ausbaustufe, Human-in-the-loop) ───────────────────────── */
.ai-suggest { border: 1px solid #f0d58c; background: #fffaf0; border-radius: 8px;
  padding: 8px 10px; margin-bottom: 8px; }
.ai-suggest__head { font-size: 13px; display: flex; align-items: center; gap: 6px; }
.ai-suggest__why { font-size: 12.5px; color: var(--text-2); margin: 4px 0 6px; }
.ai-suggest__acts { display: flex; gap: 6px; }
.ai-suggest__acts form { display: inline; }

/* ── Corporate-Design-Editor / Branding ──────────────────────────────────── */
.color-field { display: flex; align-items: center; gap: 8px; }
.color-field input[type="color"] { width: 42px; height: 38px; padding: 2px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: var(--surface); cursor: pointer; flex: 0 0 auto; }
.color-field .input { flex: 1 1 auto; }
.logo-preview { display: flex; align-items: center; gap: 14px; margin-bottom: 8px; }
.logo-preview img { max-height: 48px; max-width: 180px; background: var(--sidebar-bg);
  padding: 6px 10px; border-radius: var(--radius-sm); }
.sidebar__logo { max-height: 30px; max-width: 190px; width: auto; display: block; }

/* ── Klapp-Baum: Chevron + Steuerleiste ──────────────────────────────────── */
.tree-controls { display: flex; gap: 6px; padding: 8px 12px 0; }
.node-row__toggle {
  flex: 0 0 auto; width: 20px; height: 20px; padding: 0; margin: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; background: none; cursor: pointer; color: var(--text-3);
  font-size: 11px; line-height: 1; border-radius: 5px; user-select: none;
}
.node-row__toggle:hover { background: var(--bg); color: var(--text-2); }
.node-row__toggle--leaf { cursor: default; pointer-events: none; }
.node-row.is-collapsed > .node-row__name { font-weight: 600; }

/* ── Knotentyp als Icon statt Buchstaben-Chip ────────────────────────────── */
.node-row__type { background: none !important; color: var(--text-3); width: 24px; height: 24px; border-radius: 0; }
.node-row__type svg { width: 19px; height: 19px; display: block; }
.node-row__type--module { color: var(--navy-mid); }
.node-row__type--group { color: var(--teal); }
.node-row__type--criterion,
.node-row__type--topic { color: var(--brand-600); }
/* Modul-Kopf in der Scoring-Ansicht hat dunklen Grund -> Icon hell. */
.scoring-head--module .node-row__type { color: #fff; }
.scoring-head--group .node-row__type { color: var(--teal); }

/* ── Builder: Gewicht-Spalte (inline) + Gesamtgewichtung ──────────────────── */
.tree-legend { margin-left: auto; display: flex; gap: 10px; align-items: center;
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--text-3); }
.tree-legend__w { width: 172px; text-align: center; }
.tree-legend__e { width: 84px; text-align: right; }
.tree-legend .text-3 { text-transform: none; letter-spacing: 0; font-weight: 500; }
@media (max-width: 720px) { .tree-legend { display: none; } }

.node-row__weight { flex: 0 0 auto; width: 172px; }
.node-row__weight.value-slider { min-width: 172px; }
.node-row__weight .input[type="number"] { flex: 0 0 58px; width: 58px; }
.node-row__eff { flex: 0 0 auto; width: 84px; text-align: right; font-variant-numeric: tabular-nums;
  font-weight: 600; font-size: 12.5px; color: var(--brand-700); }
.node-row.is-collapsed > .node-row__eff { color: var(--text); }

/* ── Builder: 70/30-Split mit Spiderweb-Diagramm ─────────────────────────── */
.builder-split { display: grid; grid-template-columns: minmax(0, 7fr) minmax(230px, 3fr); gap: 16px; align-items: start; }
@media (max-width: 900px) { .builder-split { grid-template-columns: 1fr; } }
.builder-side { position: sticky; top: 16px; }
.builder-radar { width: 100%; }
.radar-svg { width: 100%; height: auto; display: block; overflow: visible; }
.radar-grid { fill: none; stroke: var(--border); }
.radar-axis { stroke: var(--border); }
.radar-area { fill: color-mix(in srgb, var(--brand-500) 22%, transparent); stroke: var(--brand-600); stroke-width: 2; stroke-linejoin: round; }
.radar-dot { fill: var(--brand-600); }
.radar-label { font-size: 9px; fill: var(--text-2); font-weight: 600; }
.radar-val { font-size: 9px; fill: var(--brand-700); font-weight: 700; }

/* Verschieben nur am Griff links: Zeile selbst zeigt keinen Greif-Cursor. */
.node-row[draggable="true"] { cursor: default; }
.node-row__handle { cursor: grab; }
.node-row__handle:active { cursor: grabbing; }

/* ── Builder: Spalten-Kopfzeile (statt schwebender Legende) ───────────────── */
.node-row--head { text-transform: uppercase; letter-spacing: .03em; }
.node-row--head .node-row__name { font-weight: 700; color: var(--text-3); font-size: 11.5px; }
.node-row--head .node-row__weight { text-align: center; font-weight: 700; color: var(--text-3); font-size: 11.5px; }
.node-row--head .node-row__eff { font-weight: 700; color: var(--text-3); font-size: 11.5px; }

/* Gewicht/Anteil-Spalten etwas schmaler und mit Luft zum Card-Rand, damit die
   Werte nicht am aeussersten Rand kleben. */
.node-row { padding-right: 8px; }
.node-row__weight { width: 150px; }
.node-row__weight.value-slider { min-width: 150px; }
.node-row__weight .input[type="number"] { flex: 0 0 52px; width: 52px; }
.node-row__eff { width: 74px; }

/* Ampel-Option unter dem Netzdiagramm */
.radar-opt { margin-top: 10px; font-size: 12.5px; }


/* ── Anteil-Spalte: Zahl + Stärke-Balken, mit klarem Abstand zum Gewicht ──── */
.node-row__eff {
  width: 116px;
  margin-left: 22px;               /* Abstand: Gewicht-Input klebt nicht mehr an der Anteil-Zahl */
  display: flex; align-items: center; justify-content: flex-end; gap: 7px;
}
.eff-val { font-variant-numeric: tabular-nums; font-weight: 600; font-size: 12.5px; color: var(--brand-700); }
.eff-bar { flex: 0 0 auto; width: 42px; height: 6px; background: var(--bg);
  border: 1px solid var(--border); border-radius: 999px; overflow: hidden; }
.eff-bar__fill { display: block; height: 100%; background: var(--brand-500); border-radius: 999px; transition: width .15s ease; }
/* Kopfzeile: „Anteil" rechtsbündig über der Spalte, kein Balken. */
.node-row--head .node-row__eff { color: var(--text-3); }

/* ── Builder-Feinschliff v2: Gewicht-Feld breiter, Reset-Knopf + Gleichgewichts-
   Marke auf dem Slider, mehr Abstand zur Anteil-Spalte, Hierarchie-Index. ──── */
.node-row__weight, .node-row__weight.value-slider { width: 200px; min-width: 200px; }
.node-row__weight input[type="range"] { min-width: 0; flex: 1 1 auto; }
.node-row__weight .input[type="number"], .node-row__weight input[type="number"] { flex: 0 0 68px; width: 68px; }
.node-row__eff { margin-left: 30px; }

/* Hierarchie-Index vor dem Namen (1, 1.1, 1.1.1 …). */
.node-row__idx { flex: 0 0 auto; margin-right: 8px; min-width: 30px; text-align: right;
  color: var(--text-3); font-variant-numeric: tabular-nums; font-size: 11.5px; font-weight: 600; }

/* Slider mit Gleichgewichts-Marke (100 / Geschwisterzahl) + Reset-Knopf links. */
.node-row__weight .slider-wrap { position: relative; flex: 1 1 auto; display: flex; min-width: 0; align-items: center; }
.node-row__weight .slider-wrap input[type="range"] { flex: 1 1 auto; min-width: 0; }
.slider-tick { position: absolute; top: 50%; left: var(--equal, 50%); width: 2px; height: 15px;
  transform: translate(-1px, -50%); background: var(--text-3); border-radius: 1px; pointer-events: none; opacity: .6; }
.weight-reset { flex: 0 0 auto; width: 20px; height: 20px; padding: 0; line-height: 18px; text-align: center;
  border: 1px solid var(--border); background: var(--surface, var(--bg)); color: var(--text-2);
  border-radius: 6px; cursor: pointer; font-size: 12px; }
.weight-reset:hover { color: var(--brand-600); border-color: var(--brand-500); }

/* ── Assessment: Modul-Spiderweb in der Seitenleiste (statt Modul-Liste) ──── */
.score-radar { margin-top: 8px; }
.score-radar__canvas { width: 100%; }

/* ── Builder: „Anteil"-Spaltenkopf als Sortier-Schalter ──────────────────── */
.node-row__eff--sort { cursor: pointer; user-select: none; }
.node-row__eff--sort:hover { color: var(--brand-600); }
.sort-caret { display: inline-block; width: 1.1em; text-align: right; font-size: 10px; }

/* ── Phase 6: Gewichtungsprofile (Builder-Seitenleiste) ──────────────────── */
.profile-list { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
.profile-list__item { display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 7px 10px; border: 1px solid var(--border); border-radius: 8px; text-decoration: none;
  color: var(--text); background: var(--surface, var(--bg)); font-size: 13.5px; }
.profile-list__item:hover { border-color: var(--brand-500); color: var(--brand-700); }
.profile-list__name { font-weight: 600; }
.profile-create { display: flex; flex-direction: column; gap: 6px; }

/* ── Einstellungen → E-Mail: Layout-Auswahl ────────────────────────────────── */
.mlp-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
@media (max-width: 900px) { .mlp-grid { grid-template-columns: 1fr; } }
.mlp-card { position: relative; display: flex; flex-direction: column; border: 2px solid var(--border);
  border-radius: var(--radius-sm); overflow: hidden; cursor: pointer; background: var(--surface);
  transition: border-color .12s ease, box-shadow .12s ease; }
.mlp-card:hover { border-color: var(--brand-500); }
.mlp-card > input { position: absolute; opacity: 0; width: 0; height: 0; }
.mlp-card:has(input:checked) { border-color: var(--brand-500); box-shadow: 0 0 0 3px rgba(99,102,241,.18); }
.mlp-thumb { height: 280px; overflow: hidden; background: #fff; border-bottom: 1px solid var(--border); }
.mlp-thumb iframe { width: 200%; height: 560px; border: 0; transform: scale(.5); transform-origin: top left; pointer-events: none; }
.mlp-meta { padding: 12px 14px; }
.mlp-name { display: flex; align-items: center; justify-content: space-between; font-weight: 600; font-size: 14px; color: var(--text); }
.mlp-check { color: var(--brand-500); opacity: 0; font-weight: 700; }
.mlp-card:has(input:checked) .mlp-check { opacity: 1; }
.mlp-desc { display: block; margin-top: 4px; color: var(--text-2); font-size: 12.5px; line-height: 1.4; }

/* ── Einstellungen → E-Mail: Protokoll füllt die Fensterhöhe, Liste scrollt intern ── */
#settings-tabs .ftabs__pane[data-pane="protokoll"] > .card.pane { height: calc(100vh - 250px); min-height: 320px; }

/* ── Phase 6b: Profile im Vergleich ───────────────────────────────────────── */
.cmp-opt { font-size: 12.5px; font-weight: 400; white-space: nowrap; }
.cmp-wrap { overflow-x: auto; }
.cmp-table { width: 100%; }
.cmp-table th.cmp-th-name { text-align: left; }
.cmp-table th.cmp-th-val { text-align: right; white-space: nowrap; }
.cmp-th-sub { display: block; font-weight: 400; font-size: 10.5px; color: var(--text-3); }
.cmp-table.is-hiding-leaves .cmp-row--criterion { display: none; }
.cmp-name { padding-left: calc(8px + var(--depth, 0) * 18px) !important; white-space: nowrap; }
.cmp-name .node-row__idx { min-width: 34px; }
.cmp-name .node-row__type { display: inline-flex; vertical-align: middle; }
.cmp-name__text { font-weight: 500; }
.cmp-row--module .cmp-name__text { font-weight: 700; }
.cmp-row--group .cmp-name__text { font-weight: 600; }
.cmp-cell { text-align: right; white-space: nowrap; }
.cmp-val { font-variant-numeric: tabular-nums; font-weight: 600; }
.cmp-delta { display: inline-block; margin-left: 6px; font-size: 11px; font-variant-numeric: tabular-nums; }
.cmp-delta--up { color: #16a34a; }
.cmp-delta--down { color: #ef4444; }
.cmp-cell .eff-bar { display: block; margin: 4px 0 0 auto; width: 68px; }

/* ── Phase 6b: K.O.-Überschreibung je Profil ──────────────────────────────── */
.ko-table th.ko-col, .ko-table td.ko-col { text-align: center; white-space: nowrap; }
.ko-table td.ko-col .checkbox { justify-content: center; margin: 0; }
.ko-threshold { width: 90px; text-align: right; }
.ko-row--overridden td { background: color-mix(in srgb, var(--brand-500) 7%, transparent); }
.ko-table .node-row__idx { min-width: 34px; }
