/* ============================================================
   Materialverwaltung – Oberfläche
   ============================================================ */

:root {
  --bg:        #f4f6f9;
  --panel:     #ffffff;
  --ink:       #1c2430;
  --ink-soft:  #5d6b7d;
  --line:      #dfe4ec;
  --line-soft: #edf0f5;
  --brand:     #2d6cdf;
  --brand-dk:  #1f52b0;
  --ok:        #1a8a52;
  --ok-bg:     #e6f5ed;
  --warn:      #a26a00;
  --warn-bg:   #fdf3dd;
  --err:       #c0392b;
  --err-bg:    #fdeceb;
  --side:      #1b2534;
  --side-ink:  #a9b6c8;
  --radius:    8px;
  --shadow:    0 1px 2px rgba(20,30,45,.06), 0 2px 8px rgba(20,30,45,.05);

  /* REDESIGN-SCHRITT-1 – Vorgabe «Portal-Zwilling» Fassung 3.1, §2.
     Die Namen sind dieselben wie in lib/core/ui/farben.dart der App.

     ABWEICHUNG (B2): Felder brauchen nach WCAG 1.4.11 einen Rahmen mit
     3:1. `--line` hat auf Weiss nur 1,28:1, dieser Wert 3,08:1. */
  --feldrand:  #8794a6;

  /* ABWEICHUNG: Text AUF hellem Zustandsgrund. `--ok` auf `--ok-bg` hat
     nur 3,88:1, `--warn` auf `--warn-bg` 4,14:1. Diese drei haben
     4,77:1, 5,37:1 und 5,38:1. Gilt in Marken, Hinweisen UND Meldungen. */
  --ok-text:   #167a48;
  --warn-text: #8a5a00;
  --err-text:  #b23427;

  --ok-rand:   #bfe3d0;
  --warn-rand: #f0dcae;
  --err-rand:  #f3c8c4;
  --info-rand: #c6d9f8;
  --marke-hell:#e8f0fe;

  /* Seitenleiste. ABWEICHUNG: der Zwischentitel ist heller als die
     bisherigen #6b7a90, weil er nur 10,5 px hoch ist. */
  --side-unter:#93a1b6;
  --side-zw:   #8593a8;
  --side-ged:  #8f9cb0;

  --leiste:    #f1f4f9;
  --tkopf:     #fafbfd;
  --hover:     #f7f9fc;

  /* Neu in §2, gebraucht von §12: */
  --gesperrt:  #c3cbd6;
  --punkt-warn:#d39a1c;
  --punkt-leise:#b4bfcd;
  --heute-zelle:#f5f8fe;
  --belegt-zelle:#c6d9f8;
  --schleier:  rgba(27,37,52,.32);
  --toast-link:#9cc0ff;

  --schatten-menue:  0 10px 30px rgba(15,25,40,.18);
  --schatten-dialog: 0 12px 40px rgba(10,20,35,.30);
}

* { box-sizing: border-box; }
/* Reicht der Browser allein, aber nicht gegen eine inline gesetzte
   Anzeige – und genau die setzt die Artikelart-Umschaltung. */
[hidden] { display: none !important; }
/* Dateifelder bringen eine eigene Mindestbreite mit und schieben sonst
   die ganze Spalte auseinander. */
input[type="file"] { max-width: 100%; }

html, body {
  margin: 0; padding: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  -webkit-text-size-adjust: 100%;
}

a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ---------------- Grundgerüst ---------------- */
.shell { display: flex; min-height: 100vh; }

.side {
  /* 184 statt 232: Die Navigation braucht nur so viel Platz, wie der
     laengste Eintrag hoch ist – der gewonnene Rand geht an die
     Positionstabelle, die ihn dringender braucht. */
  width: 184px; flex: 0 0 184px;
  background: var(--side);
  color: var(--side-ink);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
}

.brand {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 12px 12px;
  border-bottom: 1px solid rgba(255,255,255,.07);
}
.brand-mark {
  width: 20px; height: 20px; flex: 0 0 20px;
  display: flex; align-items: center; justify-content: center;
}
.brand-mark svg { width: 100%; height: 100%; display: block; }
.brand-text { color: #fff; font-weight: 600; font-size: 13.5px; line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.side nav { padding: 8px 7px; flex: 1; overflow-y: auto; }
.side nav a {
  display: block; padding: 6px 9px; margin-bottom: 1px;
  border-radius: 6px; color: var(--side-ink);
  font-size: 13.5px; line-height: 1.35; text-decoration: none;
}
.side nav a:hover { background: rgba(255,255,255,.06); color: #fff; }
.side nav a.on { background: var(--brand); color: #fff; font-weight: 500; }
/* REDESIGN-SCHRITT-1: eigene Farbe statt Deckkraft - eine Deckkraft
   auf Text senkt den Kontrast unkontrolliert (§2 `seiteUnterpunkt`). */
.side nav a.sub { padding-left: 20px; font-size: 12.5px;
                  color: var(--side-unter); }
/* Ein gewaehlter Unterpunkt ist weiss wie jeder gewaehlte Eintrag.
   Ohne diese Regel gewinnt `.side nav a.sub` (eine Klasse, spaeter in
   der Datei) ueber `.side nav a.on` und setzt die Schrift auf
   --side-unter (#93a1b6). Auf dem blauen Grund sind das 1,85:1 --
   am 19.10.2026 im Browser gemessen, mit der Berichtigung 4,86:1.
   Zwei Klassen gewinnen, darum genuegt die Farbe; Groesse, Gewicht
   und Einzug bleiben unveraendert (ebenfalls gemessen). */
.side nav a.sub.on { color: #fff; }
.nav-sep {
  margin: 12px 9px 4px; font-size: 10.5px; text-transform: uppercase;
  /* REDESIGN-SCHRITT-1: heller als die bisherigen #6b7a90 (§2) */
  letter-spacing: .07em; color: var(--side-zw);
}

.side-foot { padding: 10px 12px; border-top: 1px solid rgba(255,255,255,.07); font-size: 12.5px; }
.me strong { display: block; color: #fff; font-weight: 600; }
.me span { color: var(--side-ged); font-size: 12px; }
.me-links { margin-top: 6px; display: flex; gap: 10px; flex-wrap: wrap; }
.me-links a { color: var(--side-ink); font-size: 12.5px; }
.me-version { margin-top: 7px; font-size: 10.5px; letter-spacing: .02em; opacity: .45; }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 26px; background: var(--panel);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
}
.topbar h1 { margin: 0; font-size: 19px; font-weight: 600; }

.content { padding: 18px 18px 56px; }

/* ===================================================================
   §11.3 Speicheranzeige, §15: rechts in der vorhandenen header.topbar,
   gleiche Masse wie in der App.

   Drei Zustaende, und ein vierter, der nichts zeigt:

     ruhig        nichts (keine Aenderung seit dem Laden)
     gespeichert  Haken 14 px in --ok-text, «Gespeichert», tinteSanft
     speichert    Drehkreis 13 px (Rand --line, oben --brand),
                  «Speichert …» - erst nach 300 ms, damit es nicht
                  flackert (das macht das JavaScript, nicht das CSS)
     fehler       Kreis mit «!» 14 px, «Nicht gespeichert · Erneut
                  versuchen», Text --err-text, der Link unterstrichen
                  in --brand-dk

   Die Farben sind die aus §2, die im Portal schon stehen (gemessen am
   11.10.2026): --ok-text ist #167a48, --err-text ist #b23427 - genau
   die Werte, die §11.3 nennt.

   «Bewegung reduzieren»: der Kreis dreht sich nicht (§11.3, letzter
   Satz).
   =================================================================== */

.speicheranzeige {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  font-size: 13px;
  line-height: 1;
  white-space: nowrap;
  /* Der Platz bleibt, auch wenn nichts steht: sonst springt die
     Kopfleiste bei jedem Speichern. */
  min-height: 18px;
}

.speicheranzeige[hidden] { display: none; }

/* --- Gespeichert ------------------------------------------------- */

.speicheranzeige-text { color: var(--ink-soft); }

.speicheranzeige-haken {
  width: 14px;
  height: 14px;
  flex: 0 0 14px;
  color: var(--ok-text);
}

/* --- Speichert --------------------------------------------------- */

.speicheranzeige-kreis {
  width: 13px;
  height: 13px;
  flex: 0 0 13px;
  border: 2px solid var(--line);
  border-top-color: var(--brand);
  border-radius: 50%;
  animation: speicheranzeige-dreh .9s linear infinite;
}

@keyframes speicheranzeige-dreh {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .speicheranzeige-kreis { animation: none; }
}

/* --- Fehler ------------------------------------------------------ */

.speicheranzeige-fehler .speicheranzeige-text { color: var(--err-text); }

.speicheranzeige-ruf {
  width: 14px;
  height: 14px;
  flex: 0 0 14px;
  color: var(--err-text);
}

.speicheranzeige-nochmal {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--brand-dk);
  text-decoration: underline;
  cursor: pointer;
}

.speicheranzeige-nochmal:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 3px;
}

/* --- Schmal ------------------------------------------------------ */
/* §15: unter 1180 px und im Handy-Layout tritt die Suche zur Lupe
   zusammen. Die Speicheranzeige behaelt ihr Symbol und laesst den
   Text weg - der Zustand bleibt erkennbar, die Leiste bleibt schmal. */

@media (max-width: 1180px) {
  .speicheranzeige-text { display: none; }
  .speicheranzeige-nochmal { display: inline; }
}

/* Die Kopfleiste verschwindet beim Drucken ohnehin (app.css, .topbar
   in @media print) - hier ist nichts nachzuholen. */


.burger { display: none; flex-direction: column; gap: 4px; cursor: pointer; padding: 4px; }
.burger span { display: block; width: 20px; height: 2px; background: var(--ink); border-radius: 2px; }
.nav-scrim { display: none; }

/* ---------------- Meldungen ---------------- */
.flash {
  margin: 14px 26px 0; padding: 11px 14px;
  border-radius: var(--radius); font-size: 14px; border: 1px solid transparent;
}
/* REDESIGN-SCHRITT-1: Text auf hellem Grund in der dunklen Farbe (§2) */
.flash-ok   { background: var(--ok-bg);   color: var(--ok-text);
              border-color: var(--ok-rand); }
.flash-warn { background: var(--warn-bg); color: var(--warn-text);
              border-color: var(--warn-rand); }
.flash-err  { background: var(--err-bg);  color: var(--err-text);
              border-color: var(--err-rand); }
.flash-info { background: var(--marke-hell); color: var(--brand-dk);
              border-color: var(--info-rand); }

.errbox {
  /* REDESIGN-SCHRITT-1 (§5): Text in --err-text */
  background: var(--err-bg); border: 1px solid var(--err-rand);
  color: var(--err-text);
  padding: 12px 14px 12px 30px; border-radius: var(--radius); margin-bottom: 18px;
}
.errbox ul { margin: 0; padding-left: 0; }
.errbox li { margin: 2px 0; }

/* ---------------- Karten & Raster ---------------- */
.card {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  margin-bottom: 20px;
}
.card > h2 {
  margin: 0; padding: 13px 18px; font-size: 15px; font-weight: 600;
  border-bottom: 1px solid var(--line-soft);
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.card-body { padding: 18px; }
.card-body > :first-child { margin-top: 0; }
.card-body > :last-child  { margin-bottom: 0; }

/* Eine ganze Karte zuklappen, mit der Zusammenfassung in der Zeile des
   Griffs. Gebaut wie .postfach-mail weiter unten (880-885), nur ohne eigenen
   Rahmen: dort ist jedes <details> ein Kaestchen in einer Liste, hier ist es
   der Inhalt einer Karte, die ihren Rahmen schon hat. Steht hier bei .card
   und nicht beim Postfach, weil es zu den Karten gehoert und nicht zu den
   Nachrichten.
   Das Dreieck des Browsers wird ersetzt und nicht nur umgefaerbt: es sieht
   in Safari und Chrome verschieden aus und laesst sich nicht ausrichten. */
.klapp-karte > summary { cursor: pointer; padding: 11px 18px; display: flex; gap: 10px;
                         align-items: baseline; flex-wrap: wrap; font-size: 13px;
                         color: var(--ink-soft); }
.klapp-karte > summary::-webkit-details-marker { display: none; }
.klapp-karte > summary::before { content: '▸'; flex: 0 0 auto; }
.klapp-karte[open] > summary::before { content: '▾'; }
.klapp-karte > summary:hover { color: var(--ink); }
.klapp-karte[open] > summary { border-bottom: 1px solid var(--line-soft); }

.grid  { display: grid; gap: 18px; }
.g2    { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g3    { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.g4    { grid-template-columns: repeat(4, minmax(0, 1fr)); }
/* REDESIGN-SCHRITT-1 (§4.4): 270 px fest statt eines Anteils. Ein
   Anteil machte die Spalte im breiten Fenster unnoetig breit und im
   schmalen zu eng. */
.g-side{ grid-template-columns: minmax(0,1fr) 270px; align-items: start; gap: 14px; }

/* Die Seitenspalte ist Nachschlagewerk, nicht Arbeitsfläche: enger
   gesetzt, damit links mehr Zeilen auf einen Blick passen. */
.g-side > *:last-child .card          { margin-bottom: 12px; }
.g-side > *:last-child .card > h2     { padding: 9px 12px; font-size: 13.5px; }
.g-side > *:last-child .card-body     { padding: 11px 12px; font-size: 13.5px; }
/* REDESIGN-SCHRITT-1 (B5): 124 statt 104 px. Bei 104 bricht
   «Wiederbeschaffung» mitten im Wort; 116 reichten im Prototyp nicht. */
.g-side > *:last-child .dl            { font-size: 13px; gap: 5px 10px;
                                        grid-template-columns: minmax(0,124px) minmax(0,1fr); }
.g-side > *:last-child hr.sep         { margin: 10px 0; }
/* In einer 200px-Spalte passt weder ein breiter Knopf noch eine
   Summenzeile in einem Stück. Beides darf hier umbrechen. */
.g-side > *:last-child .btn           { max-width: 100%; white-space: normal; text-align: center; }
.g-side > *:last-child .card-body > div[style*="space-between"] { flex-wrap: wrap; gap: 2px 8px; }

/* REDESIGN-SCHRITT-1 (B5, §4.4): eine Formularkarte wird nicht
   breiter als 820 px - ueber die ganze Breite gezogene Felder sind
   unlesbar. Die Klasse muss in den Views gesetzt werden; welche Karten
   sie bekommen, entscheidet §12.11. */
.card-form { max-width: 820px; }

.stat { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 16px 18px; box-shadow: var(--shadow); }
.stat .n { font-size: 28px; font-weight: 650; line-height: 1.1; }
.stat .l { color: var(--ink-soft); font-size: 13px; margin-top: 4px; }

/* ---------------- Tabellen ---------------- */
/* Der Tabellenkopf bleibt beim Blaettern stehen (Vorgabe 3.1 §5,
   Jochens Entscheidung vom 19.10.2026).

   Am Kopf steht seit langem `position: sticky; top: 0` -- und es wirkte
   NIE. Am 19.10.2026 im Browser gemessen: bei 400 px Rollweg stand der
   Kopf auf -319 px, also ganz aus dem Bild. Die Ursache ist nicht der
   Kopf, sondern dieser Umschlag: `overflow-x: auto` macht ihn zum
   Rollbereich fuer BEIDE Achsen (der Browser rechnet overflow-y
   ebenfalls auf auto). Der Kopf klebte damit an einem Behaelter, der
   senkrecht nie rollt, und wanderte mit ihm aus dem Bild.

   Vier Varianten gemessen; nur zwei wirken, und nur diese eine behaelt
   dabei die waagerechte Rolle fuer breite Tabellen (Positionstabelle).
   Die Tabelle rollt dafuer in sich statt mit der Seite -- eine
   Verhaltensaenderung, die Jochen so entschieden hat.

   Die 70 vh sind der Anteil der Fensterhoehe; darunter bleibt Platz
   fuer die Fusszeile der Karte. */
.tablewrap { overflow-x: auto; max-height: 70vh; overflow-y: auto; }
table.t { width: 100%; border-collapse: collapse; font-size: 14px; }
table.t th, table.t td { padding: 9px 12px; text-align: left; border-bottom: 1px solid var(--line-soft); vertical-align: middle; }
table.t th {
  font-size: 11.5px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-soft); font-weight: 600; background: #fafbfd;
  position: sticky; top: 0; z-index: 1;
}
table.t tbody tr:hover { background: #f7f9fc; }
table.t tbody tr[data-zeile-href] { cursor: pointer; }
/* Rechtsbuendige Zellen tragen Zahlen. «312,00 €» ueber zwei Zeilen
   umzubrechen macht eine Spalte unlesbar – lieber schmaler setzen. */
table.t td.r, table.t th.r { text-align: right; white-space: nowrap; }
table.t td.c, table.t th.c { text-align: center; }
table.t .muted { color: var(--ink-soft); }
.nowrap { white-space: nowrap; }

.thumb {
  width: 40px; height: 40px; border-radius: 5px; object-fit: cover;
  background: var(--line-soft); display: block;
}
.thumb-lg { width: 100%; max-width: 320px; border-radius: var(--radius); display: block; }

/* ---------------- Bildausschnitt beim Hochladen (Crop-Werkzeug) ---------------- */
.crop-tool { margin: 10px 0 4px; }
.crop-box {
  position: relative; width: 100%; max-width: 360px; aspect-ratio: 4/3;
  overflow: hidden; background: #fff; border: 1px solid var(--line-soft); border-radius: var(--radius);
  cursor: grab; touch-action: none; user-select: none;
}
.crop-box:active { cursor: grabbing; }
.crop-box img { position: absolute; top: 0; left: 0; max-width: none; transform-origin: 0 0; }
.crop-controls { display: flex; align-items: center; gap: 10px; margin-top: 8px; max-width: 360px; }
.crop-controls input[type="range"] { flex: 1; }

/* ---------------- Marken / Etiketten ---------------- */
.tag {
  display: inline-block; padding: 2px 8px; border-radius: 20px;
  font-size: 12px; font-weight: 500; white-space: nowrap;
  background: var(--line-soft); color: var(--ink-soft);
}
/* REDESIGN-SCHRITT-1: Text auf hellem Grund in der dunklen Farbe (§2) */
.tag-ok   { background: var(--ok-bg);   color: var(--ok-text); }
.tag-warn { background: var(--warn-bg); color: var(--warn-text); }
.tag-err  { background: var(--err-bg);  color: var(--err-text); }
.tag-info { background: var(--marke-hell); color: var(--brand-dk); }

/* ---------------- Formulare ---------------- */
.field { margin-bottom: 15px; }
.field > label, .lbl {
  display: block; font-size: 13px; font-weight: 600;
  color: var(--ink); margin-bottom: 5px;
}
.hint { font-size: 12.5px; color: var(--ink-soft); margin-top: 4px; }

/* Alle Eingabefelder sind gleich hoch – auch Auswahl- und Datumsfelder.
   Ohne «appearance: none» behalten Auswahl-, Datums- und Dateifelder in
   Safari ihre Systemdarstellung und ignorieren Höhe und Innenabstand:
   nebeneinander stehen dann drei verschieden hohe Felder. */
input[type=text], input[type=email], input[type=password], input[type=number],
input[type=date], input[type=time], input[type=search], input[type=tel],
input[type=url], input[type=file], select, textarea {
  width: 100%; padding: 8px 11px; font: inherit; font-size: 14px;
  line-height: 20px; min-height: 38px;
  color: var(--ink); background: #fff;
  /* REDESIGN-SCHRITT-1: --feldrand statt --line (§2, B2) */
  border: 1px solid var(--feldrand); border-radius: 6px;
  -webkit-appearance: none; appearance: none;
}
textarea { min-height: 92px; }
/* Der Aufklapp-Pfeil, den «appearance: none» entfernt – als Bild, damit
   er in jedem Browser gleich sitzt. Rechts Platz lassen, sonst liefe
   langer Text darunter. */
select {
  padding-right: 30px; cursor: pointer;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%236b7280' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center;
  background-size: 11px 8px;
}
select[multiple] { background-image: none; padding-right: 11px; }
/* Datumsfelder: Safari zentriert den Inhalt, alle anderen setzen ihn
   nach links – ohne das stünde das Datum anders als der Text daneben. */
input[type=date], input[type=time] { text-align: left; }
/* Dateifelder: der Knopf gehört in das Feld, nicht daneben.

   Kein «display: flex» mehr. Es wirkte nur in Chrome: der
   ::file-selector-button ist ein Pseudo-Element und in Safari kein
   Flex-Kind – dort blieb er an der Grundlinie kleben und sass am oberen
   Feldrand, während er in Chrome mittig stand (am 25.09.2026 gemessen).
   Stattdessen sitzen Knopf und Dateiname auf derselben Mittellinie:
   line-height so hoch wie das Feld innen, beide «vertical-align: middle».
   Das können alle Browser. */
input[type=file] {
  padding: 0 11px; cursor: pointer;
  line-height: 36px;        /* 38px Feldhöhe minus 2×1px Rahmen */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
input[type=file]::file-selector-button {
  font: inherit; font-size: 13px; margin: 0 10px 0 0; padding: 0 11px;
  height: 26px; line-height: 24px; vertical-align: middle;
  color: var(--ink); background: var(--bg-soft, #f3f4f6);
  border: 1px solid var(--line); border-radius: 5px; cursor: pointer;
}
input[type=file]::file-selector-button:hover { border-color: var(--brand); }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(45,108,223,.13);
}
textarea { min-height: 92px; resize: vertical; }
input[type=checkbox] { width: 16px; height: 16px; accent-color: var(--brand); vertical-align: -2px; }

.check { display: flex; align-items: center; gap: 8px; font-size: 14px; cursor: pointer; }
.check input { flex: 0 0 auto; }

.row { display: grid; gap: 14px; }
.row-2 { grid-template-columns: repeat(2, minmax(0,1fr)); }
.row-3 { grid-template-columns: repeat(3, minmax(0,1fr)); }
.row-4 { grid-template-columns: repeat(4, minmax(0,1fr)); }

.actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.actions-end { justify-content: flex-end; }

/* ---------------- Schaltflächen ---------------- */
.btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 15px; font: inherit; font-size: 14px; font-weight: 500;
  border-radius: 6px; border: 1px solid var(--line);
  background: #fff; color: var(--ink); cursor: pointer; text-decoration: none;
  white-space: nowrap;
}
.btn:hover { background: #f5f7fa; text-decoration: none; }
.btn-primary { background: var(--brand); border-color: var(--brand); color: #fff; }
.btn-primary:hover { background: var(--brand-dk); border-color: var(--brand-dk); }
.btn-danger { background: #fff; border-color: #f0c4bf; color: var(--err); }
.btn-danger:hover { background: var(--err-bg); }
.btn-sm { padding: 5px 10px; font-size: 13px; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
/* Für Buttons mit ungewöhnlich langem Text (z.B. "Rechnungs- oder
   Angebotsnummer vergeben" im Beleg-anlegen-Formular): bricht sauber auf
   zwei Zeilen um, statt über den Rand der Spalte/des Bildschirms
   hinauszuragen. Etwas kleinere Schrift, damit es nicht zu klobig wirkt. */
.btn-wrap {
  white-space: normal; text-align: center; line-height: 1.25; font-size: 13px;
}

/* ---------------- Filterleiste ---------------- */
.filters {
  display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 14px 16px; margin-bottom: 18px;
  box-shadow: var(--shadow);
}
.filters .field { margin: 0; }
.filters input:not([type=checkbox]), .filters select { min-width: 150px; }
.filters .check { white-space: nowrap; }
.filters .grow { flex: 1; min-width: 200px; }

/* ---------------- Seitenkopf ---------------- */
.pagehead { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 16px; flex-wrap: wrap; }
.pagehead h2 { margin: 0; font-size: 17px; }
.crumbs { font-size: 13px; color: var(--ink-soft); margin-bottom: 6px; }

/* ---------------- Blättern ---------------- */
.pager { display: flex; gap: 6px; align-items: center; margin-top: 16px; flex-wrap: wrap; font-size: 14px; }
.pager a, .pager span {
  padding: 5px 11px; border: 1px solid var(--line); border-radius: 6px;
  background: #fff; color: var(--ink); text-decoration: none;
}
.pager .on { background: var(--brand); border-color: var(--brand); color: #fff; }
.pager .muted { border: none; background: none; color: var(--ink-soft); }

/* ---------------- Verfügbarkeitsraster ---------------- */
.planwrap { overflow: auto; max-height: 74vh; border: 1px solid var(--line); border-radius: var(--radius); background: #fff; }
table.plan { border-collapse: separate; border-spacing: 0; font-size: 13px; width: max-content; min-width: 100%; }
table.plan th, table.plan td { border-bottom: 1px solid var(--line-soft); border-right: 1px solid var(--line-soft); padding: 0; }
table.plan thead th {
  position: sticky; top: 0; z-index: 3; background: #fafbfd;
  font-size: 11px; font-weight: 600; color: var(--ink-soft);
  padding: 6px 4px; text-align: center; min-width: 34px;
}
table.plan thead th.we { background: #eef1f6; }
table.plan th.namecol, table.plan td.namecol {
  position: sticky; left: 0; z-index: 2; background: #fff;
  min-width: 260px; max-width: 320px; padding: 7px 12px; text-align: left;
  border-right: 1px solid var(--line);
}
table.plan thead th.namecol { z-index: 4; background: #fafbfd; }
table.plan tbody tr:hover td.namecol { background: #f7f9fc; }
.plan td.cell {
  text-align: center; padding: 8px 6px;
  font-variant-numeric: tabular-nums; font-size: 12.5px;
}
/* Belegungsraster: leer heisst frei, Farbe heisst es passiert etwas */
td.bel-frei   { background: #fff; }
td.bel-fest   { background: #d9e6fb; color: #1b4a8a; font-weight: 600; }
td.bel-option { background: #fdf3dd; color: #8a5a00; font-weight: 600; }
td.bel-sperre { background: #e9ecf1; color: #5a6675; font-weight: 600; }
td.bel-ueber  { background: #f9d9d6; color: #a3271b; font-weight: 700; }

.legende { display: inline-block; margin-left: 8px; padding: 1px 7px; border-radius: 4px; font-size: 11.5px; }
.legende.bel-fest   { background: #d9e6fb; color: #1b4a8a; }
.legende.bel-option { background: #fdf3dd; color: #8a5a00; }
.legende.bel-sperre { background: #e9ecf1; color: #5a6675; }
.legende.bel-ueber  { background: #f9d9d6; color: #a3271b; }
.plan .item-name { font-weight: 500; }
.plan .item-meta { font-size: 11.5px; color: var(--ink-soft); }

/* ---------------- Kleinteile ---------------- */
.muted { color: var(--ink-soft); }
.small { font-size: 13px; }
.mono  { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 13px; }
.empty { padding: 34px 18px; text-align: center; color: var(--ink-soft); }
.empty p { margin: 0 0 12px; }
hr.sep { border: none; border-top: 1px solid var(--line-soft); margin: 18px 0; }
.dl { display: grid; grid-template-columns: minmax(0, 150px) minmax(0, 1fr); gap: 7px 14px; font-size: 14px; margin: 0; }
.dl dt { color: var(--ink-soft); min-width: 0; overflow-wrap: anywhere; }
/* Ohne die Null als Untergrenze macht ein langer Firmenname die
   Beschreibungsliste breiter als die Karte, in der sie steht. */
.dl dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.inline-form { display: inline; }

/* ---------------- Anmeldeseite ---------------- */
.auth {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 24px; background: linear-gradient(160deg, #1b2534 0%, #24344b 100%);
}
.auth-box {
  width: 100%; max-width: 400px; background: #fff;
  border-radius: 12px; padding: 30px 28px;
  box-shadow: 0 12px 40px rgba(10,20,35,.30);
}
.auth-box h1 { margin: 0 0 4px; font-size: 20px; }
.auth-box .sub { color: var(--ink-soft); font-size: 14px; margin: 0 0 22px; }
.auth-box .btn { width: 100%; justify-content: center; margin-top: 6px; }

/* ---------------- Handy / Tablet ---------------- */
/* Unter 1100px bleibt fuer die Seitenspalte zu wenig uebrig: Summen und
   Eckdaten wuerden auf 200px zusammengedrueckt. Dann lieber unter den
   Positionen, wo sie in voller Breite lesbar sind. */
@media (max-width: 1100px) {
  /* minmax(0,1fr) statt 1fr: sonst zieht eine breite Tabelle die
     Spalte auf, und die ganze Seite wandert nach rechts aus dem
     Bild. Mit der Null als Untergrenze bleibt die Spalte schmal und
     die Tabelle rollt in ihrem .tablewrap. */
  .g-side { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 900px) {
  .g4, .g3, .g2 { grid-template-columns: minmax(0, 1fr); }
  .row-4 { grid-template-columns: repeat(2, minmax(0,1fr)); }
}

@media (max-width: 720px) {
  .side {
    position: fixed; left: 0; top: 0; bottom: 0; z-index: 60;
    transform: translateX(-100%); transition: transform .18s ease;
  }
  #navtoggle:checked ~ .shell .side { transform: translateX(0); }
  #navtoggle:checked ~ .nav-scrim {
    display: block; position: fixed; inset: 0; z-index: 50;
    background: rgba(15,22,33,.45);
  }
  .burger { display: flex; }
  .content { padding: 16px 14px 50px; }
  .topbar  { padding: 13px 14px; }
  .flash   { margin: 12px 14px 0; }
  .row-2, .row-3, .row-4 { grid-template-columns: 1fr; }
  .dl { grid-template-columns: 1fr; gap: 2px 0; }
  .dl dt { margin-top: 8px; font-size: 12.5px; }
  table.plan th.namecol, table.plan td.namecol { min-width: 170px; }
}

/* ---------------- Druck ---------------- */
@media print {
  .side, .topbar, .filters, .actions, .pager, .flash { display: none !important; }
  .content { padding: 0; }
  .card { border: none; box-shadow: none; }
  body { background: #fff; }
}

/* ------------------------------------------------------------------
   Registerkarten
   Für Seiten, die sonst endlos scrollen. Ohne JavaScript bleiben
   alle Bereiche sichtbar – die Seite ist dann lang, aber vollständig.
   ------------------------------------------------------------------ */
/* REDESIGN-SCHRITT-1 (B4): einreihig. Reicht der Platz nicht, rollt
   die Leiste waagerecht statt umzubrechen; am Rand zeigt ein 16 px
   breiter Verlauf, dass es weitergeht. Eine umbrechende Leiste schob
   den ganzen Inhalt nach unten. */
.tabs {
  display: flex; gap: 2px; flex-wrap: nowrap;
  overflow-x: auto; scrollbar-width: thin;
  border-bottom: 1px solid var(--line);
  margin: 0 0 16px;
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 16px), transparent);
  mask-image: linear-gradient(90deg, #000 calc(100% - 16px), transparent);
}
.tabs button { flex: 0 0 auto; }
.tabs button {
  appearance: none; background: none; border: 0; cursor: pointer;
  font: 600 14px/1 inherit; color: var(--ink-soft);
  padding: 11px 15px; margin-bottom: -1px;
  border-bottom: 2px solid transparent; border-radius: 6px 6px 0 0;
  display: inline-flex; align-items: center; gap: 7px;
}
.tabs button:hover { color: var(--ink); background: var(--line-soft); }
.tabs button[aria-selected="true"] {
  color: var(--brand); border-bottom-color: var(--brand); background: none;
}
/* Die Zahl an einem Reiter oder einer Kartenüberschrift: wie viele
   stecken da drin. Auch ausserhalb der Reiterleiste brauchbar. */
.zahl {
  font-weight: 600; font-size: 11.5px; line-height: 1;
  padding: 3px 6px; border-radius: 999px;
  background: var(--line-soft); color: var(--ink-soft);
}
.tabs button[aria-selected="true"] .zahl { background: #e7eefb; color: var(--brand-dk); }
.zahl.achtung { background: var(--err-bg); color: var(--err-text); }
table.t td.err, table.t td.err strong { color: var(--err); }
@media (max-width: 620px) {
  .tabs { gap: 0; }
  .tabs button { padding: 10px 11px; font-size: 13.5px; }
}

/* ------------------------------------------------------------------
   Freelancer-Portal
   Eigener Rahmen, aber dieselben Bausteine wie in der Verwaltung:
   Karten, Felder, Knöpfe. Wer beides kennt, findet sich sofort zurecht.
   ------------------------------------------------------------------ */
body.portal { background: var(--bg); }
.portal-innen { max-width: 880px; margin: 0 auto; padding: 0 18px; }
.portal-kopf {
  background: var(--side); color: #fff; padding: 12px 0; margin-bottom: 26px;
}
.portal-kopf .portal-innen {
  display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap;
}
.portal-marke {
  display: inline-flex; align-items: center; gap: 10px;
  color: #fff; text-decoration: none; font-weight: 600; font-size: 15px;
}
.portal-zusatz {
  font-weight: 500; font-size: 12px; opacity: .72;
  border-left: 1px solid rgba(255,255,255,.25); padding-left: 10px;
}
.portal-nav { display: flex; gap: 4px; flex-wrap: wrap; }
.portal-nav a {
  color: rgba(255,255,255,.78); text-decoration: none;
  font-size: 13.5px; font-weight: 500; padding: 7px 11px; border-radius: 7px;
}
.portal-nav a:hover { background: rgba(255,255,255,.1); color: #fff; }
.portal-nav a.on { background: var(--brand); color: #fff; }
.portal-haupt { padding-bottom: 40px; }
.portal-titel { font-size: 21px; margin: 0 0 18px; }
.portal-fuss {
  display: flex; justify-content: space-between; gap: 12px;
  font-size: 12.5px; color: var(--ink-soft);
  padding-top: 18px; padding-bottom: 30px;
  border-top: 1px solid var(--line);
}
.portal-fuss a { color: var(--ink-soft); }
.portal-version { opacity: .6; }
.portal-schmal { max-width: 430px; margin: 0 auto; }

/* Gewerkezeile im Profil: Haken, Satz, Notiz nebeneinander */
.gewerk-zeile {
  display: grid; grid-template-columns: 1fr 140px 1fr; gap: 12px; align-items: center;
  padding: 11px 0; border-bottom: 1px solid var(--line-soft);
}
.gewerk-zeile:last-child { border-bottom: 0; }
.gewerk-zeile .name { font-weight: 500; }
@media (max-width: 620px) {
  .gewerk-zeile { grid-template-columns: 1fr; gap: 7px; }
}

/* Zahl neben einem Navigationspunkt, z.B. wartende Registrierungen */
.nav-zahl {
  display: inline-block; min-width: 18px; text-align: center;
  font-size: 11px; font-weight: 700; line-height: 18px;
  border-radius: 999px; background: var(--err); color: #fff;
  padding: 0 5px; margin-left: 4px;
}

/* ------------------------------------------------------------------
   Stundenraster für Arbeitszeiten
   24 Rechtecke je Tag. Anklicken und ziehen setzt den Zeitraum; die
   beiden Uhrzeitfelder daneben bleiben massgeblich und lassen sich
   auch mit der Tastatur bedienen.
   ------------------------------------------------------------------ */
.zeit-tag {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 7px 12px; align-items: center;
  padding: 10px 0; border-bottom: 1px solid var(--line-soft);
}
/* Datum und Uhrzeiten teilen sich die erste Reihe, das Raster bekommt
   die zweite über die volle Breite. Nebeneinander blieben von den 24
   Feldern in einer Spalte von 690px nur 10px je Stunde übrig – zu
   schmal zum Treffen, und die Uhrzeitfelder standen aus der Karte
   heraus. */
.zeit-tag:last-of-type { border-bottom: 0; }
.zeit-tag.leer .zeit-datum { color: var(--ink-soft); }
.zeit-datum { grid-area: 1 / 1; font-size: 13px; font-weight: 500; }
.zeit-datum .wt { color: var(--ink-soft); font-weight: 400; }

.zeit-raster {
  grid-area: 2 / 1 / 3 / 3;
  display: grid; grid-template-columns: repeat(24, 1fr);
  gap: 1px; user-select: none; min-width: 0;
  border: 1px solid var(--line); border-radius: 6px; overflow: hidden;
  background: var(--line);
}
.zeit-raster i {
  display: block; height: 26px; background: #fff; cursor: pointer;
  font-style: normal; font-size: 10px; line-height: 26px; text-align: center;
  color: #c3cad6;
}
.zeit-raster i:nth-child(6n+1) { color: var(--ink-soft); }
.zeit-raster i:hover { background: #eef3fb; }
.zeit-raster i.an { background: var(--brand); color: #fff; }
.zeit-raster i.an:hover { background: var(--brand-dk); }

.zeit-felder { grid-area: 1 / 2; display: flex; align-items: center; gap: 5px; }
/* 108px: ein Uhrzeitfeld braucht in Chrome neben «20:00» noch das
   kleine Uhrsymbol, und im englischen Gebietsschema zusaetzlich das
   PM. Bei 78px wurde beides abgeschnitten. */
.zeit-felder input[type="time"] { width: 108px; padding: 6px 7px; font-size: 13px; }
.zeit-felder .btn { padding: 4px 8px; }
.zeit-summe { font-size: 12px; color: var(--ink-soft); min-width: 52px; text-align: right; }

@media (max-width: 560px) {
  .zeit-tag { grid-template-columns: 1fr; }
  .zeit-felder { grid-area: auto; }
  .zeit-raster { grid-area: auto; }
  .zeit-raster i { height: 30px; }
}

/* Positionstabelle: zwölf Spalten, von denen jede zweite ein Eingabe-
   feld trägt. Mit dem üblichen Zellenabstand von 12px je Seite gingen
   allein dafür fast 300px drauf – deshalb hier enger, kleiner und ohne
   Innenabstand an den Feldern. */
/* Positionstabelle: zwölf Spalten, von denen jede zweite ein Eingabe-
   feld trägt. Mit dem üblichen Zellenabstand von 12px je Seite gingen
   allein dafür fast 300px drauf – deshalb hier enger und kleiner.

   Überall «table.pos-t» statt nur «.pos-t»: Die allgemeine Regel heisst
   «table.t th, table.t td» und ist damit spezifischer als eine blosse
   Klasse. Ohne das Element davor bliebe hier alles beim Alten. */
table.pos-t { font-size: 12.5px; table-layout: fixed; width: 100%; }
table.pos-t th, table.pos-t td { padding: 4px; vertical-align: middle; }
table.pos-t th:first-child, table.pos-t td:first-child { padding-left: 8px; }
table.pos-t th:last-child,  table.pos-t td:last-child  { padding-right: 8px; }

/* Feste Spaltenbreiten: Sonst verteilt der Browser den Platz nach dem
   längsten Inhalt, und «Stück» im Einheitenfeld wird auf 50px
   gequetscht, während die Bezeichnung sich ausbreitet. */
table.pos-t input { width: 100%; min-width: 0; padding: 4px 6px; font-size: 12.5px; }

/* Die Zahlenspalten sahen aus wie gesetzter Text: heller Rahmen, weisser
   Grund, rechtsbündig – und wer sie für eine Anzeige hält, klickt nicht
   hinein. Ein Hauch Hintergrund und ein dunklerer Rahmen machen aus der
   Zahl wieder ein Feld, ohne die Tabelle unruhig zu machen. */
table.pos-t input[inputmode="decimal"],
table.pos-t input[type="number"] {
  background: #f7f9fc;
  border-color: #cdd5e1;
  text-align: right;
}
table.pos-t input[inputmode="decimal"]:hover,
table.pos-t input[type="number"]:hover { background: #fff; border-color: var(--brand); }
table.pos-t input[inputmode="decimal"]:focus,
table.pos-t input[type="number"]:focus { background: #fff; }
/* Gesperrte Zeilen sollen weiter nach Anzeige aussehen. */
table.pos-t input[readonly] { background: transparent; border-color: var(--line-soft); }
/* Der Zusatztext steht unter der Bezeichnung und kostet in jeder Zeile
   Höhe. Kleiner gesetzt passen ein paar Positionen mehr aufs Bild. */
table.pos-t input[name$="[description]"] { font-size: 11px; padding: 2px 6px; margin-top: 2px; }
table.pos-t .btn-sm { padding: 1px 5px; font-size: 11px; }
table.pos-t .tag { padding: 0 6px; font-size: 10.5px; }
/* Die beiden Pfeile untereinander statt nebeneinander: spart Breite in
   jeder Zeile und liest sich als Auf/Ab sogar besser. */
table.pos-t .inline-form { display: block; }
table.pos-t td:first-child { line-height: 1.1; }

/* Fotogalerie. Feste Reihenhöhe, damit aus Hoch- und Querformaten ein
   ruhiges Raster wird statt einer Treppe. */
.galerie { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 14px; }
.galerie.klein { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 8px; }
.galerie .bild { margin: 0; }
.galerie .bild a, .galerie .bild > img, .galerie .bild > .keinbild {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 150px; border-radius: 8px; overflow: hidden;
  background: #eef1f5; border: 1px solid var(--line);
}
.galerie.klein .bild a, .galerie.klein .bild > img, .galerie.klein .bild > .keinbild { height: 96px; }
.galerie .bild img { width: 100%; height: 100%; object-fit: cover; display: block; }
.galerie .keinbild { font-size: 12px; color: var(--ink-soft); text-align: center; line-height: 1.3; }
.galerie figcaption { font-size: 12px; line-height: 1.4; margin-top: 5px; }
.galerie figcaption .muted { color: var(--ink-soft); }
.galerie figcaption form { margin-top: 4px; }

/* Monatsansicht im Portal. Auf dem Telefon rollt sie in ihrem
   .tablewrap – sieben Spalten unter 400px zu quetschen ergibt
   Zellen, in denen keine Uhrzeit mehr lesbar ist. */
.kal { border-collapse: collapse; width: 100%; min-width: 620px; table-layout: fixed; }
.kal th { padding: 6px 4px; font-size: 11px; text-transform: uppercase; letter-spacing: .05em;
          color: var(--ink-soft); border-bottom: 1px solid var(--line); }
.kal td { border: 1px solid var(--line-soft); vertical-align: top; height: 78px; padding: 4px; }
.kal td.fremd { background: #fafbfd; }
.kal td.fremd .kal-tag { color: #b6bfcc; }
.kal td.heute { outline: 2px solid var(--brand); outline-offset: -2px; }
.kal td.belegt { background: #f3f8ff; }
.kal-tag { font-size: 11.5px; color: var(--ink-soft); margin-bottom: 3px; }
.kal-eintrag {
  display: block; margin-bottom: 3px; padding: 3px 5px; border-radius: 5px;
  background: var(--brand); color: #fff; text-decoration: none; font-size: 11px; line-height: 1.3;
}
.kal-eintrag:hover { background: var(--brand-dk); }
.kal-zeit { display: block; font-weight: 600; }
.kal-was  { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; opacity: .92; }

/* Mehrere Haken nebeneinander, die bei schmalem Fenster umbrechen.
   .check ist selbst ein Flexkasten – ohne Hülle stünde jeder Haken
   auf einer eigenen Zeile. */
.haken-reihe { display: flex; flex-wrap: wrap; gap: 8px 18px; }

/* Zumietanfrage: Firmen untereinander, ihre Ansprechpartner eingerückt
   darunter. Die Kontakte erscheinen erst, wenn die Firma angehakt ist –
   sonst wäre die Liste bei zwanzig Lieferanten eine Tapete. */
.zumiete-wen { display: flex; flex-direction: column; gap: 6px; }
.zumiete-firma > .check { font-weight: 500; }
.zumiete-kontakte { display: flex; flex-wrap: wrap; gap: 4px 16px;
                    margin: 4px 0 8px 24px; padding-left: 10px;
                    border-left: 2px solid var(--line-soft); }
.zumiete-kontakte .check { font-weight: 400; font-size: 13.5px; }

/* Postfach: eine Zeile je Nachricht, aufklappbar. Das Dreieck des
   Browsers reicht als Bedienelement – ein eigener Knopf daneben wäre
   eine zweite Stelle, an der dasselbe passiert. */
.postfach-mail { border: 1px solid var(--line); border-radius: 9px; margin-bottom: 7px;
                 background: var(--panel); }
.postfach-mail > summary { cursor: pointer; padding: 8px 11px; display: flex; gap: 10px;
                           align-items: baseline; flex-wrap: wrap; font-size: 13.5px; }
.postfach-mail > summary::-webkit-details-marker { display: none; }
.postfach-mail > summary::before { content: '▸'; color: var(--ink-soft); flex: 0 0 auto; }
.postfach-mail[open] > summary::before { content: '▾'; }
.postfach-mail[open] > summary { border-bottom: 1px solid var(--line-soft); }
.pf-zeit { color: var(--ink-soft); font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.pf-betreff { font-weight: 500; flex: 1 1 200px; }
.pf-inhalt { padding: 10px 12px 12px; }
.pf-text { white-space: pre-wrap; word-break: break-word; font: inherit; font-size: 13.5px;
           background: #f7f9fc; border-radius: 8px; padding: 10px 12px; margin: 8px 0 0; }

/* Dokumente am Artikel: eine Zeile je Datei, Knöpfe rechts daneben.
   Auf dem Telefon bricht die Zeile um, statt die Knöpfe aus dem Bild
   zu schieben. */
.idoc { display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
        padding: 8px 0; border-bottom: 1px solid var(--line-soft); font-size: 13.5px; }
.idoc:last-child { border-bottom: 0; }
.idoc-art { flex: 0 0 auto; font-size: 11.5px; padding: 2px 8px; border-radius: 999px;
            background: var(--line-soft); color: var(--ink-soft); }
.idoc-name { flex: 1 1 200px; font-weight: 500; overflow-wrap: anywhere; }
.idoc .inline-form { display: inline; }

/* Materialdokumente im Projekt und im Portal */
.mdoc-gruppe { margin-bottom: 14px; }
.mdoc-gruppe:last-child { margin-bottom: 0; }
.mdoc-art { font-size: 13px; font-weight: 600; margin: 0 0 5px; }
.mdoc-teil { margin-left: 18px; }

/* Kostentabelle: neun Spalten passen in keine Seitenspalte. Statt die
   Felder auf Pfeilbreite zu quetschen, bekommt die Tabelle eine
   Mindestbreite und rollt in ihrem .tablewrap. */
.kosten-t { min-width: 1080px; }
.kosten-t select, .kosten-t input[type="text"] { width: 100%; }
.kosten-t input[type="file"] { max-width: 100%; font-size: 12px; }

/* Deckungsbeitrag in der Seitenspalte: eine Zeile, anklickbar. */
.db-zeile {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 4px 10px; text-decoration: none; color: inherit;
  font-size: 16px; font-weight: 600;
  /* Umbrechen statt aus der Karte laufen: «Deckungsbeitrag» und ein
     langer Minusbetrag passen in einer schmalen Spalte nicht in eine
     Zeile. Die Zahl selbst bleibt zusammen. */
  flex-wrap: wrap;
}
.db-zeile:hover .db-wert { text-decoration: underline; }
.db-wert { color: var(--ok, #1f7a48); white-space: nowrap; margin-left: auto; }
.db-wert.db-minus { color: var(--err); }
.db-prozent { font-size: 12.5px; font-weight: 500; color: var(--ink-soft); margin-left: 4px; }

/* Übersichtsraster im Projektreiter */
.dispo { border-collapse: collapse; width: 100%; font-size: 12.5px; }
.dispo th, .dispo td { border: 1px solid var(--line-soft); padding: 6px 8px; text-align: center; }
.dispo th { background: #fafbfd; font-weight: 600; color: var(--ink-soft); white-space: nowrap; }
.dispo td.wer { text-align: left; white-space: nowrap; }
.dispo td.zeit { background: #eef3fb; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dispo td.frei { color: #c3cad6; }
.dispo .nacht { color: var(--brand-dk); }

/* Einsatzliste im Portal
   ----------------------
   Die Übersicht ist das erste, was ein Freelancer nach dem Anmelden
   sieht. Ein Einsatz ist dort kein Eintrag in einer Tabelle, sondern
   eine Fläche, die man ganz anfassen kann – auf dem Telefon mit dem
   Daumen, ohne einen Link von zwei Zeilen Höhe zu treffen. */
.einsatzliste { display: flex; flex-direction: column; }
.einsatzliste .einsatz {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 16px; border-top: 1px solid var(--line-soft);
  text-decoration: none; color: inherit;
}
.einsatzliste .einsatz:first-child { border-top: 0; }
.einsatzliste .einsatz:hover { background: #f6f9fe; }
.einsatzliste .einsatz:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.einsatz-haupt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.einsatz-haupt strong { font-size: 15px; overflow-wrap: anywhere; }
.einsatz-pfeil { margin-left: auto; font-size: 22px; line-height: 1; color: var(--ink-soft); flex: 0 0 auto; }
.einsatzliste.vorbei .einsatz { opacity: .62; }
.einsatzliste.vorbei .einsatz:hover { opacity: 1; }

/* Registerkarten der offenen Projekte
   -----------------------------------
   Eine Leiste am oberen Rand des Arbeitsbereichs, die zum Fenster
   gehört und nicht zum Projekt. Die Reiter innerhalb eines Projekts
   sind bewusst anders gebaut – flach, nur mit Unterstrich –, damit
   zwei Reihen übereinander nicht verwechselt werden.

   Die Leiste rollt waagerecht, wenn es eng wird, statt umzubrechen:
   auf dem Telefon wischt man durch die offenen Projekte. */
.ptabs { position: relative; border-bottom: 1px solid var(--line); background: #f1f4f9; }
.ptabs-liste {
  display: flex; align-items: flex-end; gap: 2px;
  padding: 6px 14px 0; overflow-x: auto; scrollbar-width: thin;
}
.ptabs-liste::-webkit-scrollbar { height: 6px; }
.ptabs-liste::-webkit-scrollbar-thumb { background: #cbd4e1; border-radius: 3px; }

.ptab {
  display: inline-flex; align-items: center; gap: 2px; flex: 0 0 auto;
  max-width: 260px; border: 1px solid var(--line); border-bottom: 0;
  border-radius: 8px 8px 0 0; background: #e6ebf3; color: var(--ink-soft);
  font-size: 12.5px; line-height: 1.2;
}
.ptab.on { background: #fff; color: var(--ink); box-shadow: 0 -1px 0 var(--brand) inset; }
.ptab:hover { background: #eef2f8; }
.ptab.on:hover { background: #fff; }

.ptab-link {
  display: flex; align-items: baseline; gap: 6px; min-width: 0;
  padding: 8px 4px 8px 11px; text-decoration: none; color: inherit;
}
.ptab-nr { font-variant-numeric: tabular-nums; color: var(--ink-soft); flex: 0 0 auto; }
.ptab.on .ptab-nr { color: var(--brand-dk, var(--brand)); }
.ptab-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.ptab-zu-form { display: flex; margin: 0; }
.ptab-zu {
  border: 0; background: none; cursor: pointer; color: var(--ink-soft);
  font-size: 15px; line-height: 1; padding: 6px 9px 7px 5px; border-radius: 6px;
}
.ptab-zu:hover { background: rgba(0,0,0,.08); color: var(--ink); }

.ptab-neu {
  border-style: dashed; background: transparent; cursor: pointer;
  padding: 8px 12px; color: var(--ink-soft); font: inherit; font-size: 12.5px;
  white-space: nowrap;
}
.ptab-neu:hover { background: #e9eef6; color: var(--ink); }
.ptab-plus { font-size: 14px; font-weight: 700; margin-right: 2px; }

/* Auswahlfeld unter der Leiste */
.ptabs-waehler {
  position: absolute; z-index: 30; right: 14px; left: 14px; top: 100%;
  max-width: 560px; margin-top: -1px;
  background: #fff; border: 1px solid var(--line); border-radius: 0 0 10px 10px;
  box-shadow: 0 10px 28px rgba(19,32,54,.16); padding: 10px;
}
.ptabs-suche {
  width: 100%; padding: 8px 10px; font: inherit; font-size: 13.5px;
  border: 1px solid var(--line); border-radius: 7px;
}
.ptabs-treffer { max-height: 320px; overflow-y: auto; margin-top: 8px; }
.ptabs-treffer-zeile {
  display: flex; align-items: baseline; gap: 8px;
  padding: 7px 8px; border-radius: 7px; text-decoration: none; color: inherit; font-size: 13px;
}
.ptabs-treffer-zeile:hover, .ptabs-treffer-zeile.an { background: #eef3fb; }
.ptabs-treffer-nr { font-variant-numeric: tabular-nums; color: var(--ink-soft); flex: 0 0 auto; }
.ptabs-treffer-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ptabs-treffer-status { margin-left: auto; color: var(--ink-soft); font-size: 12px; flex: 0 0 auto; }
.ptabs-leer { margin: 6px 8px; font-size: 13px; color: var(--ink-soft); }

@media (max-width: 700px) {
  .ptab { max-width: 180px; }
  .ptabs-waehler { right: 8px; left: 8px; }
}

/* ------------------------------------------------------------------
   Projekt-Ampel

   Eine Zeile unter der Überschrift, die sagt, was noch klemmt. Jeder
   Punkt ist ein Knopf, der in den passenden Reiter springt – eine
   Meldung ohne Weg dorthin ist nur Lärm.
   ------------------------------------------------------------------ */
.ampel { display: flex; flex-wrap: wrap; gap: 7px; margin: 0 0 18px; align-items: center; }
.ampel-punkt {
  font: inherit; font-size: 12.5px; line-height: 1.2;
  padding: 5px 11px; border-radius: 999px; border: 1px solid transparent;
  cursor: pointer; text-align: left;
}
button.ampel-punkt:hover { filter: brightness(.97); }
.ampel-ok   { background: var(--ok-bg);   color: var(--ok);       border-color: #bfe3d0; cursor: default; }
.ampel-info { background: #eef2f8;        color: var(--ink-soft); border-color: var(--line); }
.ampel-warn { background: var(--warn-bg); color: var(--warn);     border-color: #f0dcae; }
.ampel-err  { background: var(--err-bg);  color: var(--err);      border-color: #f3c8c4; }
.small.err  { color: var(--err); }

/* ==================================================================
   Projektkalender (Reiter «Zeitplan»)

   Alles hängt unter .pk. Das ist kein Schmuck, sondern nötig: Klassen
   wie .legende und .karte sind in dieser Datei schon anders belegt,
   und der Kalender bringt seine eigenen Farbvariablen mit. Unter .pk
   stören sich die beiden Welten nicht.
   ================================================================== */
.pk {
    --bg:#f4f6f9; --panel:#fff; --ink:#1c2430; --ink-soft:#5d6b7d;
    --line:#dfe4ec; --line-soft:#edf0f5; --brand:#2d6cdf; --brand-dk:#1f52b0;
    --err:#c0392b;

    /* Zustandsbänder – Fläche hell, Schrift dunkel, Kontrast 6:1 aufwärts.
       Die Zahl im Band trägt die Aussage auch ohne Farbe. */
    --frei-fl:#d7efe1;  --frei-ink:#14603a;  --frei-kante:#a9d9c1;
    --knapp-fl:#fbeaba; --knapp-ink:#7a4f00; --knapp-kante:#e8cf8a;
    --weg-fl:#fadedb;   --weg-ink:#96271b;   --weg-kante:#f0b8b1;
    --miete-fl:#dcf3e9; --miete-ink:#0e6b49; --miete-kante:#1baf7a;

    /* Personal */
    --crew-fl:#dde5f8;  --crew-ink:#23408a;  --crew-kante:#bccdf0;
    --crew-offen:#eef2fa;

    /* Projektphasen. Lager (Prep/De-Prep) ist blau, Arbeit vor Ort
       (Aufbau/Abbau) warm, die Durchführung trägt als einzige eine
       Vollfläche – sie ist der Tag, um den es geht. */
    --ph-vor:#e3e8f2;    --ph-prep:#cfe0fa;   --ph-durch:#2d6cdf;
    --ph-deprep:#cfe0fa; --ph-nach:#e3e8f2;
    --ph-aufbau:#fae0c6; --ph-abbau:#eedfcd;  --ph-eigen:#e8ecf3;
    --radius:8px; --shadow:0 1px 2px rgba(20,30,45,.06), 0 2px 8px rgba(20,30,45,.05);
    --namen:216px;
  }
.pk .karte { background:var(--panel); border:1px solid var(--line);
           border-radius:var(--radius); box-shadow:var(--shadow); margin:0 0 14px }
.pk .kopf { display:flex; align-items:center; gap:12px; flex-wrap:wrap;
          padding:10px 14px; border-bottom:1px solid var(--line) }
.pk .kopf strong { font-size:14px }
.pk .kopf .leise { color:var(--ink-soft); font-size:12.5px }
.pk .rechts { margin-left:auto; display:flex; align-items:center; gap:10px; flex-wrap:wrap }
.pk .schalter { display:flex; border:1px solid var(--line); border-radius:7px; overflow:hidden }
.pk .schalter button { padding:5px 12px; font:inherit; font-size:12px; color:var(--ink-soft);
                     background:#fff; border:0; border-left:1px solid var(--line); cursor:pointer }
.pk .schalter button:first-child { border-left:0 }
.pk .schalter button.an { background:var(--brand); color:#fff; font-weight:600 }
.pk .kn { padding:5px 11px; font:inherit; font-size:12px; background:#fff; cursor:pointer;
        border:1px solid var(--line); border-radius:7px; color:var(--ink-soft) }
.pk .kn:hover { background:#f2f6fd; color:var(--ink) }
.pk .haken { display:inline-flex; align-items:center; gap:7px; font-size:12.5px;
           color:var(--ink-soft); cursor:pointer; user-select:none }
.pk .haken input { position:absolute; opacity:0; pointer-events:none }
.pk .haken .kaestchen { width:15px; height:15px; border:1.5px solid #b9c2d0; border-radius:4px;
                      display:inline-block; position:relative; background:#fff; flex:0 0 auto }
.pk .haken input:checked + .kaestchen { background:var(--brand); border-color:var(--brand) }
.pk .haken input:checked + .kaestchen::after { content:"✓"; position:absolute; left:2px; top:-3px;
                      color:#fff; font-size:11px }
.pk .haken input:focus-visible + .kaestchen { outline:2px solid var(--brand); outline-offset:2px }
.pk .ueber { padding:0 }
.pk .ueber-raster { display:grid; grid-template-columns:var(--namen) 1fr }
.pk .ueber-namen { padding:10px 14px; border-right:1px solid var(--line-soft) }
.pk .ueber-namen b { display:block; font-size:12.5px }
.pk .ueber-namen span { font-size:11px; color:var(--ink-soft) }
.pk .ueber-feld { position:relative; padding:10px 14px 8px; overflow:hidden;
                cursor:grab; user-select:none }
.pk .ueber-feld.zieht { cursor:grabbing }
.pk .monate { position:relative; height:16px; margin-bottom:5px }
.pk .monat { position:absolute; top:0; font-size:10.5px; color:var(--ink-soft);
           border-left:1px solid var(--line); padding-left:5px; height:16px; white-space:nowrap }
.pk .phasenspur { position:relative; height:24px; margin-bottom:7px }
.pk .phase { position:absolute; top:0; height:24px; border-radius:5px; display:flex;
           align-items:center; justify-content:center; font-size:10.5px; overflow:hidden;
           white-space:nowrap; padding:0 6px; border:1px solid rgba(0,0,0,.06) }
.pk .ph-vor { background:var(--ph-vor);    color:#44506a }
.pk .ph-prep { background:var(--ph-prep);   color:var(--brand-dk) }
.pk .ph-durch { background:var(--ph-durch);  color:#fff; font-weight:600 }
.pk .ph-deprep { background:var(--ph-deprep); color:var(--brand-dk) }
.pk .ph-nach { background:var(--ph-nach);   color:#44506a }
.pk .ph-aufbau { background:var(--ph-aufbau); color:#73400f }
.pk .ph-abbau { background:var(--ph-abbau);  color:#5c4534 }
.pk .ph-eigen { background:var(--ph-eigen);  color:#44506a }
.pk .meilenspur { position:relative; height:30px }
.pk .meilen { position:absolute; top:0; transform:translateX(-50%); text-align:center; width:0 }
.pk .meilen .raute { width:11px; height:11px; background:#fff; border:2px solid var(--brand-dk);
                   transform:rotate(45deg); margin:0 auto 2px; border-radius:2px }
.pk .meilen.wichtig .raute { background:var(--brand-dk) }
.pk .meilen .txt { font-size:9.5px; color:var(--ink-soft); white-space:nowrap;
                 transform:translateX(-50%); display:inline-block; margin-left:0 }
.pk .meilen .linie { position:absolute; left:0; top:11px; width:1px; height:0; background:#cbd5e6 }
.pk .fenster { position:absolute; top:8px; bottom:6px; background:rgba(45,108,223,.13);
             border:1.5px solid rgba(45,108,223,.55); border-radius:6px; cursor:grab;
             box-shadow:0 1px 6px rgba(45,108,223,.18) }
.pk .fenster:active { cursor:grabbing }
.pk .fenster::before, .pk .fenster::after {
    content:""; position:absolute; top:50%; width:3px; height:20px; margin-top:-10px;
    background:rgba(45,108,223,.5); border-radius:2px }
.pk .fenster::before { left:-1px }
.pk .fenster::after { right:-1px }
.pk .heute-linie { position:absolute; top:4px; bottom:4px; width:2px;
                 background:var(--err); opacity:.5; pointer-events:none }
.pk .detail { display:grid; grid-template-columns:var(--namen) 1fr; position:relative }
.pk .d-namen { border-right:1px solid var(--line); background:#fff; z-index:2 }
.pk .d-scroll { overflow-x:auto; overflow-y:hidden; scrollbar-width:thin }
.pk .d-inhalt { position:relative }
.pk .z { height:38px; display:flex; align-items:center; border-bottom:1px solid var(--line-soft) }
.pk .z.kopfz { height:46px; border-bottom:1px solid var(--line); background:#fafbfd }
.pk .z.gruppe { height:28px; background:#f6f8fb; border-bottom:1px solid var(--line-soft) }
.pk .d-namen .z { padding:0 12px; gap:7px }
.pk .d-namen .z.gruppe { font-size:10.5px; text-transform:uppercase; letter-spacing:.05em;
                       color:var(--ink-soft); font-weight:600 }
.pk .d-namen .txt { min-width:0; overflow:hidden }
.pk .d-namen .txt b { display:block; font-size:12.5px; font-weight:600; line-height:1.25;
                    overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
/* Die Unterzeile muss in einer Zeile bleiben. Eine Zeile mit «2 gebraucht ·
   4 im Bestand · 2 zugemietet» bricht sonst um, und weil die Zeilenhöhe
   fest ist (die Balken daneben müssen ja auf gleicher Höhe liegen),
   liefe sie in die nächste Zeile hinein. */
.pk .d-namen .txt span { display:block; font-size:10.5px; color:var(--ink-soft);
                       overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.pk .tagzelle { position:absolute; top:0; bottom:0; border-left:1px solid var(--line-soft) }
.pk .tagzelle.we { background:#f5f7fb }
.pk .tagkopf { position:absolute; top:0; text-align:center; padding-top:5px; font-size:10.5px }
.pk .tagkopf .wt { display:block; color:var(--ink-soft); font-size:9.5px }
.pk .tagkopf .dz { display:block; font-variant-numeric:tabular-nums; font-size:11.5px }
.pk .tagkopf .mo { display:block; font-size:9px; color:var(--ink-soft) }
.pk .tagkopf.heute .dz { color:var(--err); font-weight:700 }
.pk .balken { position:absolute; height:24px; top:7px; border-radius:5px; display:flex;
            align-items:center; justify-content:center; font-size:11px; font-weight:600;
            font-variant-numeric:tabular-nums; border:1px solid; overflow:hidden;
            white-space:nowrap; padding:0 5px }
.pk .b-frei { background:var(--frei-fl);  color:var(--frei-ink);  border-color:var(--frei-kante) }
.pk .b-knapp { background:var(--knapp-fl); color:var(--knapp-ink); border-color:var(--knapp-kante) }
.pk .b-weg { background:var(--weg-fl);   color:var(--weg-ink);   border-color:var(--weg-kante) }
.pk .b-miete { background:var(--miete-fl); color:var(--miete-ink); border-color:var(--miete-kante) }
.pk .b-crew { background:var(--crew-fl);  color:var(--crew-ink);  border-color:var(--crew-kante) }
.pk .b-offen { background:repeating-linear-gradient(135deg,#e3eafa 0 5px,#f2f5fc 5px 10px);
             color:#3c4c6d; border-color:#c9d6ef; border-style:dashed }
.pk .balken:hover { filter:brightness(.97) }
.pk .etikett { position:absolute; transform:translateX(-50%); white-space:nowrap;
             pointer-events:none }
.pk .meilen.e1 .txt { margin-top:0 }
.pk .meilen.e2 .txt { margin-top:20px }
.pk .meilen.e3 .txt { margin-top:40px }
.pk .meilenspur { height:72px }
.pk .phasenschatten { position:absolute; top:0; bottom:0; background:rgba(45,108,223,.05);
                    border-left:1px solid rgba(45,108,223,.18);
                    border-right:1px solid rgba(45,108,223,.18); pointer-events:none }
.pk .meilen-d { position:absolute; top:0; bottom:0; width:0; pointer-events:none }
.pk .meilen-d i { position:absolute; top:0; bottom:0; left:-1px; width:2px;
                background:repeating-linear-gradient(180deg,#8fa6cc 0 4px,transparent 4px 8px) }
.pk .heute-d { position:absolute; top:0; bottom:0; width:2px; background:var(--err); opacity:.45 }
.pk .hinweis { position:fixed; z-index:40; background:#fff; border:1px solid var(--line);
             border-radius:8px; box-shadow:0 10px 26px rgba(19,32,54,.2); padding:9px 11px;
             font-size:12px; max-width:250px; pointer-events:none; display:none }
.pk .hinweis h4 { margin:0 0 5px; font-size:12.5px }
.pk .hinweis dl { display:grid; grid-template-columns:auto auto; gap:1px 10px; margin:0 }
.pk .hinweis dt { color:var(--ink-soft) }
.pk .hinweis dd { margin:0; text-align:right; font-variant-numeric:tabular-nums }
.pk .legende { display:flex; flex-wrap:wrap; gap:14px; padding:9px 14px;
             border-top:1px solid var(--line); font-size:11.5px; color:var(--ink-soft) }
.pk .legende span { display:flex; align-items:center; gap:6px }
.pk .muster { width:20px; height:12px; border-radius:3px; border:1px solid; flex:0 0 auto }
.pk .fuss { font-size:12px; color:var(--ink-soft); margin:14px 2px 0 }
@media (max-width:760px){ .pk { --namen:150px } }

@media (max-width: 900px) {
  .pk { --namen: 150px; }
  .pk .kopf { gap: 8px; }
  .pk .rechts { width: 100%; margin-left: 0; }
}

/* ==================================================================
   Assistent – die Sprechblase unten rechts

   Liegt über allem, nimmt aber nur ihre eigene Ecke ein. Geschlossen
   ist sie ein Knopf; offen ein Fenster, das auf dem Telefon die ganze
   Breite bekommt, weil 380 Pixel dort keine sind.
   ================================================================== */
.as { position: fixed; right: 18px; bottom: 18px; z-index: 60;
      display: flex; flex-direction: column; align-items: flex-end; gap: 10px; }

.as-blase {
  width: 52px; height: 52px; border-radius: 50%; border: 0; cursor: pointer;
  background: var(--brand); color: #fff;
  box-shadow: 0 4px 14px rgba(20,30,45,.22), 0 1px 3px rgba(20,30,45,.16);
  display: flex; align-items: center; justify-content: center;
  transition: transform .12s, background .12s;
}
.as-blase:hover { background: var(--brand-dk); transform: translateY(-1px); }
.as-blase:focus-visible { outline: 3px solid #9dbcf5; outline-offset: 2px; }
.as.offen .as-blase { display: none; }

.as-fenster {
  width: 380px; max-width: calc(100vw - 32px);
  height: 560px; max-height: calc(100vh - 100px);
  background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
  box-shadow: 0 12px 34px rgba(19,32,54,.20), 0 2px 8px rgba(19,32,54,.10);
  display: flex; flex-direction: column; overflow: hidden;
}

.as-kopf { flex: 0 0 auto; display: flex; align-items: center; gap: 10px;
           padding: 11px 12px 11px 15px; border-bottom: 1px solid var(--line-soft); }
.as-kopf strong { font-size: 14px; }
.as-leise { font-size: 11.5px; color: var(--ink-soft); margin-left: auto;
            font-variant-numeric: tabular-nums; }
.as-klein { border: 0; background: none; font: inherit; font-size: 12.5px;
            color: var(--ink-soft); cursor: pointer; padding: 3px 6px; border-radius: 6px; }
.as-klein:hover { background: var(--line-soft); color: var(--ink); }
.as-kopf .as-klein:last-child { font-size: 19px; line-height: 1; padding: 0 6px 2px; }

/* min-height:0 ist hier kein Schmuck: Ein Flex-Element hat von Haus aus
   min-height:auto und schrumpft deshalb nicht unter seinen Inhalt. Ohne
   diese Zeile rollt die Liste nicht, sondern wächst aus dem Fenster
   heraus – und die Eingabezeile liegt dann über den letzten Karten. */
.as-lauf { flex: 1; min-height: 0; overflow-y: auto; padding: 14px; display: flex;
           flex-direction: column; gap: 10px; scrollbar-width: thin; }

/* Und hier dasselbe Thema von der anderen Seite: Die Liste ist ein
   Flex-Container, ihre Kinder sind Flex-Elemente – und die dürfen von
   sich aus schrumpfen, wenn der Platz knapp wird. Bei Textblasen fällt
   das nicht auf, die gehen nicht unter ihren Inhalt. Die Vorschlagskarte
   hat aber overflow:hidden, und damit ist ihre Mindesthöhe null: sie
   wurde auf zwei Pixel zusammengedrückt, ihr Inhalt lag unsichtbar
   darunter, und der Knopf «Anlegen» war nicht erreichbar. */
.as-lauf > * { flex: 0 0 auto; }
.as-hinweis { font-size: 13px; color: var(--ink-soft); background: #f6f8fb;
              border-radius: 10px; padding: 11px 13px; }

.as-m { max-width: 86%; padding: 9px 12px; border-radius: 12px; font-size: 14px;
        line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; }
.as-m-user { align-self: flex-end; background: var(--brand); color: #fff;
             border-bottom-right-radius: 4px; }
.as-m-bot  { align-self: flex-start; background: #f2f5f9; color: var(--ink);
             border-bottom-left-radius: 4px; }
.as-m-fehler { align-self: flex-start; background: var(--err-bg); color: var(--err);
               border: 1px solid #f3c8c4; }

/* Wartezeichen: drei Punkte, die nacheinander heller werden. */
.as-wartet { align-self: flex-start; display: flex; gap: 4px; padding: 12px 13px; }
.as-wartet i { width: 7px; height: 7px; border-radius: 50%; background: #b9c4d2;
               animation: as-tupf 1.1s infinite ease-in-out; }
.as-wartet i:nth-child(2) { animation-delay: .16s; }
.as-wartet i:nth-child(3) { animation-delay: .32s; }
@keyframes as-tupf { 0%, 70%, 100% { opacity: .35 } 35% { opacity: 1 } }
@media (prefers-reduced-motion: reduce) { .as-wartet i { animation: none; opacity: .6 } }

/* Vorschlagskarte: das, was der Mensch liest, bevor er zustimmt. */
.as-karte { align-self: stretch; border: 1px solid var(--line); border-radius: 11px;
            background: #fff; overflow: hidden; }
.as-karte-kopf { padding: 9px 12px; background: #f7f9fc; font-size: 13px; font-weight: 600;
                 border-bottom: 1px solid var(--line-soft); }
.as-karte dl { display: grid; grid-template-columns: auto 1fr; gap: 3px 10px;
               margin: 0; padding: 10px 12px; font-size: 13px; }
.as-karte dt { color: var(--ink-soft); }
.as-karte dd { margin: 0; overflow-wrap: anywhere; }
.as-karte-fuss { display: flex; gap: 8px; padding: 0 12px 11px; }
.as-karte-fuss .btn { font-size: 13px; padding: 6px 12px; }
.as-karte-ergebnis { padding: 9px 12px; font-size: 13px; border-top: 1px solid var(--line-soft); }
.as-karte-ergebnis.ok { background: var(--ok-bg); color: var(--ok); }
.as-karte-ergebnis.weg { background: #f6f8fb; color: var(--ink-soft); }

.as-fuss { flex: 0 0 auto; display: flex; gap: 8px; align-items: flex-end;
           padding: 10px 12px; border-top: 1px solid var(--line-soft); }
/* Die Mindesthöhe von 92px weiter oben gilt für Formularfelder, in die
   man Absätze schreibt. Hier ist eine Zeile der Normalfall; grösser
   wird das Feld beim Tippen von selbst. */
.as-fuss textarea {
  flex: 1; resize: none; min-height: 0; height: 38px; max-height: 120px;
  padding: 8px 11px; font: inherit; font-size: 14px; line-height: 1.4;
  border: 1px solid var(--line); border-radius: 10px; background: #fff; color: inherit;
}
.as-fuss textarea:focus { outline: 2px solid var(--brand); outline-offset: -1px; border-color: var(--brand); }
.as-senden { flex: 0 0 auto; width: 38px; height: 38px; border: 0; border-radius: 10px;
             background: var(--brand); color: #fff; cursor: pointer;
             display: flex; align-items: center; justify-content: center; }
.as-senden:hover { background: var(--brand-dk); }
.as-senden:disabled { background: #b9c4d2; cursor: default; }

@media (max-width: 560px) {
  .as { right: 12px; bottom: 12px; left: 12px; align-items: stretch; }
  .as-blase { align-self: flex-end; }
  .as-fenster { width: 100%; height: calc(100vh - 90px); }
}

@media print { .as { display: none } }

/* ==================================================================
   Dispo – die Zeitleiste im Register «Unterlagen/Dispo»
   ==================================================================
   Ein Gitter aus einer Namensspalte und einer Spalte je Tag. Die
   Blöcke liegen absolut in der Zelle ihres ersten Tages und ziehen
   sich über die Breite ihrer Dauer – so braucht kein Balken eine
   eigene Zelle und das Gitter bleibt ein Gitter.

   Die Namensspalte klebt links, damit man beim Schieben nach rechts
   noch weiss, wessen Zeile man liest.                                */

.dispo { --dspalte: 46px; --dnamen: 220px; }
.dispo-rollen { overflow-x: auto; }
.dispo-gitter { min-width: max-content; }

.dz { --dspuren: 1;
      display: grid; grid-template-columns: var(--dnamen) repeat(var(--dsp), var(--dspalte));
      border-bottom: 1px solid var(--line-soft);
      min-height: calc(var(--dspuren) * 42px + 10px); }
.dz:last-child { border-bottom: 0; }
.dz-kopf { position: sticky; top: 0; z-index: 3; background: #fbfcfe;
           border-bottom: 1px solid var(--line); min-height: 0; }
.dz-tag { font-size: 11px; text-align: center; padding: 5px 0; line-height: 1.25;
          border-left: 1px solid var(--line-soft); color: var(--ink-soft); }
.dz-tag b { display: block; font-size: 11.5px; color: var(--ink); }
.dz-tag.we { background: #f1f4f8; }
.dz-tag.heute { background: #e8f0fd; color: var(--brand-dk); }
.dz-tag.heute b { color: var(--brand-dk); }
.dz-ecke { font-size: 12px; font-weight: 600; color: var(--ink-soft);
           display: flex; align-items: flex-end; }

.dz-band { grid-column: 1 / -1; padding: 6px 12px; background: #f1f4f8;
           border-top: 1px solid var(--line); border-bottom: 1px solid var(--line-soft);
           font-size: 12px; font-weight: 600; color: var(--ink-soft);
           letter-spacing: .02em; text-transform: uppercase; }

.dz-name { padding: 7px 12px; border-right: 1px solid var(--line); background: #fff;
           position: sticky; left: 0; z-index: 2;
           display: flex; flex-direction: column; justify-content: center; gap: 1px; }
.dz-name b { font-size: 13.5px; font-weight: 600; }
.dz-name span { font-size: 11.5px; color: var(--ink-soft); }
.dz-offen .dz-name { background: #fffaf9; }
.dz:hover .dz-name { background: #f8fafc; }
.dz-offen:hover .dz-name { background: #fff5f3; }

.dz-zelle { border-left: 1px solid var(--line-soft); position: relative; }
.dz-zelle.we { background: #f7f9fc; }
.dz-zelle.heute { background: #f0f6ff; }

.dblock { --dspur: 0;
          position: absolute; left: 2px; border-radius: 5px;
          top: calc(6px + var(--dspur) * 42px); height: 38px;
          padding: 2px 7px; font: inherit; font-size: 11.5px; line-height: 1.3;
          text-align: left; text-decoration: none; overflow: hidden; cursor: pointer;
          border: 1px solid; display: flex; flex-direction: column; justify-content: center;
          z-index: 1; }
.dblock:hover { filter: brightness(.97); text-decoration: none; }
.dblock b { font-weight: 600; display: block;
            white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dblock > span { display: block; font-size: 10.5px; opacity: .85;
                 white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dkz { font-weight: 700; font-size: 10px; letter-spacing: .04em; }

.b-besetzt   { background: var(--ok-bg);   border-color: #9ed4b9; color: #12603a; }
.b-angefragt { background: var(--warn-bg); border-color: #e3c789; color: #7a5000; }
.b-offen     { background: var(--err-bg);  border-color: #efb1aa; color: #98291d; }
.b-abgesagt  { background: #f2f3f5; border-color: #d8dce3; color: #79828f;
               text-decoration: line-through; }
.b-extern    { background: #eef1f6; border-color: #cdd5e2; color: #3c4858; }
.b-fremd     { background: #eaf0fb; border-color: #bed0ee; color: #2b4a80; }
.b-gesperrt  { background: repeating-linear-gradient(45deg,#f0f2f6,#f0f2f6 5px,#e4e8ef 5px,#e4e8ef 10px);
               border-color: #d3d9e3; color: #5d6b7d; }
.kollision   { outline: 2px solid var(--err); outline-offset: -2px; }

.dispo-legende { display: flex; flex-wrap: wrap; gap: 14px; padding: 10px 14px;
                 border-top: 1px solid var(--line-soft); background: #fbfcfe;
                 font-size: 12px; color: var(--ink-soft); }
.dispo-legende i { display: inline-block; width: 14px; height: 14px; border-radius: 3px;
                   border: 1px solid; vertical-align: -3px; margin-right: 5px; }
.dispo-legende .trenn { border-left: 1px solid var(--line); padding-left: 14px; }

/* Vorschlagsliste */
.dispo-dialog { position: fixed; inset: 0; z-index: 60; background: rgba(20,30,45,.35);
                display: flex; align-items: center; justify-content: center; padding: 20px; }
.dispo-dialog[hidden] { display: none; }
.dispo-dialog-kasten { background: #fff; border-radius: 10px; width: 100%; max-width: 660px;
                       max-height: 85vh; display: flex; flex-direction: column;
                       box-shadow: 0 10px 40px rgba(20,30,45,.25); position: relative; }
.dispo-dialog-kasten h3 { margin: 0; padding: 13px 46px 13px 16px; font-size: 15px;
                          border-bottom: 1px solid var(--line-soft); background: #fbfcfe;
                          border-radius: 10px 10px 0 0; }
.dispo-dialog-zu { position: absolute; top: 8px; right: 10px; border: 0; background: none;
                   font-size: 22px; line-height: 1; cursor: pointer; color: var(--ink-soft); }
.dispo-dialog-inhalt { overflow-y: auto; min-height: 0; }
.dispo-vorschlaege { display: flex; flex-direction: column; }
.dispo-vorschlag { display: flex; align-items: center; gap: 12px; padding: 9px 16px;
                   border-bottom: 1px solid var(--line-soft); cursor: pointer; }
.dispo-vorschlag:hover { background: #f8fafc; }
.dispo-vorschlag .wer { flex: 1; min-width: 0; }
.dispo-vorschlag .wer b { display: block; font-size: 14px; }
.dispo-vorschlag .wer span { font-size: 12px; color: var(--ink-soft); }
.marke { font-size: 11px; padding: 2px 8px; border-radius: 99px; border: 1px solid; white-space: nowrap; }
.m-frei   { background: var(--ok-bg);   border-color: #9ed4b9; color: #12603a; }
.m-belegt { background: var(--err-bg);  border-color: #efb1aa; color: #98291d; }
.m-unklar { background: var(--warn-bg); border-color: #e3c789; color: #7a5000; }
.dispo-dialog-fuss { padding: 12px 16px; border-top: 1px solid var(--line-soft);
                     background: #fbfcfe; border-radius: 0 0 10px 10px; }
.dispo-dialog-fuss .hint { display: block; margin-top: 6px; }

@media (max-width: 720px) { .dispo { --dnamen: 150px; --dspalte: 40px; } }
@media print {
  .dispo-rollen { overflow: visible; }
  .dispo-dialog { display: none; }
}

/* Abwesenheit im Portal-Kalender: gestreift, damit sie sich von einer
   Buchung unterscheidet, auch wenn man Farben schlecht trennt. */
.kal td.abwesend { background: repeating-linear-gradient(45deg,#f6f7fa,#f6f7fa 6px,#eceff4 6px,#eceff4 12px); }
.kal-abwesend { display: block; font-size: 11px; color: var(--ink-soft);
                border: 1px dashed #c8cfda; border-radius: 4px; padding: 1px 5px;
                margin-top: 3px; background: #fff; }
.dispo-abwesende { border-top: 1px solid var(--line-soft); }
.dispo-abwesende > summary { padding: 9px 16px; font-size: 12.5px; color: var(--ink-soft);
                             cursor: pointer; background: #fbfcfe; }
.dispo-abwesende > summary:hover { color: var(--ink); }
.dispo-gruppe { padding: 7px 16px 5px; font-size: 11.5px; font-weight: 600;
                color: var(--ink-soft); text-transform: uppercase; letter-spacing: .02em;
                background: #f6f8fb; border-bottom: 1px solid var(--line-soft); }

/* Ansicht aus der Verwaltung: ein Band, das man nicht übersehen kann.
   Wer als jemand anderes im Portal steht, soll das jede Sekunde sehen –
   sonst hält er den fremden Kalender für den eigenen. */
.ansicht-band { background: #1b2534; color: #e6ebf3; font-size: 13px;
                border-bottom: 2px solid var(--warn); }
.ansicht-band .portal-innen { display: flex; align-items: center; gap: 12px;
                              flex-wrap: wrap; padding: 8px 0; }
.ansicht-band strong { color: #ffd27a; }
.ansicht-band span { color: #aebbcd; flex: 1; min-width: 200px; }
.ansicht-band .btn { background: #fff; border-color: #fff; color: #1b2534; }
.ansicht-band .btn:hover { background: #e8edf5; }
@media print { .ansicht-band { display: none } }

/* ==================================================================
   Übersichtsseite
   ==================================================================
   Kacheln unterschiedlicher Breite in einem Zwölferraster. Hell wie
   der Rest der Anwendung – ein dunkles Dashboard vor einer hellen
   Anwendung sieht aus wie ein fremdes Programm.                      */

.ub-kopf { margin: 2px 0 20px; }
.ub-datum { font-size: 12.5px; color: var(--ink-soft); letter-spacing: .02em; }
.ub-gruss { font-size: 27px; font-weight: 700; letter-spacing: -.02em;
            margin: 4px 0 6px; color: var(--ink); }
.ub-lage { font-size: 15px; color: var(--ink-soft); margin: 0; max-width: 680px; line-height: 1.5; }

.ub-bento { display: grid; grid-template-columns: repeat(12, 1fr); gap: 14px; margin-bottom: 22px; }
.ub-kachel { grid-column: span 4; background: var(--panel); border: 1px solid var(--line);
             border-radius: var(--radius); box-shadow: var(--shadow); padding: 16px 18px;
             display: flex; flex-direction: column; color: inherit; text-decoration: none;
             min-height: 150px; transition: border-color .15s ease, box-shadow .15s ease; }
a.ub-kachel:hover { border-color: #c6d2e4; box-shadow: 0 2px 10px rgba(20,30,45,.09);
                    text-decoration: none; }
.ub-kachel.k3 { grid-column: span 3; }
.ub-kachel.k4 { grid-column: span 4; }
.ub-kachel.k5 { grid-column: span 5; }
.ub-kachel.k7 { grid-column: span 7; }
@media (max-width: 1100px) { .ub-kachel, .ub-kachel.k3, .ub-kachel.k4,
                             .ub-kachel.k5, .ub-kachel.k7 { grid-column: span 6; } }
@media (max-width: 680px)  { .ub-kachel, .ub-kachel.k3, .ub-kachel.k4,
                             .ub-kachel.k5, .ub-kachel.k7 { grid-column: span 12; } }

.ub-label { font-size: 12.5px; font-weight: 600; color: var(--ink-soft); }
.ub-zahl { font-size: 34px; font-weight: 700; letter-spacing: -.02em; line-height: 1.15;
           font-variant-numeric: tabular-nums; color: var(--ink); margin-top: 2px; }
.ub-zahl small { font-size: 14px; font-weight: 500; color: var(--ink-soft); margin-left: 7px; }
.ub-fuss { font-size: 11.5px; color: var(--ink-soft); margin-top: auto; padding-top: 8px; }
.ub-warn { color: var(--warn); font-weight: 600; }
.ub-leer { font-size: 13px; color: var(--ink-soft); margin: 10px 0 0; }

.ub-kurve { justify-content: space-between; }
.ub-spark { width: 100%; height: 58px; display: block; margin: 8px 0 0; }

.ub-ring { align-items: center; text-align: center; }
.ub-ring .ub-label { align-self: flex-start; }
.ub-ring-wrap { position: relative; width: 104px; height: 104px; margin: 6px 0 2px; }
.ub-ring-svg { width: 104px; height: 104px; display: block; }
.ub-ring-zahl { position: absolute; inset: 0; display: flex; align-items: center;
                justify-content: center; font-size: 23px; font-weight: 700;
                font-variant-numeric: tabular-nums; color: var(--ink); }
.ub-ring-zahl span { font-size: 13px; color: var(--ink-soft); margin-left: 1px; }
.ub-ring .ub-fuss { text-align: center; }

.ub-liste { list-style: none; margin: 10px 0 0; padding: 0; }
.ub-liste li + li { border-top: 1px solid var(--line-soft); }
.ub-liste a { display: flex; align-items: center; gap: 12px; padding: 8px 0;
              color: inherit; text-decoration: none; }
.ub-liste a:hover { text-decoration: none; }
.ub-liste a:hover .ub-was b { color: var(--brand); }
.ub-wann { flex: 0 0 84px; display: flex; flex-direction: column; }
.ub-wann b { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.ub-wann i { font-size: 11px; color: var(--ink-soft); font-style: normal; }
.ub-was { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ub-was b { font-size: 13.5px; font-weight: 600; white-space: nowrap;
            overflow: hidden; text-overflow: ellipsis; }
.ub-was i { font-size: 11.5px; color: var(--ink-soft); font-style: normal;
            white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ub-liste-schmal { margin-top: 12px; }
.ub-marke { font-size: 11px; padding: 2px 8px; border-radius: 99px; white-space: nowrap;
            border: 1px solid; }
.ub-marke.m-blau { background: #e8f0fd; border-color: #bcd2f5; color: var(--brand-dk); }
.ub-marke.m-grau { background: #f1f4f8; border-color: var(--line); color: var(--ink-soft); }
.ub-marke.m-gelb { background: var(--warn-bg); border-color: #e3c789; color: var(--warn); }

.ub-abschnitt { display: flex; align-items: baseline; justify-content: space-between;
                gap: 12px; margin: 26px 0 10px; }
.ub-abschnitt h2 { font-size: 18px; font-weight: 700; letter-spacing: -.01em; margin: 0; }
.ub-mehr { font-size: 13px; font-weight: 600; }

.ub-reiter { display: flex; gap: 4px; background: var(--panel); border: 1px solid var(--line);
             border-radius: 10px; padding: 4px; margin-bottom: 12px; width: fit-content;
             max-width: 100%; overflow-x: auto; }
.ub-reiter button { border: 0; background: none; font: inherit; font-size: 13px;
                    font-weight: 600; color: var(--ink-soft); padding: 7px 14px;
                    border-radius: 7px; cursor: pointer; white-space: nowrap; }
.ub-reiter button:hover { color: var(--ink); }
.ub-reiter button.on { background: var(--brand); color: #fff; }

.ub-balken { display: block; width: 100%; height: 6px; border-radius: 3px;
             background: var(--line-soft); overflow: hidden; }
.ub-balken-fuell { display: block; height: 100%; border-radius: 3px; background: var(--brand); }
.ub-tabelle td { vertical-align: middle; }
.ub-offen { white-space: nowrap; }

.ub-knapp { display: block; padding: 9px 0; color: inherit; text-decoration: none;
            border-bottom: 1px solid var(--line-soft); }
.ub-knapp:last-child { border-bottom: 0; }
.ub-knapp:hover { text-decoration: none; }
.ub-knapp:hover b { color: var(--brand); }
.ub-knapp-kopf { display: flex; align-items: baseline; justify-content: space-between;
                 gap: 10px; margin-bottom: 5px; }
.ub-knapp-kopf b { font-size: 13px; font-weight: 600; }
.ub-knapp-kopf i { font-style: normal; font-size: 12px; font-weight: 600;
                   color: var(--ok); font-variant-numeric: tabular-nums; }
.ub-knapp-kopf i.gelb { color: var(--warn); }
.ub-knapp-kopf i.rot { color: var(--err); }
.ub-trenn { height: 1px; background: var(--line); margin: 14px 0; }
.ub-engpass h2 .zahl { margin-left: 6px; }

@media print { .ub-reiter { display: none } }
.ub-delta { display: inline-flex; align-items: center; gap: 4px; align-self: flex-start;
            font-size: 11.5px; font-weight: 600; margin-top: 8px;
            padding: 2px 8px; border-radius: 99px; }
.ub-delta.hoch { color: var(--ok); background: var(--ok-bg); }
.ub-delta.runter { color: var(--ink-soft); background: #f1f4f8; }


/* Umschalter Material / Dienstleistung beim Hinzufügen einer Position */
.pos-wahl { display: inline-flex; gap: 3px; background: #eef1f6; border-radius: 8px;
            padding: 3px; margin-bottom: 6px; }
.pos-wahl button { border: 0; background: none; font: inherit; font-size: 12.5px;
                   font-weight: 600; color: var(--ink-soft); padding: 5px 12px;
                   border-radius: 6px; cursor: pointer; }
.pos-wahl button:hover:not(:disabled) { color: var(--ink); }
.pos-wahl button.on { background: var(--panel); color: var(--ink); box-shadow: var(--shadow); }
.pos-wahl button:disabled { opacity: .5; cursor: default; }

/* --- Schnellanlage im Projekt --------------------------------------
   Artikel oder Dienstleistung anlegen, ohne das Projekt zu verlassen.
   Das Formular sitzt im selben Dialog wie die Dispo-Vorschläge, hat
   aber Ränder – eine Liste darf bis an die Kante, ein Formular nicht. */
.schnell { padding: 16px; }
.schnell .field { margin-bottom: 12px; }
.schnell-fehler { background: #fef2f2; border: 1px solid #fecaca; color: #991b1b;
                  border-radius: 8px; padding: 9px 12px; margin-bottom: 12px; }
.schnell-fuss { display: flex; justify-content: flex-end; gap: 8px;
                border-top: 1px solid var(--line-soft); margin: 4px -16px -16px;
                padding: 12px 16px; background: #fbfcfe; border-radius: 0 0 10px 10px; }

/* ==================================================================
   Demo-Band (Paket «demo»)
   ==================================================================
   Ein schmaler Streifen über der Kopfzeile, nur in einer Demo-Instanz.
   Bewusst zurückhaltend: er soll die ganze Zeit dastehen, ohne bei
   jedem Blick nach oben zu stören – deshalb die Warnfarben der
   vorhandenen Meldungen, aber ohne Rahmen und ohne Abstand ringsum.
   Beim Drucken hat er nichts verloren. */
.demo-band {
  padding: 5px 26px;
  background: var(--warn-bg); color: var(--warn);
  border-bottom: 1px solid #f0dcae;
  font-size: 12.5px; line-height: 1.4;
}
@media (max-width: 720px) { .demo-band { padding: 5px 14px; } }
@media print { .demo-band { display: none } }

/* --- Vorführung des Selbst-Installers (nur Demo-Instanz, Paket «vorfuehrung») ---
   Sitzt im Fuß der Seitenleiste, direkt unter «Stand …». Dieselbe blaue
   Tönung wie der Update-Hinweis in der Schreibtisch-App: auffällig, aber
   keine Warnfarbe – es ist ja nichts kaputt. */
.vorf-kasten {
  margin-top: 9px; padding: 7px 9px;
  background: rgba(36,84,255,.20); border-radius: 6px;
}
.vorf-kasten strong { display: block; color: #fff; font-size: 12px; font-weight: 600; }
.vorf-knopf {
  margin-top: 3px; padding: 0; border: 0; background: none;
  color: #8fa8ff; font: inherit; font-size: 12px;
  text-decoration: underline; cursor: pointer;
}
.vorf-knopf:hover { color: #fff; }

.vorf-dialog {
  max-width: 430px; border: 0; border-radius: 10px;
  padding: 22px 24px; color: var(--ink);
  box-shadow: 0 18px 50px rgba(0,0,0,.28);
}
.vorf-dialog::backdrop { background: rgba(12,16,28,.55); }
.vorf-dialog h2 { margin: 0 0 10px; font-size: 17px; }
.vorf-dialog p { margin: 0 0 10px; font-size: 13.5px; line-height: 1.5; }
.vorf-dialog .vorf-nebensatz { color: var(--ink-soft); }
.vorf-dialog form { margin: 14px 0 0; text-align: right; }
@media print { .vorf-kasten, .vorf-dialog { display: none } }

/* --- Finanzen: Ampel des Zahlungsabgleichs (Paket «finanzen», 25.09.2026)
   Dieselbe Sprache wie beim Packen und bei der Inventur: gruen heisst
   «ein Klick genuegt», gelb «bitte ansehen», grau «bleibt liegen».
   Farbe allein traegt die Aussage nicht – neben jedem Punkt steht der
   Grund im Klartext. ------------------------------------------------ */
.punkt {
  display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  flex: 0 0 9px; vertical-align: 1px;
}
.punkt.gruen { background: var(--ok); }
.punkt.gelb  { background: var(--warn); }
.punkt.grau  { background: #b3bcc9; }

tr.amp-gruen { background: #f6fcf8; }
tr.amp-gelb  { background: #fffcf3; }

/* Die Zahlungen unter einer Rechnung – eingerueckt und leiser, damit die
   Rechnungszeile die Zeile bleibt, die man liest. */
tr.zahlzeile td { border-top: 0; padding-top: 2px; padding-bottom: 6px; }
tr.zahlzeile td:first-child { border-left: 3px solid var(--line); }

/* Betragsfeld in der Vorschlagsliste: schmal, rechtsbuendig, damit die
   Spalte aussieht wie eine Betragsspalte und nicht wie ein Formular. */
.betragfeld {
  width: 110px; text-align: right;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* Der Knopf «bezahlt» in der Liste der offenen Posten (Paket
   «finanzen-rollen», 26.09.2026). Ein Formular ist von Haus aus ein
   Block – ohne diese Zeilen steht das Datumsfeld auf voller Breite und
   schiebt «ansehen» in die naechste Zeile. */
.bezahltform { display: inline-flex; gap: 6px; align-items: center; margin-right: 8px; }
.bezahltform input[type="date"] { padding: 4px 7px; font-size: 12.5px; width: 132px; }
@media (max-width: 720px) {
  .bezahltform { display: flex; margin: 0 0 6px; }
  .bezahltform input[type="date"] { flex: 1; width: auto; }
}

/* --- Zahlungen zu einer Rechnung nachsehen (26.09.2026) -------------
   Ein kleiner Knopf in der Spalte «Offen» und ein <dialog> dahinter.
   Vorher standen die Zahlungen als Zusatzzeilen unter der Rechnung:
   sie machten die Liste lang, ohne die Frage zu beantworten, die man
   bei einer Teilzahlung wirklich hat – wann kam wie viel, und was war
   danach noch offen. -------------------------------------------- */
.info-knopf {
  appearance: none; border: 1px solid var(--line); background: #fff;
  color: var(--brand-dk); border-radius: 999px; cursor: pointer;
  font: 600 11px/1 inherit; padding: 2px 7px 3px; margin-left: 6px;
  display: inline-flex; align-items: center; gap: 4px; vertical-align: 1px;
}
.info-knopf:hover  { background: #eef3fd; border-color: #c7d7f5; }
.info-knopf:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.info-knopf span:first-child {
  font-family: Georgia, "Times New Roman", serif; font-style: italic;
  font-weight: 700; font-size: 12px; line-height: 1;
}
.info-zahl { font-size: 10.5px; opacity: .75; }

.zdlg {
  border: 0; border-radius: 10px; padding: 0; width: min(92vw, 760px);
  box-shadow: 0 18px 50px rgba(12,16,28,.28); color: var(--ink);
}
.zdlg::backdrop { background: rgba(12,16,28,.5); }
.zdlg h2 {
  margin: 0; padding: 14px 18px; font-size: 15.5px; font-weight: 600;
  border-bottom: 1px solid var(--line-soft);
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
.zdlg-inhalt { max-height: min(62vh, 520px); overflow-y: auto; }
.zdlg-t { width: 100%; }
.zdlg-t th, .zdlg-t td { padding: 8px 12px; }
.zdlg-t tbody tr:hover { background: #fafbfd; }
/* Die Kopfzeile des Verlaufs: der Rechnungsbetrag, von dem alles abgeht. */
.zdlg-start td { background: #fafbfd; border-bottom: 1px solid var(--line); }
.zdlg-null  { color: var(--ok); font-weight: 600; }
.zdlg-offen { color: var(--err); }
.zdlg-t tfoot th {
  background: #fafbfd; border-top: 2px solid var(--line); border-bottom: 0;
  font-size: 13px; text-transform: none; letter-spacing: 0; color: var(--ink);
}
.zdlg-fuss {
  margin: 0; padding: 12px 18px; border-top: 1px solid var(--line-soft);
  text-align: right; background: #fff; border-radius: 0 0 10px 10px;
}
.zdlg-t form { display: inline; }

@media (max-width: 720px) {
  .zdlg { width: 94vw; }
  .zdlg-t th, .zdlg-t td { padding: 7px 8px; font-size: 12.5px; }
}

/* Ausgeglichene Rechnungen in der Ansicht «auch ausgeglichene zeigen»:
   da, aber leiser – die offenen sollen weiter ins Auge springen. */
tr.ausgeglichen td { color: var(--ink-soft); }
tr.ausgeglichen td strong { font-weight: 500; }

/* Die Liste der offenen Posten hat neun Spalten, darunter ein Datumsfeld.
   Unter rund 1000 px quetscht der Browser sie zusammen, bis der Kundenname
   dreizeilig umbricht. Lieber eine Mindestbreite und rollen – dieselbe
   Entscheidung wie bei der Packliste weiter oben. */
.finanz-t { min-width: 1120px; }
.finanz-t td, .finanz-t th { vertical-align: top; }
.finanz-t td:first-child { padding-top: 11px; }
/* Ein langer Firmenname darf die Zeile nicht dreizeilig machen – er
   wird abgeschnitten und steht vollstaendig im title. */
.finanz-t td.kunde, .finanz-t td.projekt {
  max-width: 190px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.finanz-t td.projekt { max-width: 165px; }

/* ================================================================== Zoll
   Paket «zoll-1», 14.10.2026.

   KEINE NEUE FARBE UND KEINE NEUE ZAHL. Alles kommt aus den Variablen
   oben, die der Vorgabe 3.1 §2 entsprechen -- auch die Textfarben auf
   hellem Zustandsgrund (--ok-text, --warn-text, --err-text), die es
   wegen des Kontrasts gibt. Radius 8 wie eine Meldung, nicht 20 wie
   eine einzeilige Marke (§5 «Hinweise»): dieser Kasten ist mehrzeilig.
   ================================================================== */
.zoll-lage {
  border: 1px solid; border-radius: var(--radius);
  padding: 12px 14px; margin-bottom: 0;
}
.zoll-lage.z-ok     { background: var(--ok-bg);   border-color: var(--ok-rand);   color: var(--ok-text); }
.zoll-lage.z-warn   { background: var(--warn-bg); border-color: var(--warn-rand); color: var(--warn-text); }
.zoll-lage.z-fehler { background: var(--err-bg);  border-color: var(--err-rand);  color: var(--err-text); }
.zoll-lage.z-leise  { background: var(--hover);   border-color: var(--line);      color: var(--ink-soft); }
.zoll-satz   { font-weight: 600; font-size: 14px; }
.zoll-miete  { margin-top: 8px; padding: 8px 10px; border-radius: 6px;
               background: rgba(255,255,255,.65); font-size: 13.5px; }
.zoll-punkte { margin: 8px 0 0; padding-left: 18px; font-size: 13.5px; }
.zoll-punkte li { margin: 3px 0; }
.zoll-quelle { margin-top: 9px; font-size: 12px; opacity: .85; }

/* Die Lückentabelle erbt von .t; hier nur, was eigen ist. */
.zoll-fehlt {
  display: inline-block; margin: 1px 4px 1px 0; padding: 1px 8px;
  border: 1px solid var(--err-rand); border-radius: 20px;
  background: var(--err-bg); color: var(--err-text); font-size: 11.5px;
}
.zoll-gut { color: var(--ok-text); font-size: 12px; }
.zoll-zus {
  display: flex; flex-wrap: wrap; gap: 22px;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line-soft);
  font-size: 13px;
}
.zoll-zus b    { display: block; font-size: 18px; font-variant-numeric: tabular-nums; }
.zoll-zus span { color: var(--ink-soft); font-size: 12px; }

/* ============================================================== Suchwahl
   Ein Auswahlfeld, das sich als Aufklapper oeffnet und die Suche als
   ERSTE ZEILE darin traegt (Paket «suchwahl», 14.10.2026).

   Jochens Wort am 14.10.2026, vor dem Bildschirm: «Die suche ist
   getrennt zum Ergebnisfenster. Es soll ein scrolldown aufgehen, die
   erste zeile suche. Im ganzen Portal soll das so sein, bei allen
   Suchen die man ausfuehren kann. Nicht erst einstellen, dann woanders
   klicken.»

   Vorher standen Suchfeld und Auswahlfeld untereinander: zwei
   Bedienschritte und zwei Felder fuer eine Entscheidung.

   OHNE JAVASCRIPT bleibt das <select> sichtbar und vollstaendig
   bedienbar -- lang, aber bedienbar. Erst das Skript blendet es aus
   und setzt den Aufklapper davor. Darum gibt es hier KEIN
   `display:none` auf dem select: das macht das Skript, und nur wenn
   es wirklich laeuft.

   Masse nach Vorgabe 3.1 §5: Feldhoehe 38 px, Rahmen --feldrand,
   Radius 6, Fokusring 3 px. Das Menue nach §5 «Menues»: weiss,
   Rahmen --line, Radius 8, Schatten, mindestens 220 px breit. */
.suchwahl { position: relative; }

/* Der Knopf sieht aus wie ein Auswahlfeld -- denn er ist eines. */
.suchwahl-knopf {
  display: flex; align-items: center; gap: 8px; width: 100%;
  height: 38px; padding: 8px 11px; font: inherit; font-size: 14px;
  text-align: left; color: var(--ink);
  background: var(--panel); border: 1px solid var(--feldrand);
  border-radius: 6px; cursor: pointer;
}
.suchwahl-knopf:hover { border-color: var(--brand); }
.suchwahl-knopf:focus-visible {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(45,108,223,.13);
}
.suchwahl-knopf .wert { flex: 1 1 auto; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.suchwahl-knopf .wert.leer { color: var(--ink-soft); }
/* Der Pfeil: 11 x 8 px, #6B7280 -- Vorgabe §5 «Auswahl». */
.suchwahl-knopf .pfeil {
  flex: 0 0 auto; width: 11px; height: 8px; color: #6B7280;
}
.suchwahl.auf .suchwahl-knopf {
  border-color: var(--brand); box-shadow: 0 0 0 3px rgba(45,108,223,.13);
}

.suchwahl-menue {
  position: absolute; z-index: 60; left: 0; right: 0; top: calc(100% + 4px);
  min-width: 220px; padding: 5px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 10px 30px rgba(15,25,40,.18);
  display: none;
}
.suchwahl.auf .suchwahl-menue { display: block; }
/* Nach oben, wenn unten kein Platz ist. */
.suchwahl.hoch .suchwahl-menue { top: auto; bottom: calc(100% + 4px); }

/* DIE ERSTE ZEILE IST DIE SUCHE. Genau das war der Wunsch. */
.suchwahl-suche {
  width: 100%; height: 32px; padding: 6px 10px; font: inherit; font-size: 13.5px;
  border: 1px solid var(--line); border-radius: 6px; background: var(--panel);
  box-sizing: border-box;
}
.suchwahl-suche:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(45,108,223,.13);
}
.suchwahl-liste {
  margin: 5px 0 0; padding: 0; list-style: none;
  max-height: 260px; overflow-y: auto;
}
.suchwahl-liste li {
  display: flex; justify-content: space-between; gap: 10px;
  padding: 7px 9px; border-radius: 5px; cursor: pointer; font-size: 13.5px;
}
.suchwahl-liste li:hover,
.suchwahl-liste li.an { background: var(--marke-hell); }
.suchwahl-liste li[aria-selected="true"] { font-weight: 600; }
.suchwahl-liste .neben { color: var(--ink-soft); font-size: 12px;
  font-variant-numeric: tabular-nums; }
.suchwahl-leer { padding: 9px; font-size: 13px; color: var(--ink-soft); }
.suchwahl-hinweis { padding: 2px 9px 6px; font-size: 12px; color: var(--ink-soft); }

/* ==================================================================
   Tabelle «Phasen und Meilensteine» (Reiter «Zeitplan»), Vorschlag A
   Vorgabe 3.1 §5 «Zeile und Zelle: gleich hoch, senkrecht mittig»,
   §5 «Tabellenfeld», §5 «Menüs», §11.4 «Geänderte Zeile».

   KEINE NEUE FARBE UND KEINE NEUE ZAHL FÜR FARBEN: alles kommt aus den
   Variablen oben in :root. Die Masse für Abstand und Schrift sind die
   der Positionstabelle (table.pos-t): 4 px Innenabstand, 12,5 px, Felder
   30 px hoch.

   Überall «table.zp-t» statt nur «.zp-t»: die allgemeine Regel heisst
   «table.t th, table.t td» und ist damit spezifischer als eine blosse
   Klasse - dieselbe Lehre wie bei table.pos-t.
   ================================================================== */

/* Feste Spaltenbreiten, Bezeichnung nimmt den Rest. Gerechnet für die
   schmalste Karte, in der das Fenster noch eine Seitenspalte trägt
   (1280 px Fenster: 774 px Karte, davon 772 px innen): 128 + 236 + 78 +
   140 + 44 = 626, bleiben 146 px für die Bezeichnung.

   DIE 28 PX SIND EINE ENTSCHEIDUNG, KEINE MESSUNG. Gemessen war zuerst
   «Wer» 168 und Bezeichnung 118 -- und 118 px schnitten lange Namen früh
   ab. Jochen am 14.10.2026, vor den gemessenen Zahlen: «28 px von Wer
   nehmen.» Ein Name in «Wer» wird dafür etwas früher gekürzt; dort steht
   ohnehin höchstens einer, und wer alle sehen will, öffnet das Fenster.

   Hier stand davor «bleiben 128 px», gerechnet mit 68 px Dauer; die Spalte
   wurde danach auf 78 verbreitert und die Rechnung nicht mitgezogen. Darum
   steht die Rechnung jetzt zweimal: hier und als Messung im Blatt 24.
   «Dauer» braucht 68 px: «53 Tage» ist mit 56 px bereits mit «…» gekürzt
   worden (gemessen). Darunter rollt die Tabelle in ihrem .tablewrap,
   statt eine Zeile umzubrechen (min-width). */
table.zp-t { table-layout: fixed; width: 100%; min-width: 772px; font-size: 12.5px; font-variant-numeric: tabular-nums; }
table.zp-t col.zp-c-art    { width: 128px; }
table.zp-t col.zp-c-termin { width: 236px; }
table.zp-t col.zp-c-dauer  { width: 78px; }   /* 68 -> 78: «Speichern» steht hier */
table.zp-t col.zp-c-wer    { width: 140px; }  /* 168 -> 140: die 28 px gehen an die Bezeichnung (Jochen, 14.10.2026) */
table.zp-t col.zp-c-mehr   { width: 44px; }
table.zp-t th, table.zp-t td { padding: 4px; vertical-align: middle; }
table.zp-t th:first-child, table.zp-t td:first-child { padding-left: 8px; }
table.zp-t th:last-child,  table.zp-t td:last-child  { padding-right: 8px; }
table.zp-t td.r { padding-right: 8px; }

/* Jede Zeile 39 px (30 px Feld + 2 × 4 px Innenabstand + 1 px Linie) und
   ohne Umbruch: was zu lang ist, wird mit «…» gekürzt, die Zeile wächst
   nicht. */
table.zp-t tbody td { height: 39px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
table.zp-t form { margin: 0; }

/* Die allgemeine Feldregel (app.css, «Formulare») macht Felder 38 px hoch;
   Tabellenfelder sind nach §5 30 px. */
table.zp-t input, table.zp-t select { height: 30px; min-height: 30px; min-width: 0; padding: 4px 6px; font-size: 12.5px; }
table.zp-t select { padding-right: 22px; background-position: right 7px center; }
table.zp-t input[name="name"] { font-weight: 500; }
table.zp-t .btn-sm { height: 30px; padding: 0 10px; }

/* Anfang und Ende nebeneinander, in jeder Zeile gleich breit: so stehen
   die Zeiträume bündig (Jochen, 10.10.2026, «Bitte bündig»). */
.zp-termin { display: grid; grid-template-columns: minmax(0, 1fr) 14px minmax(0, 1fr); align-items: center; }
.zp-bis { text-align: center; color: var(--ink-soft); }

/* Meilenstein: an der Stelle der Art ein gesperrtes Feld (§5 «Gesperrte
   Zeilen»: Rahmen linieSanft) mit der Marke darin. */
.zp-art-fest { display: flex; align-items: center; height: 30px; padding: 0 6px; border: 1px solid var(--line-soft); border-radius: 6px; }

/* Die Zelle «Wer» ist selbst der Knopf zum Personal-Fenster. Er sieht aus
   wie Text, bis die Maus darauf steht. Der Name kürzt sich mit «…», die
   Zahl dahinter und die Marke «n offen» nicht: sie sind das, was man in
   der Zeile sucht. */
.zp-wer { display: flex; align-items: center; gap: 5px; width: 100%; height: 30px; padding: 0 6px; border: 1px solid transparent; border-radius: 6px;
          background: none; font: inherit; color: var(--ink); text-align: left; cursor: pointer; overflow: hidden; white-space: nowrap; }
button.zp-wer:hover { background: var(--hover); border-color: var(--line); }
button.zp-wer:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.zp-wer-text { cursor: default; }
.zp-wer-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; font-weight: 500; }
.zp-wer-mehr { flex: none; color: var(--ink-soft); }
.zp-wer .tag { flex: none; }
.zp-wer-leer { color: var(--brand); }
button.zp-wer:hover .zp-wer-leer { text-decoration: underline; }

/* Knopfspalte: nur das Menü hat Platz in der Zeile. «Speichern» liegt
   darüber, links neben dem Menü, auf der Spalte «Wer» - nur solange diese
   Zeile geändert ist, und dann ist «Wer» nicht das, was man ansieht.
   Eine eigene Spalte dafür hätte jeder Zeile 90 px genommen, die
   sie nur selten braucht. Die Zelle muss überlaufen dürfen (sonst schneidet
   «overflow: hidden» den Knopf ab) und ist der Bezugspunkt für die Lage. */
/* «Speichern» steht in der Spalte «Dauer» und TAUSCHT mit der Zahl, es legt
   sich nicht darueber. Im ersten Entwurf lag der Knopf mit position:absolute
   ueber der Spalte «Wer» und machte den Personal-Knopf dort unklickbar.
   Die Dauer kommt vom Server und rechnet sich nicht mit, solange nichts
   gespeichert ist -- sie ist beim Aendern ohnehin veraltet. */
.zp-speichern { display: none; }
table.zp-t td.zp-dauerzelle { padding-right: 6px; }

/* OHNE JAVASCRIPT steht der Knopf in jeder Zeile: dann bemerkt nichts die
   Aenderung. zp-neu.js setzt «zp-js» an die Tabelle und tauscht erst dann. */
table:not(.zp-js) .zp-speichern { display: inline-flex; }
table:not(.zp-js) .zp-dauer     { display: none; }
table.zp-js tr.zp-geaendert .zp-speichern { display: inline-flex; }
table.zp-js tr.zp-geaendert .zp-dauer     { display: none; }

/* Geänderte, noch nicht gespeicherte Zeile: 3 px Balken links in der
   Warnfarbe (Vorgabe §11.4). */
table.zp-t tr.zp-geaendert > td:first-child { box-shadow: inset 3px 0 0 var(--warn); }

/* Die Eingabezeilen unten. Die 2 px Linie darüber kommt aus einem
   Schatten statt aus einem Rand: der Rand der Zelle (1 px) gewinnt beim
   border-collapse nur, wenn der andere breiter ist, und ein breiterer
   machte die Zeile höher als die anderen. */
table.zp-t tr.zp-neu-erste > td { box-shadow: inset 0 2px 0 var(--line); }

/* ------------------------------------------------------------------
   Menü «⋯» (Vorgabe §5 «Menüs»)

   Allgemein gehalten, ohne Wort aus dem Zeitplan: die Positionstabelle
   (§12.1) und jede andere Tabelle sollen es mitbenutzen können.

   Gebaut als <details>, nicht als Knopf mit Skript: es klappt auch ohne
   JavaScript auf, und was darin steht (Formulare, Knöpfe, ein Haken) ist
   gewöhnliches HTML. zp-neu.js ergänzt nur, was ein <details> nicht
   kann: Esc, Klick daneben, Pfeiltasten und ein Platz, der im Fenster
   bleibt.

   Die Liste ist «fixed», damit weder der .tablewrap (overflow-x: auto
   schneidet auch nach unten ab) noch die Zelle sie beschneidet. Ohne
   Skript sitzt sie dort, wo sie im Fluss stünde, rechtsbündig zum Knopf
   (negativer Rand = Breite der Liste minus Breite des Knopfes).
   ------------------------------------------------------------------ */
.menue-knopf { list-style: none; display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 6px;
               color: var(--ink-soft); font-size: 18px; line-height: 1; cursor: pointer; user-select: none; }
.menue-knopf::-webkit-details-marker { display: none; }
.menue-knopf:hover, .menue[open] > .menue-knopf { background: var(--line-soft); color: var(--ink); }
.menue-knopf:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.menue-liste { position: fixed; z-index: 60; width: 220px; margin: 4px 0 0 calc(30px - 220px); padding: 5px; text-align: left; white-space: nowrap;
               font-size: 13.5px; background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--schatten-menue); }
.menue-form { margin: 0; }
.menue-eintrag { position: relative; display: flex; justify-content: space-between; align-items: center; gap: 12px; width: 100%; padding: 7px 10px;
                 border: 0; border-radius: 6px; background: none; font: inherit; font-size: 13.5px; color: var(--ink); text-align: left; cursor: pointer; }
.menue-eintrag:hover, .menue-eintrag:focus-visible, .menue-eintrag:focus-within { background: var(--hover); outline: none; }
.menue-eintrag:focus-visible, .menue-eintrag:focus-within { box-shadow: inset 0 0 0 2px var(--brand); }
.menue-gefahr { color: var(--err); }
.menue-trenner { height: 1px; margin: 4px 0; background: var(--line-soft); }
/* Ein Haken im Menü: das Kästchen bleibt für Tastatur und Formular da,
   sichtbar ist das ✓ rechts in der Markenfarbe (§5 «Menüs»). */
/* Der unsichtbare Fang fuer den ersten Klick daneben: unter der Liste
   (59 gegen 60), ueber allem anderen. GEMESSEN am 14.10.2026 -- ohne ihn traf
   ein Klick auf das «...» der naechsten Zeile den Eintrag «Im Kalender» des
   offenen Menues. zp-neu.js legt ihn hin und nimmt ihn weg. */
.menue-schleier { position: fixed; inset: 0; z-index: 59; background: none; }

.menue-wahl { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.menue-haken { color: var(--brand); visibility: hidden; }
.menue-wahl:checked ~ .menue-haken { visibility: visible; }

/* Nur für Vorleseprogramme: Text, der auf dem Bildschirm nicht stehen soll. */
.nur-leser { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* ------------------------------------------------------------------
   Paket «briefkopf-reiter» (21.10.2026, Entscheidung Jochens: «Weg C,
   drei Reiter»). Zusaetze zu den Registerkarten und zum Briefkopf-
   Formular; nichts darueber wurde geaendert.
   ------------------------------------------------------------------ */

/* Ein Feld, das der SERVER beim Speichern abgewiesen hat. Er setzt
   aria-invalid="true" (Briefkopf: LetterheadController::abgewiesen()).
   Vorgabe 3.1 «Felder»: Rahmen `fehler` (#C0392B = --err). Der Rand
   bleibt rot, auch wenn das Feld den Fokus hat; der blaue Fokusring
   von `input:focus` wuerde sonst den Fehler beim Hineinklicken
   verdecken. Haken und Dateifelder: Umriss, denn ein Haken hat keinen
   Rand, den man faerben koennte. */
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"],
input[aria-invalid="true"]:focus, select[aria-invalid="true"]:focus, textarea[aria-invalid="true"]:focus {
  border-color: var(--err);
}
input[aria-invalid="true"]:focus, select[aria-invalid="true"]:focus, textarea[aria-invalid="true"]:focus {
  box-shadow: 0 0 0 3px rgba(192,57,43,.16);
}
input[type=checkbox][aria-invalid="true"] { outline: 2px solid var(--err); outline-offset: 2px; }

/* Das rote «!» an einem Reiter, in dem der Server ein Feld abgewiesen
   hat (app.js, Baustein «Registerkarten»). Eigene Klasse statt
   `.zahl.achtung`: bei dem gewaehlten Reiter faerbt
   `.tabs button[aria-selected="true"] .zahl` die Marke sonst blau, und
   ausgerechnet der offene Reiter mit dem Fehler saehe harmlos aus. */
.tabs button .zahl.abgewiesen,
.tabs button[aria-selected="true"] .zahl.abgewiesen { background: var(--err-bg); color: var(--err-text); }

/* Die genaue Erklaerung zum Aufklappen (Briefkopf, «Seitenraender»).
   Gebaut wie .klapp-karte, nur ohne Griff in der Kartenzeile. */
.erklaerung { margin-top: 14px; }
.erklaerung > summary { cursor: pointer; font-size: 13px; color: var(--ink-soft); display: flex; gap: 8px; align-items: baseline; }
.erklaerung > summary::-webkit-details-marker { display: none; }
.erklaerung > summary::before { content: '▸'; flex: 0 0 auto; }
.erklaerung[open] > summary::before { content: '▾'; }
.erklaerung > summary:hover { color: var(--ink); }

/* Ein hochgeladener Bogen: Vorschau (112 px, Paket «briefkopf-feinschliff») neben dem Namen und
   dem Knopf «Bogen entfernen», statt gross darueber. */
.bogen-zeile { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 10px; }
.bogen-bild { flex: 0 0 112px; width: 112px; height: auto; display: block; background: #fff;
              border: 1px solid var(--line); border-radius: 3px; }
.bogen-info { flex: 1 1 auto; min-width: 0; }

/* ------------------------------------------------------------------
   Paket «briefkopf-vorschau» (21.10.2026). Zusaetze; nichts darueber
   wurde geaendert.
   ------------------------------------------------------------------ */

/* Der Satz unter der Reiterleiste, wenn der BROWSER das Absenden aufhaelt
   (leeres Pflichtfeld, falsche Adresse) und dafuer in einen anderen
   Reiter springt. Farben wie der Fehlerkasten (.errbox). Ohne Text bleibt
   er verborgen (hidden). */
.reiter-hinweis {
  margin: -4px 0 16px; padding: 10px 14px;
  background: var(--err-bg); border: 1px solid var(--err-rand); border-radius: var(--radius);
  color: var(--err-text); font-size: 14px; line-height: 1.4;
}
.reiter-hinweis[hidden] { display: none; }

/* Der Hinweis unter einem Dateifeld: nach einer Fehlermeldung muss die
   Datei noch einmal gewaehlt werden. */
.datei-neu { margin-top: 6px; }

/* Die Vorschau in der Liste der Briefkoepfe: 64 px breit, auch wenn die
   Bearbeiten-Seite 112 px gross macht; A4-Seitenverhaeltnis vorab reserviert, damit
   die Zeile nicht springt, wenn das Bild nachlaedt. */
table.t .bogen-bild { width: 64px; aspect-ratio: 210 / 297; object-fit: contain; height: auto; }

/* ------------------------------------------------------------------
   Paket «briefkopf-feinschliff» (21.10.2026). Zusaetze; nichts darueber
   wurde geaendert.
   ------------------------------------------------------------------ */

/* Die Reiterleiste bleibt beim Scrollen unter der Kopfzeile stehen. Sie
   steht in einem Halter, der klebt - nicht in der Leiste selbst: die
   Leiste blendet ihren rechten Rand mit mask-image aus, und das wuerde
   einen Hintergrund an der Leiste mit ausblenden. Der Halter bekommt die
   Flaeche (weiss wie die Kopfzeile) und den Abstand darunter.
   TOP = Hoehe der Kopfzeile (.topbar, klebt bei 0): 16 + 16 Polsterung
   + 28,5 Zeilenhoehe (19 px Schrift x 1,5 aus dem Body) + 1 px Rand = 61,5 px;
   unter 720 px (Polsterung 13): 13 + 13 + 28,5 + 1 = 55,5 px. */
.tabs-halter {
  position: sticky; top: 61.5px; z-index: 5;
  background: var(--panel); display: flow-root;
}
@media (max-width: 720px) { .tabs-halter { top: 55.5px; } }
