/* ============================================================================
   Gemeinsame Bausteine. Alles hier baut ausschliesslich auf `tokens.css` auf.

   Was hier steht, gehoert NICHT mehr in ein `<style>` der einzelnen Seite.
   Vorher hatte jede der 37 Seiten ihre eigene Karte, ihren eigenen Knopf und
   ihre eigene Tabelle – aehnlich, aber nie gleich. Wer eine neue Variante
   braucht, ergaenzt sie hier, damit sie allen zur Verfuegung steht.
   ============================================================================ */

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--fs-base);
  background: var(--bg);
  color: var(--text);
}

/* ── Seitengeruest ─────────────────────────────────────────────────────────
   `.wrap` ist die Inhaltsspalte. `--wrap-max` setzt die Seite, wenn sie
   schmaler sein soll (Formularseiten) – Standard ist volle Breite. */
.wrap { padding: var(--sp-4); margin: 0 auto; max-width: var(--wrap-max, 100%); }

/* Seiten-Toolbar: zweite Zeile unter der Kopfzeile, klebt beim Scrollen mit. */
.toolbar {
  position: sticky; top: var(--appheader-h); z-index: var(--z-toolbar);
  display: flex; align-items: center; gap: var(--sp-2);
  flex-wrap: wrap; padding: var(--sp-2) var(--sp-4);
  background: var(--card); border-bottom: 1px solid var(--border);
}
.toolbar-title { font-weight: 700; font-size: var(--fs-lg); margin-right: auto; }
/* Eingabefelder sind standardmaessig `width:100%`. In einer Toolbar sprengt
   das die Zeile: Suchfeld, jedes Auswahlfeld und jeder Knopf stehen dann
   untereinander statt nebeneinander. Dieselbe Regel gilt seit jeher fuer
   `.filterbar`; die Toolbar hatte sie nicht, weil bis VALDURA-489 keine
   Seite Formularfelder hineingestellt hatte. */
.toolbar .form-input, .toolbar .form-select, .toolbar .form-textarea { width: auto; }

/* ── Karte ─────────────────────────────────────────────────────────────── */
.card {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: var(--sp-4); margin-bottom: var(--sp-3);
}
.card-title { font-weight: 700; font-size: var(--fs-lg); margin: 0 0 var(--sp-2); }
.muted { color: var(--muted); font-size: var(--fs-sm); }

/* ── Knoepfe ───────────────────────────────────────────────────────────────
   Genau eine Basisklasse `.btn` plus Bedeutung. Die Bedeutung steckt in der
   Klasse, nicht in der Farbe: `btn-danger` heisst „macht etwas kaputt", nicht
   „ist rot". */
.btn {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  border: 1px solid var(--border); border-radius: var(--r-md);
  padding: var(--sp-2) var(--sp-3);
  font-family: inherit; font-size: var(--fs-md); line-height: 1.2;
  background: var(--card); color: var(--text);
  cursor: pointer; text-decoration: none; white-space: nowrap;
}
.btn:hover:not(:disabled) { background: var(--surface); }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn:focus-visible { outline: 2px solid var(--accent2); outline-offset: 1px; }
.btn-primary   { background: var(--accent2); border-color: var(--accent2); color: var(--on-accent); }
.btn-primary:hover:not(:disabled)   { filter: brightness(1.08); background: var(--accent2); }
.btn-secondary { background: var(--card); }
.btn-danger    { background: var(--danger); border-color: var(--danger); color: var(--on-accent); }
.btn-danger:hover:not(:disabled)    { filter: brightness(1.08); background: var(--danger); }
.btn-success   { background: var(--success); border-color: var(--success); color: var(--on-accent); }
.btn-ghost     { background: transparent; border-color: transparent; }
.btn-sm { padding: var(--sp-1) var(--sp-2); font-size: var(--fs-sm); }
.btn-xs { padding: 2px var(--sp-1); font-size: var(--fs-xs); }

/* ── Formular ──────────────────────────────────────────────────────────────
   Ein Feld ist: Beschriftung, Eingabe, darunter Platz fuer Hilfe ODER Fehler.
   Der Fehler ersetzt die Hilfe nicht, er tritt daneben – sonst verliert man
   beim Fehler genau die Erklaerung, die man dann braucht. */
.field { margin-bottom: var(--sp-3); }
.field-label {
  display: block; font-size: var(--fs-xs); font-weight: 600;
  color: var(--muted); text-transform: uppercase; letter-spacing: .03em;
  margin-bottom: var(--sp-1);
}
.field-label .req { color: var(--danger); margin-left: 2px; }
.form-input, .form-select, .form-textarea {
  width: 100%; font-family: inherit; font-size: var(--fs-md);
  padding: var(--sp-2); border: 1px solid var(--border);
  border-radius: var(--r-sm); background: var(--card); color: var(--text);
}
.form-textarea { resize: vertical; min-height: 68px; }
.form-input:focus, .form-select:focus, .form-textarea:focus {
  outline: none; border-color: var(--accent2);
  box-shadow: 0 0 0 3px var(--info-bg);
}
.form-input:disabled, .form-select:disabled, .form-textarea:disabled {
  background: var(--surface); color: var(--muted);
}
.field-help { font-size: var(--fs-xs); color: var(--muted); margin-top: 3px; }
.field-error { font-size: var(--fs-xs); color: var(--danger); margin-top: 3px; font-weight: 600; }
.field.has-error .form-input,
.field.has-error .form-select,
.field.has-error .form-textarea { border-color: var(--danger); }
.field-row { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.field-row > .field { flex: 1 1 200px; }

/* ── Tabelle ───────────────────────────────────────────────────────────────
   Zahlen rechts, Text links – ohne Ausnahme. Eine Zahlenspalte, die links
   steht, laesst sich nicht vergleichen, und Vergleichen ist der Zweck. */
.table { border-collapse: collapse; width: 100%; font-size: var(--fs-sm); }
.table th, .table td {
  border-bottom: 1px solid var(--border);
  padding: var(--sp-1) var(--sp-2); text-align: left; vertical-align: top;
}
.table th {
  color: var(--muted); font-weight: 600; font-size: var(--fs-xs);
  text-transform: uppercase; letter-spacing: .03em; white-space: nowrap;
  position: sticky; top: 0; background: var(--card); z-index: 1;
}
.table td.num, .table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.table tbody tr:hover { background: var(--surface); }
.table-group td { background: var(--surface); font-weight: 600; }
/* Breite Tabellen scrollen in ihrem Rahmen, nicht die ganze Seite. */
.table-scroll { overflow-x: auto; }

/* ── Statuschip ────────────────────────────────────────────────────────────
   Ein Status wird IMMER als Chip gezeigt, nie als nackter Text und nie nur
   als Farbe – wer Farben schlecht unterscheidet, liest sonst nichts. */
.chip {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  padding: 1px var(--sp-2); border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 600; white-space: nowrap;
  border: 1px solid var(--border); background: var(--surface); color: var(--text);
}
.chip-success { background: var(--success-bg); border-color: var(--success); color: var(--success); }
.chip-warn    { background: var(--warn-bg);    border-color: var(--warn);    color: var(--warn); }
.chip-danger  { background: var(--danger-bg);  border-color: var(--danger);  color: var(--danger); }
.chip-info    { background: var(--info-bg);    border-color: var(--accent2); color: var(--accent2); }

/* ── Leerzustand, Ladezustand, Fehlzustand ────────────────────────────────
   Alle drei sagen, was als Naechstes zu tun ist. „Keine Daten" allein ist
   eine Sackgasse. */
.state { padding: var(--sp-5); text-align: center; color: var(--muted); }
.state-title { font-weight: 600; color: var(--text); margin-bottom: var(--sp-1); }
.state-action { margin-top: var(--sp-3); }
.state-error .state-title { color: var(--danger); }
.spinner {
  display: inline-block; width: 14px; height: 14px;
  border: 2px solid rgba(0,0,0,.15); border-top-color: var(--accent2);
  border-radius: 50%; animation: spin .8s linear infinite; vertical-align: -2px;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Meldung (Toast) ───────────────────────────────────────────────────────
   Das Aussehen steht in static/toast.css – wie beim Menue und den Tabellen
   fuers Telefon, und aus demselben Grund: Die zwei groessten Seiten laden
   diese Datei hier nicht, brauchen den Baustein aber (VALDURA-505). */

/* ── Dialog ────────────────────────────────────────────────────────────────
   Fuer Rueckfragen bei folgenreichen Aktionen. `Abbrechen` steht links und ist
   vorausgewaehlt – die Escape-Taste schliesst. */
.modal-backdrop {
  position: fixed; inset: 0; background: rgba(16,24,40,.45);
  z-index: var(--z-modal); display: flex; align-items: center;
  justify-content: center; padding: var(--sp-4);
}
.modal {
  background: var(--card); border-radius: var(--r-lg); box-shadow: var(--shadow-lg);
  max-width: 520px; width: 100%; max-height: 85vh; overflow: auto;
  padding: var(--sp-4);
}
.modal-title { font-size: var(--fs-lg); font-weight: 700; margin: 0 0 var(--sp-2); }
/* Die Erklaerung DIESES Dialogs – ein Satz aus `services/hilfe.py`, den
   `widgets.dialog({hilfe: …})` einsetzt (VALDURA-592). Ein Dialog ist die
   dritte Ebene: Man sieht ihn erst, wenn er offen ist, und im ❓-Panel stand
   deshalb nie etwas ueber ihn. */
.modal-hilfe { font-size: var(--fs-sm); color: var(--muted); margin: 0 0 var(--sp-3); }
/* Der Satz, der sagt, was fehlt – IM Dialog (VALDURA-782). Vorher ging die
   Zurückweisung des Servers als Toast hinaus, also hinter das offene Modal:
   Wer „Anlegen“ drückte und nichts geschehen sah, las sie nie. `hidden`
   hält sie weg, solange nichts schiefging. */
.modal-fehler[hidden] { display: none; }
.modal-fehler {
  font-size: var(--fs-sm); color: var(--danger);
  background: var(--danger-bg); border-radius: var(--r-sm);
  padding: var(--sp-2) var(--sp-3); margin: 0 0 var(--sp-3);
}
/* `pre-line`: `frage()` setzt den Rumpf per `textContent` – eine Rueckfrage mit
   Aufzaehlung („\n\n• …") stand deshalb als ein Absatz da, in dem die Punkte
   aneinanderklebten. Mit `pre-line` bleiben die Zeilenumbrueche, ohne dass
   irgendwo HTML in den Rumpf koennte (VALDURA-509). Einzeilige Fragen aendern
   sich dadurch nicht. */
.modal-body { font-size: var(--fs-base); margin-bottom: var(--sp-4); white-space: pre-line; }
.modal-actions { display: flex; gap: var(--sp-2); justify-content: flex-start; }

/* ── Filterleiste ─────────────────────────────────────────────────────────
   Immer direkt ueber der Liste, mit sichtbarem „Zuruecksetzen", sobald ein
   Filter greift – sonst sucht man spaeter, warum die Liste leer ist. */
.filterbar {
  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
  margin-bottom: var(--sp-2);
}
.filterbar .form-input, .filterbar .form-select { width: auto; }
.filter-active { border-color: var(--accent2); color: var(--accent2); font-weight: 600; }

/* ── Fortschritt (Hintergrundjobs) ────────────────────────────────────────
   Nie ein Balken ohne Text: „Was laeuft gerade" ist wichtiger als „wie weit". */
.progress { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-sm); }
.progress-bar { flex: 1; height: 6px; background: var(--surface); border-radius: var(--r-pill); overflow: hidden; }
.progress-fill { height: 100%; background: var(--accent2); transition: width .3s; }

/* ── Beleg-Fenster (VALDURA-551, geteilt seit VALDURA-584) ────────────────
   `widgets.dialog({klasse:'ndp-beleg'})`: ein Foto oder Dokument groß, mit
   Kopfzeile und Text darunter. Benutzt von den ND-Fließtexten, dem
   Quellen-Panel der Objektakte und der Fotogalerie – EINE Fassung. */
/* ── Unterschrift in der App (VALDURA-1054) ───────────────────────────────
   `widgets.unterschrift`: DocuSeal im Dialog statt im neuen Tab. Groß,
   weil das Formular samt Unterschriftsfeld darin Platz braucht; die
   Satzzeile sagt, was gerade geschieht – laden, unterschreiben, übernehmen. */
.modal.unterschrift-fenster { max-width: min(1000px, 96vw); height: min(92vh, 980px);
  max-height: 92vh; display: flex; flex-direction: column; padding: var(--sp-3); }
.unterschrift-kopf { display: flex; align-items: center; gap: var(--sp-2); }
.unterschrift-kopf .modal-title { flex: 1; margin: 0; }
.unterschrift-satz { font-size: var(--fs-sm); color: var(--muted); margin: var(--sp-1) 0 var(--sp-2); }
.unterschrift-satz[data-art="laeuft"] { color: var(--text); font-weight: 600; }
.unterschrift-satz[data-art="warn"] { color: var(--warn); background: var(--warn-bg);
  border-radius: var(--r-sm); padding: var(--sp-2) var(--sp-3); }
.unterschrift-rahmen { flex: 1; min-height: 0; overflow: auto; border: 1px solid var(--border);
  border-radius: var(--r-md); background: var(--card); }
.unterschrift-rahmen > .btn { margin: var(--sp-4); }
@media (max-width: 760px) { .modal.unterschrift-fenster { height: 96vh; max-height: 96vh; padding: var(--sp-2); } }
.modal.ndp-beleg{max-width:960px}
.modal.ndp-beleg .ndp-beleg-kopf{display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-size:12px;color:var(--muted);margin-bottom:8px}
.modal.ndp-beleg .ndp-beleg-kopf b{color:var(--text)}
.modal.ndp-beleg img.ndp-beleg-bild{display:block;max-width:100%;max-height:80vh;margin:0 auto;object-fit:contain;border-radius:6px;background:var(--bg)}
.modal.ndp-beleg iframe.ndp-beleg-pdf{display:block;width:100%;height:75vh;border:1px solid var(--border);border-radius:6px;background:var(--bg)}
.modal.ndp-beleg .ndp-beleg-text{font-size:13px;color:var(--text);margin-top:8px;line-height:1.45}

/* ── Filterleiste einer Tabelle (VALDURA-683) ─────────────────────────────
   Das Aussehen zu `widgets.tabelle`. Es steht hier und nicht in einer
   eigenen Datei, weil beide Seiten, die es benutzen, von `base.html` erben
   und die Tokens ohnehin laden – anders als `tabelle_mobil.css` und
   `menue.css`, deren Seiten das nicht tun und die deshalb an jedem `var()`
   einen Rückfall tragen müssen.

   Die Leiste umbricht (`flex-wrap`): Bei drei Facetten und einer
   Sortierung passt sie auf einem Telefon nicht in eine Zeile, und
   seitliches Scrollen wäre hier derselbe Fehler wie in einer Tabelle mit
   fünfzehn Spalten. */
.tabfilter { display: flex; gap: var(--sp-2); align-items: center; flex-wrap: wrap;
  padding: var(--sp-2) 0; }
.tabfilter .tabfilter-such { flex: 1 1 220px; min-width: 160px; max-width: 340px; }
.tabfilter .form-select { width: auto; min-width: 130px; }
/* Die Zählzeile schiebt sich nach rechts und bleibt damit an derselben
   Stelle, egal wie viele Facetten die Seite liefert. */
.tabfilter-zahl { margin-left: auto; font-size: var(--fs-sm); color: var(--muted);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.tabfilter-hinweis { font-size: var(--fs-xs); color: var(--muted); flex: 1 1 100%; }
.tabfilter .tabfilter-r { min-width: 2.2em; font-variant-numeric: tabular-nums; }

/* Ein sortierbarer Spaltenkopf. Der Pfeil erscheint erst, wenn nach dieser
   Spalte sortiert wird – ein Pfeil an jeder Spalte sagt nicht, welche gilt. */
th.tabsort { cursor: pointer; user-select: none; white-space: nowrap; }
th.tabsort:hover { color: var(--accent); }
th.tabsort:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
th.tabsort.ist-auf::after { content: " \2191"; color: var(--accent); }
th.tabsort.ist-ab::after  { content: " \2193"; color: var(--accent); }

/* ── Vollbild und Teiler (VALDURA-990) ──────────────────────────────────────
   Das Verhalten steht in `static/widgets.js` (`widgets.vollbild`,
   `widgets.teiler`); das Aussehen steht hier – dasselbe Muster wie
   `modal-backdrop`/`modal`.

   Gemeldet wurde beides in einem Satz (Idee #110, Dokumentprüfung): zu wenig
   Platz zum Lesen UND eine Trennlinie, die „unerwartet festrastet". */

/* Ein Arbeitsbereich füllt das Fenster. Er wird nicht neu aufgebaut, nur
   grösser – ein neu gesetztes `src` wäre genau die Wartezeit, die weg soll. */
.w-voll { position: fixed; inset: 0; z-index: var(--z-vollbild, 45); }
body.w-voll-an { overflow: hidden; }

/* DER GRUND FÜR DIESE DREI ZEILEN: Ein iframe ist ein eigenes Dokument.
   Wandert der Zeiger beim Ziehen darüber, bekommt das Elternfenster weder
   `mousemove` noch `mouseup` – die Trennlinie bleibt stehen, und wer über
   dem Dokument loslässt, zieht danach ohne gedrückte Taste weiter. Solange
   gezogen wird, ist eingebetteter Fremdinhalt deshalb durchlässig. */
body.w-teiler-zieht { user-select: none; cursor: col-resize; }
body.w-teiler-zieht iframe,
body.w-teiler-zieht embed,
body.w-teiler-zieht object { pointer-events: none; }

/* ── KI-Details an Foto und Unterlage (VALDURA-1250, widgets.kiDetails) ── */
.kid-rumpf { max-height: 70vh; overflow-y: auto; font-size: var(--fs-sm); }
.kid-kopf { color: var(--muted); margin: 0 0 var(--sp-3); }
.kid-abschnitt { border-top: 1px solid var(--border); padding: var(--sp-2) 0; }
.kid-titel { font-size: var(--fs-md); font-weight: 700; margin: 0 0 var(--sp-1); }
.kid-text { white-space: pre-wrap; }
.kid-leer, .kid-fuss { color: var(--muted); margin: 0; }
.kid-hinweis { color: var(--warn); margin: 0 0 var(--sp-2); }
.kid-quelle { color: var(--muted); font-size: var(--fs-xs); }
.kid-liste { margin: 0; padding-left: var(--sp-4); }
.kid-tabelle { border-collapse: collapse; width: 100%; margin: var(--sp-1) 0; }
.kid-tabelle th { text-align: left; vertical-align: top; color: var(--muted);
  font-weight: 600; padding: var(--sp-1) var(--sp-2) var(--sp-1) 0; white-space: nowrap; }
.kid-tabelle td { padding: var(--sp-1) 0; word-break: break-word; }
.kid-tabelle pre, .kid-roh pre, .kid-pre { font-family: var(--font-mono); font-size: var(--fs-xs);
  white-space: pre-wrap; word-break: break-word; margin: 0; background: var(--surface);
  border-radius: var(--r-sm); padding: var(--sp-2); }
.kid-roh { margin-top: var(--sp-1); }
.kid-roh summary { cursor: pointer; color: var(--accent); }
.kid-bauteil { margin: var(--sp-2) 0; }
