/* ============================================================
   Basedo Aufträge — handgeschriebenes Stylesheet, kein Framework.
   Neutrale Basis, eine Akzentfarbe, Hierarchie über Typografie.
   ============================================================ */

/* Basedo-Hausschrift: Arimo (frei, metrisch Helvetica/Arial-kompatibel),
   selbst gehostet — Variable Font deckt 400–700 ab. */
@font-face {
  font-family: "Arimo";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/static/fonts/arimo-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Arimo";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/static/fonts/arimo-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
    U+02DD-02FF, U+0332, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Orbitron (SIL OFL, lokal unter /static/fonts/) — AUSSCHLIESSLICH für die
   ODIN-WORTMARKE. Die Anwendungsschrift bleibt Arimo.
   Lizenz: static/fonts/OFL-Orbitron.txt.

   ⚠ GELTUNGSBEREICH ERWEITERT AM 06.08.2026 (Entscheid Eric). Hier stand
   „ausschliesslich für die ODIN-Wortmarke auf der LOGIN-SEITE". Seit dem
   Logo-Tausch trägt die Wortmarke auch den Seitenleistenkopf der
   angemeldeten Oberfläche (`.odin-marke`). Die Einschränkung ist damit
   NICHT gefallen, sondern verschoben: Orbitron ist weiterhin allein der
   Wortmarke vorbehalten, jetzt an zwei Stellen statt einer. Sie für
   Überschriften, Zahlen oder Fliesstext zu benutzen bleibt untersagt —
   das Subset trägt zwar 179 Glyphen (Klein- und Grossbuchstaben,
   Ziffern, Akzente), aber die Schrift ist eine Anzeigeschrift mit engen
   Punzen und in Lesegrössen unbrauchbar. */
@font-face {
  font-family: "Orbitron";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/static/fonts/orbitron-700.woff2") format("woff2");
}

:root {
  /* Farben */
  --hintergrund:      #f7f7f8;
  --flaeche:          #ffffff;
  --flaeche-2:        #f0f0f2;
  /* Primärtext seit 18.07.2026 nahezu schwarz (Lesbarkeit, ~19:1);
     Labels/Meta bleiben abgestuft grau. */
  --text:             #111114;
  /* `--text-1` ist ein ALIAS auf `--text`, keine neue Farbe. Die Skala
     heisst --text / --text-2 / --text-3; wer sie liest, erwartet die
     erste Stufe unter dem Namen `--text-1`, und genau so wurde sie am
     04.08.2026 in `details.arbeitsflaeche > summary` benutzt — nur gab
     es sie nicht. CSS meldet das nicht: Die Deklaration fiel still aus,
     die Farbe kam per Vererbung, und weil der Erbwert zufaellig
     ebenfalls `--text` war, sah es richtig aus. Aus dem falschen Grund
     richtig ist der Zustand, der spaeter teuer wird — haette ein
     Elternteil je eine andere Farbe bekommen, waere die Ueberschrift
     lautlos mitgewandert.

     Sie steht als Alias und nicht als zweite Konstante, damit es bei
     EINER Quelle bleibt: Wer `--text` aendert, aendert beide. */
  --text-1:           var(--text);
  --text-2:           #6e6e73;
  --text-3:           #a1a1a6;
  /* Icons: kräftiges Anthrazit als Grundfarbe (statt blassem Erben
     der Textfarbe); semantische Ausnahmen je icon-<name>-Klasse. */
  --icon-grund:       #3f3f46;
  --linie:            rgba(0, 0, 0, 0.08);

  /* Basedo-Corporate-Rot. Original #e52a3b erreicht auf/mit Weiß nur
     4,44:1 (AA braucht 4,5) — daher: --akzent (leicht abgedunkelt,
     5,67:1) überall, wo Text im Spiel ist; --marke (Original) nur für
     rein dekorative Elemente ohne Text (Fortschritts-Segmente). */
  --akzent:           #c8202f;
  --akzent-hover:     #a81a27;  /* 7,39:1 */
  --akzent-flaeche:   #fdeef0;
  --marke:            #e52a3b;

  --warnung:          #9a6700;
  --warnung-flaeche:  #fff8ec;
  --fehler:           #c0392b;
  --fehler-flaeche:   #fdf2f0;
  --ok:               #1e7f37;
  --ok-flaeche:       #f0f9f2;

  /* Typografie: Basedo-Hausschrift, Fallback wie die Website.
     Skala am 18.07.2026 einen Schritt angehoben (Lesbarkeit):
     xs 12→13px, s 14→15px, m 16→17px; Überschriften unverändert. */
  --schrift: "Arimo", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --groesse-xs: 0.8125rem;
  --groesse-s:  0.9375rem;
  --groesse-m:  1.0625rem;
  --groesse-l:  1.375rem;
  --groesse-xl: 1.75rem;

  /* Abstände (4-px-Raster) */
  --a1: 4px; --a2: 8px; --a3: 12px; --a4: 16px;
  --a5: 24px; --a6: 32px; --a7: 48px;

  /* Radien & Schatten */
  --radius:       10px;
  --radius-gross: 14px;
  --radius-voll:  999px;
  --schatten-ruhe: 0 1px 2px rgba(0,0,0,.06), 0 0 0 0.5px rgba(0,0,0,.04);
  --schatten-hover: 0 3px 10px rgba(0,0,0,.10), 0 0 0 0.5px rgba(0,0,0,.04);
  --schatten-hebt: 0 12px 28px rgba(0,0,0,.16);

  /* EIN Hover-Muster für Zeilen/Listeneinträge: neutrales Grau —
     die Akzentfläche (--akzent-flaeche) ist dem AUSWAHL-Zustand
     vorbehalten (.gewaehlt, checked, aktiv), nie dem bloßen Hover. */
  --hover-flaeche: var(--flaeche-2);

  /* Typo-Ordnung (17.07.2026): DREI Textrollen für Begleitschein und
     Detail-Panels — EINE Quelle gegen Größen-/Kontrast-Drift (gleiches
     Prinzip wie die zentralen Statusfarben). Kontraste auf Weiß:
     Titel ~16:1, Label ~7:1, Meta ~4,9:1 — alle AA. */
  --rolle-titel-groesse: 1rem;        /* 16px — die primäre Lesegröße */
  --rolle-titel-farbe:   var(--text);
  --rolle-label-groesse: 0.875rem;    /* 14px — Feldnamen */
  --rolle-label-farbe:   #55555a;
  --rolle-meta-groesse:  0.875rem;    /* 14px — Datum/Person/Gründe */
  --rolle-meta-farbe:    var(--text-2);

  /* Bewegung */
  --dauer: 170ms;
  --kurve: cubic-bezier(0.25, 0.6, 0.3, 1);

  color-scheme: light;
}

/* ---------- Reset & Basis ---------- */

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

body {
  margin: 0;
  font-family: var(--schrift);
  font-size: var(--groesse-m);
  line-height: 1.5;
  color: var(--text);
  background: var(--hintergrund);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, p, ul, figure { margin: 0; }
ul { padding: 0; list-style: none; }

h1 { font-size: var(--groesse-xl); font-weight: 650; letter-spacing: -0.01em; }
h2 { font-size: var(--groesse-l);  font-weight: 650; letter-spacing: -0.01em; }
h3 { font-size: var(--groesse-m);  font-weight: 650; }

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

/* Einheitliches Hover-Timing für alle Zeilen-/Listeneinträge — Knöpfe,
   Eingaben, Karten und Kacheln haben ihre transition bereits einzeln
   (gleiche --dauer/--kurve). */
.nav-punkt, .leiste-toggle, .benutzer-menue summary, .menue-liste a,
.glocke, .menue-eintrag, .mehrfach-liste label, .vorschlag,
.begleitschein .bs-zeile label, .meilensteine label, tbody tr,
.zeile-chevron, .zeile-entfernen, .filter-chip .chip-x {
  transition: background var(--dauer) var(--kurve);
}

:focus-visible {
  outline: 2px solid var(--akzent);
  outline-offset: 2px;
  border-radius: 4px;
}

::placeholder { color: var(--text-3); }

/* ---------- Navigation: linke Seitenleiste + schlanke Kopfzeile ----------
   App-Raster: 240px Leiste | Inhalt. body.leiste-zu (Cookie, serverseitig
   gerendert) bzw. schmale Fenster: 64px Icon-Spalte. */

.app-raster {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  min-height: 100vh;
}
body.leiste-zu .app-raster { grid-template-columns: 64px minmax(0, 1fr); }

.seitenleiste {
  display: flex;
  flex-direction: column;
  gap: var(--a4);
  background: var(--flaeche);
  border-right: 1px solid var(--linie);
  padding: var(--a4) var(--a3);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}
/* ZENTRIERT, auch ausgeklappt (Korrektur 06.08.2026, Eric am Bildschirm
   gesehen). Vorher fehlte `justify-content` — Flex faellt dann auf
   `flex-start` zurueck, und die Wortmarke stand links. Aufgefallen ist
   es erst jetzt, weil das frühere Basedo-Logo mit 186px von 216px
   Innenraum fast die ganze Breite füllte; die Wortmarke füllt nur 164px
   und ließ 52px Rest sichtbar auf einer Seite liegen.
   Der eingeklappte Zustand war NIE betroffen: Beide Vertauschungsstellen
   (body.leiste-zu und die 1100px-Abfrage) setzen `justify-content:
   center` schon lange selbst. Sie wiederholen jetzt nur noch, was hier
   ohnehin gilt — harmlos, weil derselbe Wert, und bewusst stehen
   gelassen: Wer die Regel hier je einschraenkt, verliert sonst die
   Zentrierung im schmalen Zustand mit.

   ⚠ DAS `text-indent` AN `.odin-marke` GEHOERT ZU DIESER ZENTRIERUNG
   und ist keine Kosmetik. `letter-spacing` setzt den Abstand nach JEDEM
   Zeichen, auch nach dem letzten — dieser Nachlauf traegt keine Tinte,
   zaehlt aber zur Breite. Zentriert man ohne Ausgleich, sitzt der
   Schriftzug um ls/2 nach LINKS versetzt. Gerechnet fuer 48px:
   letter-spacing 6,72px, Zeilenvorschub 156,86px, sichtbare Tinte
   150,14px; ohne Ausgleich landet die Tintenmitte bei 104,64 statt
   108,00 — also 3,36px daneben. Allgemein ist die Tintenmitte
   B/2 + (indent - ls)/2, sie stimmt also GENAU dann, wenn text-indent
   gleich letter-spacing ist. Beide stehen auf 0.14em, der Versatz ist
   damit 0,00px. Wer eines der beiden aendert, muss das andere
   mitaendern. */
.seitenleiste .marke {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 60px;
}

/* ODIN-Wortmarke im Leistenkopf (Entscheid Eric 06.08.2026, ersetzt das
   Basedo-Logo, das in die Kopfleiste gewandert ist).

   FESTE GRÖSSE, ausdrücklich kein clamp: `.wortmarke` der Anmeldeseite
   skaliert mit `11vw` und ergäbe bei 1920px Fenster 211px in einer
   240px breiten Leiste.

   48px ist GEMESSEN, nicht geschätzt: Der Leistenkopf hat 216px
   Innenraum (240 minus 2x12 Polster). „ODIN" in Orbitron 700 misst dort
   mit Vorschub, viermal `letter-spacing` und dem `text-indent`
   zusammen 163,6px — das füllt 76 % und lässt beidseitig Luft. Zum
   Vergleich: 56px füllten 88 %, 64px liefen mit 218,1px über.

   Die Höhe bleibt unter den 60px `min-height` von `.marke`, die Zeile
   wächst also nicht. `text-indent` gleicht wie auf der Anmeldeseite den
   Nachlauf des Letter-Spacings rechts aus, damit die Marke optisch
   mittig sitzt. */
.odin-marke {
  font-family: "Orbitron", var(--schrift, sans-serif);
  font-weight: 700;
  font-size: 48px;
  line-height: 1;
  letter-spacing: 0.14em;
  text-indent: 0.14em;
  color: var(--text);
}

/* Basedo-Logo in der Kopfleiste (Entscheid Eric 06.08.2026). 28px Höhe,
   Breite folgt dem Seitenverhältnis 3,59:1, also rund 100px.

   ⚠ 28px UND NICHT MEHR, weil die Kopfleiste sonst wächst: Ihre Höhe
   bestimmt heute nicht die `min-height: 56px`, sondern das Suchfeld mit
   44px aus der globalen Formularregel plus 2x8px Polster, macht 60px.
   Alles bis 44px kostet nichts; darüber schiebt es die ganze Seite
   nach unten. */
.kopf-marke { display: inline-flex; align-items: center; flex: 0 0 auto; }
.logo-kopf { height: 28px; width: auto; display: block; }

/* Unter 1200px kleiner, NICHT weg (Entscheid Eric 06.08.2026).

   Der Umbruchpunkt sitzt bewusst bei 1200 und nicht bei 1100: Die
   engste Lage der Kopfleiste ist NICHT das schmalste Fenster, sondern
   die Breite knapp UEBER dem Leisten-Umschlag. Bis 1100px ist die
   Seitenleiste 240px breit; ab 1100px faellt sie auf 64px und gibt
   176px frei. Bei 1200px ist die Leiste also noch breit und das Fenster
   schon schmal — dort greift diese Regel als erste. */
@media (max-width: 1200px) {
  .logo-kopf { height: 20px; }
}

.logo-kompakt {
  display: none;
  width: 40px; height: 40px;
  border-radius: 8px;
  background: var(--marke);
  color: #fff;
  font-weight: 650;
  font-size: var(--groesse-m);
  align-items: center;
  justify-content: center;
}
.leiste-nav { display: flex; flex-direction: column; gap: var(--a4); }
.nav-gruppe { display: flex; flex-direction: column; gap: 2px; }
.nav-titel {
  font-size: var(--groesse-xs);
  font-weight: 650;
  color: var(--text-3);
  padding: 0 var(--a2) var(--a1);
}
/* Auch .nav-punkt braucht den doppelten Selektor: Der
   Seitenleisten-Umschalter traegt beide Klassen und ist ein
   Submit-Knopf; ohne ihn gewinnt `color: #fff` der roten Grundregel. */
.nav-punkt, button[type="submit"].nav-punkt {
  display: flex;
  align-items: center;
  gap: var(--a2);
  padding: var(--a2);
  border-radius: var(--radius);
  color: var(--text-2);
  font-size: 1rem;              /* Menü bewusst größer als Fließtext-S */
  font-weight: 500;
  transition: background var(--dauer) var(--kurve), color var(--dauer) var(--kurve);
}
.nav-punkt:hover { background: var(--hover-flaeche); color: var(--text); text-decoration: none; }
/* aktiver Bereich/aktive Seite: Basedo-Rot, klar erkennbar */
.nav-punkt.bereich-aktiv, .nav-punkt.nav-aktiv {
  background: var(--akzent-flaeche);
  color: var(--akzent-hover);
  font-weight: 650;
}
.nav-icon { flex: 0 0 24px; width: 24px; height: 24px; }

/* Natürliche Icon-Farben (18.07.2026): Grundton kräftiges Anthrazit
   statt blassem Vererben; semantische Ausnahmen einzeln. Der aktive
   Navigationspunkt färbt sein Icon weiter mit (Basedo-Rot), der rote
   Upload-Knopf bleibt weiß (erbt — bewusst KEINE Grundfarbe dort). */
.leiste-nav .nav-icon,
.leiste-fuss .nav-icon,
.glocke .nav-icon { color: var(--icon-grund); }
.leiste-nav .icon-aufmerksamkeit { color: var(--warnung); }

/* Bereichs-Farben der Seitenleisten-Icons (18.07.2026): je Bereich eine
   eigene, kräftige Farbe als Orientierung auf den ersten Blick — eine
   abgestimmte Palette gedeckt-gesättigter Töne gleicher Helligkeit
   (alle ≥4,5:1 auf Weiß), kein Regenbogen. Nur die Icons; der Text der
   Menüpunkte bleibt dunkel. Papierkorb bleibt bewusst Anthrazit
   (--icon-grund), Probleme bernstein (--warnung, oben). */
.leiste-nav .icon-dashboard    { color: #6b46c1; }  /* Übersicht — Violett */
.leiste-nav .icon-queue        { color: #15803d; }  /* Meine Vorgänge — Grün */
.leiste-nav .icon-statistik    { color: #0369a1; }  /* Statistik — Stahlblau */
.leiste-nav .icon-anfragen     { color: #0f766e; }  /* Anfragen — Petrol */
/* Beschaffung — Oliv (13.08.2026, Befund Eric: Beschaffung und Anfragen
   trugen dasselbe Symbol in derselben Farbe).

   ⚠ GERECHNET, NICHT GEWAEHLT. CIEDE2000 gegen ALLE zwoelf Farben, die
   auf demselben Schirm stehen (acht Bereiche, Warnfarbe, Grundton,
   Akzent, Marke), Menuegrund #ffffff:
       dE 22,5 Grundton | 22,7 Queue-Gruen | 22,9 Warnung | 25,3 Petrol
   Kleinster Abstand 22,5 — ueber der Schwelle 20 der Statusfarben.
   Kontrast 8,87:1 auf Weiss, im Band der uebrigen (4,87 bis 10,44).

   ⚠ UND EINE ZAHL, DIE DAZUGEHOERT: Die BESTEHENDE Palette haelt diese
   Schwelle selbst NICHT — Akzent/Marke liegen bei dE 6,7, Benutzer/
   Grundton bei 10,1, Auftraege/Statistik bei 10,8. Die neue Farbe ist
   damit strenger geprueft als ihre Nachbarn; wer die Palette einmal
   nachrechnet, findet dort echte Naehen. */
.leiste-nav .icon-beschaffung  { color: #4c4c24; }  /* Beschaffung — Oliv */
.leiste-nav .icon-auftraege    { color: #2456c4; }  /* Aufträge — Blau */
.leiste-nav .icon-bestellungen { color: #92400e; }  /* Bestellungen — Karton-Braun */
.leiste-nav .icon-kunden       { color: #86198f; }  /* Kunden — Beere */
.leiste-nav .icon-benutzer     { color: #475569; }  /* Benutzer — Schieferblau */

.nav-punkt.bereich-aktiv .nav-icon,
.nav-punkt.nav-aktiv .nav-icon { color: inherit; }
.nav-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Menüpunkt "Erfordert Aufmerksamkeit": Button im Nav-Look + Zähler-Badge.
   Eingeklappte Leiste: Badge als kleine Marke über der Icon-Ecke. */
button.nav-punkt {
  width: 100%;
  background: transparent;
  border: none;
  min-height: 0;
  cursor: pointer;
  position: relative;
  text-align: left;
}
.nav-badge {
  background: var(--fehler);
  color: #fff;
  border-radius: var(--radius-voll);
  font-size: 11px;
  font-weight: 650;
  line-height: 1;
  padding: 3px 7px;
}
.nav-badge-halter { margin-left: auto; display: inline-flex; }
body.leiste-zu .nav-badge-halter {
  position: absolute;
  top: 0;
  right: 0;
  margin: 0;
}
body.leiste-zu .nav-badge { padding: 2px 5px; font-size: 10px; }

.leiste-fuss { margin-top: auto; }
/* Doppelter Selektor wie bei .leise/.gefahr: Der Umschalter IST ein
   `<button type="submit">` (er sendet den Zustand ans Backend), und die
   rote Grundregel schlaegt sonst `background: transparent` — er waere
   ein roter Vollton-Balken in der Seitenleiste. Am 28.07.2026 vom
   Waechter gefunden. */
.leiste-toggle, button[type="submit"].leiste-toggle {
  width: 100%;
  background: transparent;
  border: none;
  min-height: 0;
  cursor: pointer;
}
.leiste-toggle:hover, button[type="submit"].leiste-toggle:hover {
  background: var(--hover-flaeche);
}

/* Eingeklappt: nur Icons, Wortmarke wird zum kompakten Zeichen,
   title = Tooltip.

   ⚠ DIESE VERTAUSCHUNG STEHT ZWEIMAL IM CSS — hier fuer den per Cookie
   gesetzten Zustand `body.leiste-zu`, und ein zweites Mal in der
   Medienabfrage bei 1100px, die den schmalen Zustand unabhaengig vom
   Cookie erzwingt. WER EINE AENDERT, AENDERT BEIDE. Eine Regel, die nur
   einen der beiden Ausloeser bedient, sieht richtig aus und faellt beim
   anderen lautlos aus. */
body.leiste-zu .nav-text,
body.leiste-zu .nav-titel,
body.leiste-zu .odin-marke { display: none; }
body.leiste-zu .logo-kompakt { display: inline-flex; }
body.leiste-zu .seitenleiste { padding: var(--a4) var(--a2); }
body.leiste-zu .seitenleiste .marke { justify-content: center; }
body.leiste-zu .nav-punkt { justify-content: center; }
body.leiste-zu .leiste-toggle .nav-icon { transform: rotate(180deg); }

/* Kopfzeile: Suche exakt mittig (Drei-Spalten-Grid: frei | Suche |
   +Neu/Glöckchen/Benutzer-Menü), kontextabhaengiges +Neu rechts. */
.kopfzeile {
  display: grid;
  grid-template-columns: 1fr minmax(240px, 480px) 1fr;
  align-items: center;
  gap: var(--a4);
  min-height: 56px;
  padding: var(--a2) var(--a5);
  background: var(--flaeche);
  border-bottom: 1px solid var(--linie);
}
.kopfzeile .globalsuche { grid-column: 2; }
.kopf-dazu { grid-column: 3; justify-self: end; display: flex; align-items: center; gap: var(--a3); }
@media (max-width: 900px) {
  /* Schmal: zurück zum umbruchfähigen Flex (Suche links, Menü rechts). */
  .kopfzeile { display: flex; flex-wrap: wrap; }
  .kopf-dazu { margin-left: auto; }
}

/* Globale Suche in der Kopfzeile: wächst mit, läuft auf großen Monitoren
   aber nicht ins Endlose. Dropdown in der bekannten Combobox-Optik. */
.globalsuche { flex: 1 1 240px; max-width: 480px; }
.globalsuche input[type="search"] { width: 100%; margin-top: 0; }
.globalsuche .vorschlaege { max-height: min(60vh, 480px); overflow-y: auto; }
.vorschlag-gruppe {
  padding: var(--a2) var(--a4) 2px;
  font-size: var(--groesse-xs);
  font-weight: 600;
  color: var(--text-2);
}
.vorschlag ~ .vorschlag-gruppe { border-top: 1px solid var(--linie); margin-top: var(--a1); }

/* Profilseiten (Mitarbeiter/Kunde): Status-Gruppenüberschriften über den
   Tabellen und der Stammdaten-Block des Kunden-Profils */
.profil-gruppe {
  display: flex;
  align-items: center;
  gap: var(--a2);
  margin: var(--a4) 0 var(--a2);
}
.profil-stammzeilen {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--a3) var(--a5);
}
.stammzeile-titel {
  display: block;
  color: var(--text-2);
  font-size: var(--groesse-xs);
  margin-bottom: 2px;
}
.stammzeile-anschrift { white-space: pre-line; }

/* Ergebnisseite /suche: Suchfeld + Personen-Filter + Typ-Checkboxen */
.suchfilter input[type="search"] { flex: 1 1 220px; margin-top: 0; }
.suchfilter select { width: auto; margin-top: 0; }
.suchfilter-typen { margin-top: var(--a2); }
.suchfilter-typ {
  display: inline-flex;
  align-items: center;
  gap: var(--a1);
  font-size: var(--groesse-s);
  cursor: pointer;
}
.benutzer-menue { position: relative; }
.benutzer-menue summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--a2);
  padding: var(--a1) var(--a3) var(--a1) var(--a1);
  border-radius: var(--radius-voll);
  color: var(--text-2);
  font-size: var(--groesse-s);
  font-weight: 500;
}
/* V2 (28.09.2026, gemessen in der Bedienprobe): Ohne nowrap brach der Name bei 1366 px am
   Bindestrich um, sobald eine senkrechte Bildlaufleiste 15 px Breite nahm — die Kopfzeile
   sprang von 70 auf 93 px, und ein Klick auf „Abschließen" traf zwischen mousedown und
   mouseup die Kopfleiste. Jetzt gibt die Suchspalte (minmax 240–480 px) nach. */
.benutzer-menue summary { white-space: nowrap; }
.benutzer-menue summary::-webkit-details-marker { display: none; }
.benutzer-menue summary:hover { background: var(--hover-flaeche); }
.benutzer-menue .menue-liste {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  min-width: 11rem;
  background: var(--flaeche);
  border-radius: var(--radius);
  box-shadow: var(--schatten-hebt);
  padding: var(--a1);
  display: flex;
  flex-direction: column;
  z-index: 30;
}
.menue-liste a {
  padding: var(--a2) var(--a3);
  border-radius: 8px;
  color: var(--text);
  font-size: var(--groesse-s);
}
.menue-liste a:hover { background: var(--hover-flaeche); text-decoration: none; }

/* Abmelden ist seit dem 18.08.2026 ein FORMULAR, kein Link (N1:
   `/logout` als GET liess sich von einer fremden Seite auslösen). Der
   Knopf soll dabei aussehen wie die Links daneben — sonst steht im Menü
   plötzlich ein grauer Kasten unter zwei Textzeilen.

   ⚠ DIE WERTE SIND VON `.menue-liste a` ABGESCHRIEBEN, nicht neu
   erfunden: dieselben Abstände, derselbe Radius, dieselbe Schriftgrösse.
   Wer dort etwas ändert, ändert es hier mit. */
.menue-liste .abmelden-form { display: contents; }
.menue-liste .abmelden-knopf {
  padding: var(--a2) var(--a3);
  border-radius: 8px;
  color: var(--text);
  font-size: var(--groesse-s);
  background: none;
  border: 0;
  text-align: left;
  width: 100%;
  cursor: pointer;
  font-family: inherit;
}
.menue-liste .abmelden-knopf:hover { background: var(--hover-flaeche); }

/* Schmale Fenster: Icon-Spalte erzwingen, Inhalt nie zerdruecken */
@media (max-width: 1100px) {
  .app-raster { grid-template-columns: 64px minmax(0, 1fr); }
  /* Zweite Haelfte der Vertauschung — siehe den Hinweis an
     `body.leiste-zu .odin-marke` weiter oben. */
  .nav-text, .nav-titel, .odin-marke { display: none; }
  .logo-kompakt { display: inline-flex; }
  .seitenleiste { padding: var(--a4) var(--a2); }
  .seitenleiste .marke { justify-content: center; }
  .nav-punkt { justify-content: center; }
  .leiste-fuss { display: none; }  /* Zustand ist hier ohnehin erzwungen */
}

/* ---------- Eigenschafts-Chips ----------
   Grau = inaktiv, farbig = aktiv. Deutlich als Schalter erkennbar:
   inaktive Chips haben Rand + vollen Textkontrast (WCAG AA), nicht nur
   Blässe. Gleiche Optik für Checkbox-Chips (Neu-Formular) und
   Button-Chips (Detailansicht, HTMX). */
.chips { display: flex; gap: var(--a2); flex-wrap: wrap; margin-top: var(--a1); }
.chip-schalter input[type="checkbox"] {
  position: absolute; width: 1px; height: 1px; margin: 0;
  opacity: 0; pointer-events: none;
}
/* NICHT `button.chip-knopf`: Seit dem 29.07.2026 gibt es Chips auch als
   <span> — der abgeleitete Lagerware-Chip und, fuer Rollen ohne
   `chip_umschalten`, alle Chips. Am Element haengt nur, OB man klicken
   kann; wie ein Chip aussieht, entscheidet die Klasse. Mit dem alten
   Selektor blieben die Spans voellig ungeformt (kein Rand, kein Radius,
   kein inline-flex) und fielen aus der Reihe. */
.chip-schalter span, .chip-knopf {
  display: inline-flex; align-items: center; gap: var(--a1);
  padding: 6px var(--a4); min-height: 32px;
  border-radius: var(--radius-voll);
  border: 1px solid var(--text-3);
  background: var(--flaeche-2);
  color: var(--text);
  font-size: var(--groesse-s); font-weight: 500;
  cursor: pointer;
  transition: background var(--dauer) var(--kurve),
              border-color var(--dauer) var(--kurve),
              color var(--dauer) var(--kurve);
}
.chip-schalter input:checked + span, .chip-knopf.aktiv {
  background: var(--akzent); border-color: var(--akzent); color: #fff;
}
.chip-schalter input:focus-visible + span {
  outline: 2px solid var(--akzent); outline-offset: 2px;
}
/* Strecke: abgeleiteter (automatischer) Zustand unterscheidbar von manuell */
/* Nicht setzbarer Chip (Lagerware): sieht aus wie ein abgeleiteter,
   ist aber ein <span> — kein Zeigefinger, kein Hover-Effekt. */
/* `nicht-setzbar` sagt nur „nicht klickbar" — es faerbt NICHT. Sonst
   saehe ein INAKTIVER Chip in der Nur-Anzeige aus wie ein aktiver. */
.chip-knopf.nicht-setzbar { cursor: default; }
.chip-knopf.abgeleitet {
  background: var(--akzent-flaeche); border-color: var(--akzent);
  color: var(--akzent-hover); font-style: italic;
}
.bs-chips { margin-bottom: var(--a4); }
/* ⚠ HIER STANDEN SECHS REGELN FÜR DEN LABELS-AUFKLAPPER und sind am
   11.08.2026 ERSATZLOS entfallen: `> summary` (flex-Zeile),
   `::-webkit-details-marker`, `::before` mit dem „▸", die Drehung bei
   `[open]`, `:focus-visible` und `> summary .chips`.

   Der Labels-Block ist seit dem Wegfall des Aufklappers ein `<div>`
   ohne `<summary>` — keine dieser Regeln griff noch irgendwo.

   ⚠ ICH HATTE ZUERST NUR DREI DAVON GEFUNDEN. Die übrigen drei fand
   der Wächter `test_die_tote_labels_regel_ist_weg`, weil er auf
   `labels-block > summary` prüft und nicht auf die drei Regeln, die
   ich im Kopf hatte. Toter CSS-Code meldet sich nie: Er bleibt stehen,
   sieht nach Absicht aus und wird beim nächsten Umbau mitgepflegt.

   Die Chip-Reihe selbst braucht nichts davon — `.bs-chips` und
   `.chips` tragen Abstand und Umbruch. */
.chip-warnung {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--a3); flex-wrap: wrap;
  background: var(--warnung-flaeche);
  border: 1px solid var(--warnung);
  border-radius: var(--radius);
  padding: var(--a2) var(--a3);
  margin-bottom: var(--a3);
  color: var(--warnung);
  font-weight: 500;
}
/* Warnender Rand: EILIG ODER VERZUG (Auftrag Team, 24.08.2026).

   ⚠ HIER STAND `.karte.eilig` UND `.detail-kopf.eilig`. Die Klasse
   heisst jetzt `warnt`, weil sie seit dem 24.08.2026 ZWEI Gründe hat.
   Ein zweiter Randton für Verzug wäre eine Unterscheidung, die niemand
   sieht — die Kandidatentöne liegen bei 1,01 bis 1,06:1 zueinander
   (gemessen 11.08.2026, Stil der Bürotafel). Der Rand sagt „hier ist
   etwas"; WAS, sagen die Chips, und die tragen Wörter.

   ⚠ DIE ALTEN KLASSEN SIND ERSATZLOS WEG, nicht als Alias behalten:
   Ein `.karte.eilig`, das noch etwas färbte, hielte die Frage offen,
   welche der beiden Regeln greift — und der nächste Leser hielte die
   tote für die lebende. Wächter: `test_verzug_auffaellig`. */
.karte.warnt { border-left: 3px solid var(--fehler); }
.detail-kopf.warnt { border-left: 4px solid var(--fehler); }
.detail-kopf .nummer .chip { vertical-align: 3px; margin-left: var(--a2); }

/* Dashboard-Kacheln: kompakte Info-Leiste statt großer Kästen — das
   Board ist die Hauptsache der Übersicht. Alle vier Kacheln haben
   dieselbe Struktur (Label + Wert) und über die feste Flex-Basis
   dieselbe Breite — keine Zusatztexte, die die Reihe sprengen.
   Warn-Kacheln tragen die Semantik im LABEL — Farbe nur zusätzlich. */
.kacheln {
  display: flex;
  flex-wrap: wrap;
  gap: var(--a2);
  margin-bottom: var(--a4);
}
.kachel {
  flex: 0 1 220px;
  min-width: 180px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--a2);
  background: var(--flaeche);
  border-radius: var(--radius);
  box-shadow: var(--schatten-ruhe);
  padding: var(--a1) var(--a3);
  color: var(--text);
  transition: box-shadow var(--dauer) var(--kurve);
}
.kachel:hover { box-shadow: var(--schatten-hover); text-decoration: none; }
.kachel-label { font-size: var(--groesse-s); color: var(--text-2); font-weight: 500; }
.kachel-wert { font-size: var(--groesse-m); font-weight: 650; line-height: 1.2; }
.kachel-warnt { border-left: 3px solid var(--fehler); }
.kachel-warnt .kachel-wert { color: var(--fehler); }
.dashboard-gruppe { margin: var(--a3) 0 var(--a1); font-size: var(--groesse-s); color: var(--text-2); }
.dashboard-liste li { padding: var(--a1) 0; font-size: var(--groesse-s); }
/* Erlaeuterung UNTER einer Hinweisgruppe (N1, 01.08.2026): eine
   Einschraenkung, die zur Liste gehoert, aber an keiner einzelnen Zeile
   haengt. Kleiner und blasser als die Eintraege — sie soll erklaeren,
   nicht mitzaehlen. */
.hinweis-fussnote {
  margin: var(--a1) 0 var(--a2);
  font-size: var(--groesse-xs);
  color: var(--text-2);
  line-height: 1.4;
}

/* CHIP RECHTSBUENDIG, feste Position (29.07.2026).
   
   GEMELDET wurde: „die Anzeige steht mal neben dem Kunden, mal
   darunter". VERMUTET wurde uneinheitliche Programmierung — zwei
   Templates oder zwei Zweige. TATSAECHLICH ist es Zeilenumbruch: Es gibt
   genau EIN Template (partials/aufmerksamkeit.html), alle 13 Bloecke
   haben dieselbe Struktur `<a>Nummer</a> · Kunde <span class="chip">`,
   und alles stand inline. Das Panel ist `width: min(440px, 92vw)` — bei
   kurzen Kundennamen passte der Chip daneben, bei langen rutschte er in
   die naechste Zeile. Es hing am NAMEN, nicht am Hinweistyp.

   `margin-left: auto` schiebt den Chip immer an den rechten Rand. Damit
   steht er an derselben Stelle, egal wie lang der Name ist, und bei
   kurzen Namen entsteht keine halbleere Zeile.

   BEI SEHR LANGEN NAMEN BRICHT DER NAME UM, der Chip bleibt rechts auf
   Hoehe der ersten Zeile (`align-items: baseline`). Bewusst so und nicht
   gekuerzt: Der laengste Kundenname im Bestand hat 121 Zeichen
   („Hochschule Osnabrueck Laborbereich …", gemessen 29.07.2026) — mit
   Ellipse waere der Kunde nicht mehr zu erkennen, und genau dafuer steht
   der Name da. Eine hoehere Zeile kostet nichts, ein unlesbarer Name
   kostet einen Klick.

   `flex: 0 0 auto` am Chip: Er darf NIE schrumpfen. Sonst wuerde bei
   langen Namen der Chiptext umbrochen statt der Name. */
.dashboard-liste li {
  display: flex;
  align-items: baseline;
  gap: var(--a1);
}
.dashboard-liste li > a { flex: 0 0 auto; }
.dashboard-liste .chip { margin-left: auto; flex: 0 0 auto; }

/* Ticket-Layout der Detailseiten: Arbeit links, zweispaltiges
   Details-Panel rechts (nur die Titelzeile klebt).
   Schmaler als 1500px: Panel rutscht NACH OBEN.

   BEIDE SPALTEN GLEICH BREIT (Entscheid Eric 06.08.2026). Vorher stand
   hier `minmax(0, 1fr) 600px` — die rechte Spalte war ein fester
   Pixelwert, die linke bekam den Rest. Das Verhaeltnis hing damit am
   Fenster und kippte unterwegs: bei 1920px war links 880 und rechts 600,
   bei 1600px 656 zu 600, bei 1440px 504 zu 600 — die „breite"
   Arbeitsspalte war dort bereits SCHMALER als das Panel.

   GEMESSEN 06.08.2026 bei 1920px Fenster: neben der Seitenleiste (240px)
   bleiben 1680px, `main` deckelt auf 100rem = 1600px und nimmt 48px
   Polster je Seite, macht 1504px Rasterbreite. Minus `gap` bleiben je
   Spalte 740px. Ob die Seitenleiste eingeklappt ist (64px), aendert
   NICHTS — der 1600px-Deckel greift in beiden Faellen.

   Die Positionsliste wohnt im RECHTEN Panel und gewinnt damit 140px:
   nutzbare Textbreite der Positionszeile 464px -> 604px. Genau daraus
   kommt der Platz fuer die drei Lagerfelder in der Kopfzeile.

   Nachgemessen am linken Bereich, damit die Verengung von 880 auf 740
   belegt und nicht behauptet ist: Der Begleitschein bricht NICHT um.
   Sein laengstes Label („Vorkasse-Rechnung vom Lieferanten erhalten",
   334px in Arimo) hat neben einem gesetzten Erledigt-Vermerk noch 383px
   statt 523px — es passt, aber die Reserve faellt von 189px auf 49px.
   ⚠ DARAN HAENGT EINE GRENZE: Der Erledigt-Vermerk („TT.MM.JJJJ HH:MM ·
   Name") darf ab jetzt rund 299px breit werden, also etwa 38 Zeichen.
   Ein Benutzername ueber ~25 Zeichen kippt die laengste Zeile in einen
   zweiten Umbruch. */
.ticket-raster {
  display: grid;
  /* minmax(0, …) statt blossem 1fr: sonst setzt der Inhalt (breite
     Tabellen auf der Bestellseite) die Untergrenze und sprengt die
     Spalte. Mit minmax(0, …) scrollt stattdessen .tabelle-umschlag. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  /* ZEILENHOEHEN AUSDRUECKLICH (Befund Devbox 28.07.2026):
     Ohne diese Zeile sind beide Zeilen `auto`. Das Details-Panel spannt
     ueber BEIDE (grid-row: 1 / span 2) — ist es hoeher als
     Begleitschein + Abstand + Verlauf, verteilt Grid die Ueberhoehe auf
     beide Zeilen. Zeile 1 wird dadurch hoeher als der Begleitschein,
     und die Luecke darunter waechst mit der Hoehe des RECHTEN Panels.
     `align-items: start` half nicht: Es setzt das Item an den
     Zeilenanfang, macht die Zeile aber nicht schmaler.

     `auto 1fr`: Zeile 1 bekommt genau die Hoehe ihres Inhalts, alles
     Weitere geht an Zeile 2. Der Abstand zwischen Begleitschein und
     Verlauf ist damit immer `gap` — unabhaengig von Eintragszahl und
     Panel-Hoehe. */
  grid-template-rows: auto 1fr;
  gap: var(--a5);
  align-items: start;
}
/* NICHT das ganze Panel kleben lassen (Befund Devbox 28.07.2026):
   Es war hoeher als das Fenster und versteckte damit seinen eigenen
   unteren Teil — der Dokumentenbereich am Ende war so gar nicht
   erreichbar. Jetzt klebt nur die Titelzeile (.panel-titel), der
   Inhalt scrollt normal durch. */
.ticket-details { align-self: start; }

/* Klebende Titelzeile des Auftrags-Panels.

   Der DECKENDE HINTERGRUND ist Pflicht — ohne ihn scrollt der Text
   darunter sichtbar durch. Die negativen Aussenabstaende plus
   gleiche Innenabstaende ziehen den Hintergrund bis an die
   Kastenraender: Sonst schaut der Inhalt seitlich am Titel vorbei,
   weil .kasten ringsum padding hat.

   top: 0 genuegt — auf dieser Seite klebt sonst nichts ueber dem
   Inhalt. Die Seitenleiste klebt zwar auch, steht aber in einer
   eigenen Rasterspalte DANEBEN, und die Kopfzeile in base.html ist
   nicht sticky (beides am 28.07.2026 geprueft). */
/* Die beiden Spaltenkoepfe sollen auf DERSELBEN optischen Ebene liegen:
   links „Begleitschein" (h2 in .bs-kopfzeile), rechts die Auftragsnummer.
   Deshalb dieselbe Schriftgroesse und derselbe Abstand nach unten wie
   dort — vorher war die Nummer mit 1.15rem/700 sichtbar anders gesetzt
   und sass optisch tiefer. */
.panel-titel .panel-nummer {
  font-size: var(--groesse-l);
  font-weight: 650;
  letter-spacing: -0.01em;
}
/* Kästen IM Raster brauchen kein unteres Margin — den Abstand zu den
   Vollbreite-Blöcken darunter setzt das Raster selbst. */
/* Zweispalten-Raster der Auftragsdetails (Umbau 28.07.2026):
     oben links  Begleitschein    oben rechts  Auftragsdetails
     unten links Verlauf          unten rechts Dokumente
   Die Zuordnung steht EXPLIZIT, nicht ueber die DOM-Reihenfolge: So
   bleibt im schmalen Fenster die gewohnte Abfolge erhalten (Details,
   Begleitschein, Dokumente, Verlauf), waehrend breit die gewuenschte
   Anordnung gilt. Ohne die Angaben wuerde Grid zeilenweise fuellen und
   die Dokumente linksrum setzen.

   Gleiche Form und Breite ergeben sich von selbst: Beide unteren
   Kaesten liegen in denselben Spalten wie die oberen. */
.ticket-arbeit     { grid-column: 1; grid-row: 1; }
.ticket-kommentare { grid-column: 1; grid-row: 2; }
/* Die Details ziehen sich ueber BEIDE Zeilen — sie enthalten seit dem
   28.07.2026 auch die Dokumente und sind entsprechend hoch. */
.ticket-details    { grid-column: 2; grid-row: 1 / span 2; }

.ticket-raster .kasten { margin-bottom: 0; }
.ticket-raster { margin-bottom: var(--a5); }
.panel-abschnitt {
  padding: var(--a3) 0;
  border-top: 1px solid var(--linie);
}
.panel-abschnitt:first-child { padding-top: 0; border-top: none; }
.panel-abschnitt:last-child { padding-bottom: 0; }

/* GEMESSEN 28.07.2026, warum die Zeile schief sass:

   Der Kasten hat ringsum padding: var(--a5) = 24px. Die negativen
   Aussenabstaende ziehen den Titel darueber hinaus bis an die
   Kastenraender — noetig, damit der deckende Hintergrund die
   ganze Breite bekommt und kein Inhalt seitlich daran vorbeiscrollt.

   Das eigene padding muss dieses Minus AUSGLEICHEN, sonst steht der
   Text an anderer Stelle als der uebrige Panel-Inhalt. Vorher stand
   dort `padding: var(--a3) var(--a5)` — seitlich richtig, oben aber
   12px statt 24px. Und selbst die 12px kamen nicht an: Die spaeter
   stehende Regel `.panel-abschnitt:first-child` (gleiche
   Spezifitaet, 0-2-0) setzte padding-top auf 0, der Text klebte am
   oberen Kastenrand.

   Jetzt ausgeglichen und mit .panel-abschnitt.panel-titel notiert,
   damit die Regel gegen :first-child gewinnt:
     oben    24px  = wie der Kasten (Begleitschein-h2 ebenso)
     seitlich 24px = wie der Kasten
     unten   12px  = wie .bs-kopfzeile margin-bottom */
.panel-abschnitt.panel-titel {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--flaeche);
  margin: calc(-1 * var(--a5)) calc(-1 * var(--a5)) 0;
  padding: var(--a5) var(--a5) var(--a3);
  border-top: none;
  border-bottom: 1px solid var(--linie);
}
/* Vorgangsnummer als Panel-Überschrift (die Kopfzeile ist entfallen). */
.panel-nummer {
  font-weight: 700;
  font-size: 1.15rem;
  overflow-wrap: anywhere;
}

/* Vorgangshinweis: die `notiz` des Vorgangs, direkt unter der Nummer.
   Auf allen DREI Detailseiten (Auftrag, Anfrage, Bestellung) — sie
   haben dasselbe Feld und zeigten es vorher gleich.

   ERSETZT `.hinweis` AN GENAU DIESEN DREI STELLEN, nicht überall:
   `.hinweis` ist mit 121 Verwendungen in 34 Templates die allgemeine
   Klasse für Nebentext und bleibt unverändert bestehen. Ein Hinweis in
   der Kopfzeile ist etwas anderes als eine Fussnote unter einer Liste.

   FARBE `--warnung` AUF `--warnung-flaeche`, NICHT `--akzent`
   (Entscheid Eric 06.08.2026): `--akzent` bedeutet in dieser
   Oberfläche „Link" (die Grundregel `a { color: var(--akzent) }` ist
   die einzige Quelle des Rots, auch beim Kundennamen). Rot ohne
   Klickziel würde das aufweichen. Dieselben Tokens benutzt
   `.warnzeile-warnung` darunter, und sie sind dort als AA-tauglich auf
   hellen Flächen vermerkt.

   GRÖSSE BLEIBT 15px. Auffälligkeit kommt aus der Fläche, nicht aus
   der Schriftgrösse: Bei 22px passen an der engsten Stelle (Panel
   581px bei 1501px Fenster) nur 35 Zeichen — weniger, als ein
   typischer Hinweis braucht.

   ANFÜHRUNGSZEICHEN SIND WEG. Sie standen vorher im Template und
   deuteten ein Zitat an; der Hinweis ist aber eine Ansage, keine
   wiedergegebene Äusserung.

   ⚠ AUF ZWEI ZEILEN GEDECKELT, und das ist die HÄLFTE des Schutzes.
   Die Kopfzeile des Auftrags-Panels KLEBT (`.panel-abschnitt.panel-titel`,
   `position: sticky`) und bleibt dabei im normalen Fluss: Wächst sie,
   rutscht alles darunter mit — gemessen 70px einzeilig, 92,5px
   zweizeilig, je weitere Textzeile 22,5px. Die andere Hälfte ist die
   Längengrenze im Service (`services.pruefe_hinweislaenge`, 80
   Zeichen). Keine der beiden allein hält die Höhe fest: Ohne Deckel
   kann ein Bestandswert von vor der Grenze mehrzeilig werden, ohne
   Grenze wäre der Rest stillschweigend abgeschnitten.

   Auf Anfrage- und Bestellseite klebt die Kopfzeile NICHT (beide
   öffnen mit `.panel-abschnitt` ohne `.panel-titel`, geprüft
   06.08.2026). Der Deckel gilt dort trotzdem — nicht wegen der Höhe,
   sondern damit die drei Seiten gleich aussehen. */
.vorgangshinweis {
  margin-top: var(--a2);
  padding: var(--a2) var(--a3);
  border-radius: 6px;
  background: var(--warnung-flaeche);
  border: 1px solid var(--warnung);
  color: var(--warnung);
  font-size: var(--groesse-s);
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

/* Status-Hinweise mit Achtung-Charakter oben im Details-Panel.
   Farben = bestehende Warn-Tokens (AA auf den hellen Flächen). */
.warnzeile {
  padding: var(--a2) var(--a3);
  border-radius: 6px;
  font-size: 0.85rem;
  font-weight: 600;
  margin-bottom: var(--a2);
}
.warnzeile-warnung {
  background: var(--warnung-flaeche);
  color: var(--warnung);
  border: 1px solid var(--warnung);
}
.warnzeile-fehler {
  background: var(--fehler-flaeche);
  color: var(--fehler);
  border: 1px solid var(--fehler);
}
.warnzeile-ok {
  background: var(--ok-flaeche);
  color: var(--ok);
  border: 1px solid var(--ok);
  font-weight: 500;
}
.panel-abschnitt .bs-kopf-titel { margin-bottom: var(--a1); }
/* Zuweisung im Panel: die eigene Trennlinie des Partials entfällt hier. */
.ticket-details .zuweisung { border-top: none; margin-top: 0; padding-top: 0; }

/* Zweispaltige Feldliste im Panel (Jira-Stil): Label-Spalte links,
   Wert-Spalte rechts, Zeile für Zeile. Komplexe Elemente (Status-Menü,
   Zuständig-Combobox, Chips) sind einfach Wert-Zellen. */
.panel-felder {
  display: grid;
  grid-template-columns: 140px minmax(0, 1fr);
  gap: var(--a3) var(--a3);
  align-items: baseline;
}
.panel-feldname {
  color: var(--rolle-label-farbe);
  font-size: var(--rolle-label-groesse);
  font-weight: 550;
}
.panel-feldwert { min-width: 0; font-size: var(--rolle-titel-groesse); }
.panel-feldwert .bs-kopf-name { margin: 0; }

@media (max-width: 1500px) {
  .ticket-raster { grid-template-columns: 1fr; }
  /* Eine Spalte: Die Zuordnung oben wuerde sonst Zeilen erzwingen und
     Luecken lassen. `order` bestimmt hier die Abfolge — unveraendert
     gegenueber vorher: Details, Begleitschein, Dokumente, Verlauf. */
  .ticket-arbeit, .ticket-details,
  .ticket-kommentare { grid-column: auto; grid-row: auto; }
  .ticket-details {
    order: -1;               /* Details ÜBER dem Begleitschein */
    position: static;
    max-height: none;
  }
  .ticket-arbeit     { order: 0; }
  .ticket-kommentare { order: 1; }
  /* Schmal klebt die Titelzeile nicht: Sie stuende sonst ueber dem
     Begleitschein, waehrend man dort arbeitet. */
  .panel-titel { position: static; }
}

/* Zuständig-Element (Jira-Assignee): Avatar-Initialen, Übergeben,
   „mir zuweisen“, „zurück an vorherigen“, aufklappbarer Verlauf. */
.zuweisung {
  display: flex;
  align-items: center;
  gap: var(--a3);
  flex-wrap: wrap;
  border-top: 1px solid var(--linie);
  margin-top: var(--a3);
  padding-top: var(--a3);
}
/* Grundoptik ungescoped: die Bubble sieht überall gleich aus (Zuweisung,
   Kopfzeile, Suche, Statistik, Board-Karte) — vorher hing sie an
   .zuweisung und die avatar-klein-Stellen blieben ungestylt. */
.avatar {
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--akzent-flaeche);
  color: var(--akzent-hover);
  font-weight: 650;
  font-size: var(--groesse-s);
}
.zuweisung .avatar {
  flex: 0 0 36px;
  width: 36px;
  height: 36px;
}
/* ══ DER NAME IST DAS FELD (C1, 07.08.2026 — Entscheid Eric) ══
   Die erste Fassung desselben Tages stellte das Eingabefeld NEBEN den
   Namen; am Schirm las sich der Name dadurch wie eine Beschriftung des
   Feldes. Jetzt teilen sich beide EINEN Platz: `.zustaendig-tausch`
   haelt Name und Feld, immer genau eines davon sichtbar.

   `flex: 1 1 12rem` nimmt den Rest der Zeile — bei 540px Wertspalte
   bleiben neben Avatar (36+12) und „Mir zuweisen" (108+12) rund 372px
   — und bricht erst um, wenn 12rem nicht mehr uebrig sind (schmale
   Fenster, Anfrage- und Bestellseite). `min-width: 0` ist Pflicht,
   sonst setzt der laengste Name die Untergrenze und sprengt die
   Spalte. `position: relative` traegt die Vorschlagsliste. */
.zustaendig-tausch {
  flex: 1 1 12rem;
  min-width: 0;
  position: relative;
}
.zuweisung-feld { margin: 0; }
/* Ohne diese Zeile bliebe das Formular sichtbar: `hidden` setzt nur
   `display: none` mit der schwaechsten Spezifitaet, und schon eine
   Layout-Regel am selben Element schlaegt sie. Hier stuenden sonst
   Name UND Feld gleichzeitig da. */
.zuweisung-feld[hidden] { display: none; }
/* Die Feld-Grundregel gibt jedem input `margin-top: var(--a1)` — hier
   wuerde das die Zeile gegen den Avatar verschieben. */
.zuweisung-feld .personen-eingabe { margin-top: 0; }

/* Der Name als Klickziel. Er soll wie TEXT aussehen, nicht wie ein
   Knopf — deshalb wird die Knopf-Grundoptik zurueckgenommen. Dass er
   bedienbar ist, sagt der Zeiger, die gepunktete Unterlinie und der
   Hover; ein voller Knopfrahmen haette den Namen zur Schaltflaeche
   gemacht und genau die Ruhe genommen, wegen der der Dialog wegfiel.
   `type="button"` — die rote Submit-Grundregel greift hier nicht. */
.zustaendig-oeffner {
  display: block;
  width: 100%;
  min-height: 0;
  margin: 0;
  padding: 2px 4px;
  border: none;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-weight: 650;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-decoration: underline dotted var(--text-3);
  text-underline-offset: 3px;
}
.zustaendig-oeffner:hover,
.zustaendig-oeffner:focus-visible {
  background: var(--hover-flaeche);
  text-decoration-color: var(--akzent);
}
/* C3 (Entscheid Eric): Ist niemand zustaendig, ist der Platzhaltertext
   das Klickziel — dieselbe Stelle, dieselbe Geste. Er traegt die
   Meta-Farbe, damit „nicht zugewiesen" nicht wie ein Name aussieht,
   bleibt aber genauso bedienbar. */
.zustaendig-oeffner.ist-leer { color: var(--text-3); font-weight: 400; }
.zuweisung-mir { margin: 0; flex: 0 0 auto; }
.zuweisung-info { display: flex; flex-direction: column; min-width: 9rem; }
.avatar-klein { flex-basis: 26px; width: 26px; height: 26px;
  font-size: var(--groesse-xs); margin-right: var(--a1);
  display: inline-flex; vertical-align: middle; }
.zuweisung-name { font-weight: 650; }
.personen-feld .personen-eingabe { min-height: 36px; margin-top: 0; padding: 6px var(--a3); width: 100%; }
.personen-feld .vorschlaege { min-width: 240px; right: auto; }
/* Z1 (27.09.2026): Die Liste zeigt ohne Eingabe ALLE zuweisbaren Konten —
   vorher schnitt /benutzer/suche nach acht Namen ab, und wer hinten im
   Alphabet stand, war nur über Tippen zu finden. Jetzt scrollt sie
   (`overflow-y`, nicht `hidden` wie die Grundregel .vorschlaege). */
.personen-feld .vorschlaege, .erwaehnung-feld .vorschlaege { max-height: min(50vh, 360px); overflow-y: auto; }

/* @-Erwähnungen: Vorschlagsliste unterm Kommentarfeld, erwähnte Namen
   dezent im Akzentton, verlinkt aufs Mitarbeiter-Profil. */
.nachricht-form .erwaehnung-feld { align-self: stretch; }
.erwaehnung-feld .erwaehnung-eingabe { width: 100%; }
.erwaehnung-feld .vorschlaege { min-width: 240px; right: auto; }
a.erwaehnung {
  color: var(--akzent);
  font-weight: 550;
  text-decoration: none;
}
a.erwaehnung:hover { text-decoration: underline; }

/* Glöckchen (Kopfzeile) + Benachrichtigungs-Panel. Badge nutzt die
   bestehende .nav-badge-Optik; ungelesene Einträge tragen einen
   Akzent-Balken, gelesene sind ausgegraut. */
.glocke {
  position: relative;
  display: inline-flex;
  align-items: center;
  background: none;
  border: none;
  padding: 6px;
  cursor: pointer;
  color: var(--text-2);
  border-radius: var(--radius);
}
.glocke:hover { color: var(--text); background: var(--hover-flaeche); }
.glocke .nav-badge-halter {
  position: absolute;
  top: -2px; right: -4px;
  margin-left: 0;
}
.benachrichtigungen { list-style: none; margin: 0; padding: 0; }
.benachrichtigungen-aktionen { text-align: right; margin-bottom: var(--a2); }
.benachrichtigung {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0 var(--a2);
  padding: var(--a2) var(--a2);
  border-bottom: 1px solid var(--linie);
  color: var(--text-2);
}
.benachrichtigung a { color: inherit; text-decoration: none; }
.benachrichtigung a:hover { text-decoration: underline; }
.benachrichtigung .meta { grid-column: 1; font-size: var(--groesse-xs); }
.benachrichtigung .gelesen-knopf { grid-row: 1 / span 2; align-self: center; }
.benachrichtigung.ungelesen {
  color: var(--text);
  border-left: 3px solid var(--akzent);
  background: var(--flaeche-2);
}

/* Beobachter-Element im Details-Panel. */
/* ══ BEOBACHTER WAAGERECHT (U4, 07.08.2026) ══
   Vorher standen Auge-Knopf, Beobachterliste und „Beobachter
   hinzufügen" in drei gestapelten Bloecken — drei Beobachter kamen so
   auf 139px Hoehe, waehrend von 540px Spaltenbreite hoechstens 184px
   gebraucht wurden. Jetzt ist das Element selbst eine umbrechende
   Flex-Zeile: Alles steht nebeneinander und bricht erst um, wenn es
   wirklich nicht mehr passt. */
.beobachtung-element {
  margin-top: var(--a3);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--a1) var(--a2);
}
.beobachtung-kopf {
  display: flex;
  align-items: center;
  gap: var(--a2);
}
.auge-knopf { display: inline-flex; align-items: center; gap: var(--a1); }
/* Aktiv („Beobachtest du“): dezente Akzentfläche statt Farbwechsel —
   die Textfarbe ist über .leise ohnehin akzentrot. */
.auge-knopf.aktiv { background: var(--akzent-flaeche); }
/* Die Liste laeuft in der Zeile mit (U4) und bricht selbst um, statt
   je Beobachter eine eigene Zeile zu belegen. `justify-content:
   space-between` ist weg: Es zog Name und × in einer vollbreiten Zeile
   an die entgegengesetzten Raender — sinnvoll, solange jeder Eintrag
   eine eigene Zeile hatte, sinnlos, sobald sie nebeneinander stehen. */
.beobachter {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--a1) var(--a2);
  min-width: 0;
}
.beobachter li {
  display: inline-flex;
  align-items: center;
  gap: var(--a1);
  font-size: var(--groesse-s);
  white-space: nowrap;
}
.beobachter li a { color: var(--text); }
.beobachter-hinzu { margin: 0; }
.beobachter-hinzu summary { cursor: pointer; }

/* Edit-Modus des Begleitscheins: „Bearbeiten“ toggelt die Klasse am
   #begleitschein-bereich (überlebt HTMX-Swaps); Verwaltungs-Elemente
   (.nur-bearbeiten: Entfernen-Knöpfe, Forderungs-Löschen/-Anlegen)
   sind sonst ausgeblendet. */
.bs-kopfzeile {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--a3);
  margin-bottom: var(--a3);
}
#begleitschein-bereich:not(.bearbeiten-modus) .nur-bearbeiten { display: none; }
#bs-bearbeiten[aria-pressed="true"] {
  background: var(--akzent-flaeche);
  color: var(--akzent-hover);
}

/* Aufklapper „Weitere Schritte (n)“ (Schutzregel 4 im Zwei-Ebenen-
   Modell): alle inaktiven Zeilen — chip-inaktiv und fall-ausgeblendet —
   gesammelt, ausgegraut, einzeln aktivierbar. */
.bs-weitere { margin-top: var(--a4); }
.bs-weitere summary {
  color: var(--text-2);
  font-size: var(--groesse-s);
  font-weight: 550;
  cursor: pointer;
}
.bs-weitere li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--a2);
}

/* Forderungs-Punkte unter „Weitere Schritte“: Checkbox-Zeile wie die
   festen Schritte, zusätzlich ×-Löschen; darunter die Hinzufügen-Zeile. */
.forderung-zeile { display: flex; align-items: flex-start; gap: var(--a2); }
.forderung-zeile label { flex: 1; min-width: 0; }

/* Forderungen einordnen per Ziehen (04.08.2026).
   Der ANFASSER traegt das Ziehen, nicht die Zeile: So bleibt das
   Auswahlfeld darunter bedienbar.

   Er liegt im EDIT-MODUS, wie das Auswahlfeld (Entscheid Eric, ersetzt
   die fruehere Begruendung „ausserhalb, weil er nur ~16 px kostet"):
   Ziehen soll eine BEWUSSTE HANDLUNG sein, keine, die beim Scrollen
   passieren kann.

   ⚠ DAS `display: none` OBEN IST KEINE SPERRE, sondern eine Blende.
     Gesperrt wird woanders: Das `draggable`-Attribut steht nicht in
     der Vorlage, sondern setzt `initForderungZiehen` beim Einschalten
     des Modus — und `dragstart` prueft ihn noch einmal selbst. Wer
     hier etwas aendert, aendert nur das Aussehen.

   Warum es hier Ziehen gibt und auf dem Board nicht: siehe app.js bei
   `initForderungZiehen` und partials/begleitschein.html. */
.forderung-griff {
  cursor: grab;
  color: var(--text-3);
  font-size: var(--groesse-s);
  line-height: 1.4;
  padding: 0 2px;
  user-select: none;
}
.forderung-griff:active { cursor: grabbing; }
.forderung-zeile.wird-gezogen { opacity: 0.45; }
/* Die Einfuegemarke sitzt UNTER der Zielzeile und sagt damit
   "hierhinter". Oberhalb der ersten Zeile erscheint sie NIE: "ganz nach
   vorne" ist im Datenmodell nicht ausdrueckbar (Begruendung in app.js). */
/* Die Marke GANZ OBEN, vor der ersten Zeile (05.08.2026). Sie sitzt an
   der LISTE, nicht an einer Zeile: Ueber der ersten gibt es keine, an
   deren Unterkante sie haengen koennte. Gleiche Staerke und Farbe wie
   `.ziel-darunter`, damit beide als dasselbe Ding lesbar sind. */
.begleitschein.ziel-ganz-oben {
  box-shadow: inset 0 2px 0 0 var(--akzent);
}

.begleitschein li.ziel-darunter {
  box-shadow: 0 2px 0 0 var(--akzent);
}
.forderung-loeschen { flex: none; padding-top: 2px; }
.forderung-neu {
  display: flex;
  gap: var(--a2);
  align-items: center;
  margin-top: var(--a2);
}
.forderung-neu input {
  flex: 1;
  min-width: 0;
  margin: 0;
  min-height: 32px;
  font-size: var(--groesse-s);
}
.forderung-neu button { white-space: nowrap; }

/* Kommentar-Aktionen: dezente Zeile unterm Kommentar („Bearbeiten ·
   Löschen“, Jira-Stil), Bearbeiten-Formular klappt darunter auf. */
.nachricht-aktionen {
  display: flex;
  align-items: baseline;
  gap: var(--a2);
  margin-top: var(--a1);
}
.kommentar-aktion { display: inline; }
/* Schlichte Textlinks („Bearbeiten · Löschen“): auch der
   Löschen-SUBMIT — die rote Submit-Grundregel gewann sonst bei
   gleicher Spezifität als spätere Regel (Muster wie .leise). */
button.winzig, button[type="submit"].winzig {
  background: none;
  border: none;
  padding: 0;
  min-height: auto;
  color: var(--text-2);
  font-size: var(--groesse-xs);
  cursor: pointer;
  text-decoration: none;
}
button.winzig:hover, button[type="submit"].winzig:hover {
  background: none;
  color: var(--text);
  text-decoration: underline;
}
.kommentar-bearbeiten {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--a2);
  margin-top: var(--a1);
}
.kommentar-bearbeiten[hidden] { display: none; }  /* display:flex darf hidden nicht aushebeln */
.kommentar-bearbeiten textarea { align-self: stretch; }
.zuweisung-verlauf { flex-basis: 100%; font-size: var(--groesse-s); }
.zuweisung-verlauf summary { color: var(--text-2); cursor: pointer; }
.zuweisung-verlauf li { padding: 2px 0; }

/* Auftrags-Vorschau (Anlage aus Dokument) */
.vorschau-position {
  border-top: 1px solid var(--linie);
  padding-top: var(--a3);
  margin-top: var(--a3);
}
.vorschau-position:first-of-type { border-top: none; margin-top: 0; padding-top: 0; }
.kunde-neu { border: none; padding: var(--a3) 0 0; margin: 0; }
/* Kunde-Raster mit definierten Verhältnissen: Name braucht Raum
   (Firmennamen), die Kunden-Nr. ist kurz — 2:1; Anschrift über die
   volle Panel-Breite (.breit), Kundentyp und Vorkasse-Haken
   nebeneinander, der Haken auf der Feldlinie. */
.kunde-neu .feldraster { grid-template-columns: 2fr 1fr; }
.kunde-neu .inline-label { align-self: end; }
@media (max-width: 900px) {
  .kunde-neu .feldraster { grid-template-columns: 1fr; }
}

/* Anfrage-Detail: Status-Knöpfe und Gewinnen-Zeile nebeneinander */
.aktionszeile { display: flex; gap: var(--a2); align-items: center; flex-wrap: wrap; }
.gewinnen-zeile { margin-top: var(--a4); border-top: 1px solid var(--linie); padding-top: var(--a4); }
.gewinnen-zeile input { max-width: 16rem; }

/* ---------- Seitenraster ---------- */

/* Globaler Deckel für alle Seiten: 100rem (1600px) nutzt Full-HD gut aus
   und lässt bei 1920px noch ruhigen Rand; auf Laptops greift er nicht.
   Seitenrand wächst stufenlos mit dem Fenster. */
main {
  padding: var(--a6) clamp(var(--a4), 2.5vw, var(--a7)) var(--a7);
  max-width: 100rem;
  margin: 0 auto;
}
/* Übersicht: der Deckel fällt, das Board bekommt die ganze Breite
   (8 Status-Spalten — jeder Zentimeter zählt). */
main.voll-breit { max-width: none; }
.seite-schmal { max-width: 40rem; margin: 0 auto; }  /* Formulare bewusst schmal */
/* Datenreiche Formularseiten (Auftrag-Vorschau): spürbar breiter als
   seite-schmal, aber gedeckelt — 76rem ist die Haus-Obergrenze für
   Eingabe-Layouts (siehe .feldraster). */
.seite-breit { max-width: 76rem; margin: 0 auto; }
.seite-mittel { margin: 0 auto; }  /* füllt main; Innenlayouts begrenzen sich selbst */

.seitenkopf {
  display: flex;
  align-items: baseline;
  gap: var(--a4);
  flex-wrap: wrap;
  margin-bottom: var(--a5);
}
.seitenkopf .dazu { margin-left: auto; }

/* ---------- Flächen ---------- */

.kasten {
  background: var(--flaeche);
  border-radius: var(--radius-gross);
  box-shadow: var(--schatten-ruhe);
  padding: var(--a5);
  margin-bottom: var(--a5);
}
.kasten > h2, .kasten > h3 { margin-bottom: var(--a3); }

/* ---------- Buttons ---------- */

.knopf, button, [role="button"] {
  font-family: inherit;
  font-size: var(--groesse-s);
  font-weight: 500;
  border: none;
  border-radius: var(--radius);
  padding: 10px var(--a4);
  min-height: 40px;
  cursor: pointer;
  background: var(--flaeche-2);
  color: var(--text);
  transition: background var(--dauer) var(--kurve),
              transform var(--dauer) var(--kurve),
              box-shadow var(--dauer) var(--kurve);
}
button:hover, .knopf:hover { background: #e6e6e9; text-decoration: none; }
button:active, .knopf:active { transform: scale(0.98); }

.primaer, button[type="submit"] {
  background: var(--akzent);
  color: #fff;
}
.primaer:hover, button[type="submit"]:hover { background: var(--akzent-hover); }

/* Die höhere Spezifität ist Absicht: button[type="submit"] (rote
   Grundregel) schlägt sonst .leise — ein leiser Submit-Knopf (Auge-
   Toggle, „Mir zuweisen“, ×-Entfernen) würde zum roten Vollton-Balken. */
.leise, button[type="submit"].leise {
  background: transparent;
  color: var(--akzent);
}
.leise:hover, button[type="submit"].leise:hover { background: var(--akzent-flaeche); }

/* Doppelter Selektor aus demselben Grund wie bei .leise: Ohne
   `button[type="submit"].gefahr` (0-1-1 gegen 0-1-0) schlaegt die rote
   Grundregel die Klasse, und ein Gefahr-Knopf wird zum roten
   Vollton-Balken statt zurueckhaltend rot auf transparent. Betraf am
   28.07.2026 elf Knoepfe. Waechter: test_waechter_knopfstile. */
.gefahr, button[type="submit"].gefahr {
  background: transparent;
  color: var(--fehler);
}

/* „Auftrag löschen" steht bewusst SCHWARZ, nicht rot (28.07.2026):
   Rot ist in dieser Oberflaeche die Farbe der Hauptknoepfe („Senden",
   „Speichern") — ein roter Loesch-Knopf saehe aus wie einer davon.
   Schwarz ist zurueckhaltend; die Rueckfrage ist der eigentliche
   Schutz, dazu der Abstand in .knopfzeile-weit.

   DER DOPPELTE SELEKTOR IST PFLICHT, aus demselben Grund wie bei
   .leise zwei Regeln weiter oben: `button[type="submit"]` hat
   Spezifitaet 0-1-1 (Element + Attribut), eine blosse Klasse nur 0-1-0.
   Ohne `button[type="submit"].loeschen-schwarz` gewinnt die rote
   Grundregel, und der Knopf bleibt ein roter Vollton-Balken — beim
   ersten Anlauf genau so passiert, obwohl die Warnung zwei Zeilen
   weiter oben steht. */
.loeschen-schwarz, button[type="submit"].loeschen-schwarz {
  background: transparent;
  color: var(--text);
}
.loeschen-schwarz:hover,
button[type="submit"].loeschen-schwarz:hover {
  background: var(--fehler-flaeche);
  color: var(--fehler);
}

/* Speichern links, Loeschen rechts, maximaler Abstand dazwischen —
   damit niemand versehentlich das Falsche trifft. */
.knopfzeile-weit {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--a5);
  margin-top: var(--a4);
}
.gefahr:hover, button[type="submit"].gefahr:hover {
  background: var(--fehler-flaeche);
}

.klein { padding: 6px var(--a3); min-height: 32px; font-size: var(--groesse-xs); }
.gross { padding: 12px var(--a5); min-height: 48px; font-size: var(--groesse-m); }

a.knopf { display: inline-flex; align-items: center; justify-content: center; }

/* ---------- Formulare ---------- */

label, .feld > .feldname {
  display: block;
  font-size: var(--groesse-s);
  color: var(--text-2);
  font-weight: 500;
}
.feld { margin-bottom: var(--a4); }

/* ══ HAUS-DIALOG (natives <dialog>) ══
   Hiess bis zum 07.08.2026 `.zuweisen-dialog` und gehoerte dem
   Zuweisen-Dialog. Der ist mit U3 entfallen — die Regeln standen
   danach OHNE NUTZER da (kein Template kannte sie mehr), und mit ihnen
   die Mechanik in app.js. Statt beides zu loeschen und fuer „Position
   hinzufuegen" neu zu bauen, traegt es jetzt einen Namen, der nicht an
   einen Vorgang gebunden ist.

   Die zwei Regeln fuer `textarea` und `.combobox` sind dabei WEG: Sie
   waren fuer den Uebergabe-Kommentar und die Bearbeiter-Combobox da,
   und beide gibt es nicht mehr. Sie mitzuschleppen haette einen
   Nutzer vorgetaeuscht.

   `width` statt `min-width`: Der Positionsdialog soll BREITER sein
   als die Panelspalte — bei 52rem fasst sein `.feldraster` drei
   Spalten zu 15rem statt der zwei, die im 692px-Abschnitt passen.
   Genau dafuer ist er da. */
.haus-dialog {
  border: 1px solid var(--linie);
  border-radius: var(--radius);
  padding: var(--a4);
  width: min(52rem, 92vw);
  box-shadow: var(--schatten-hover, 0 8px 30px rgba(0, 0, 0, 0.18));
}
.haus-dialog::backdrop { background: rgba(17, 17, 20, 0.35); }
.haus-dialog h3 { margin-bottom: var(--a3); }
.haus-dialog .dialog-aktionen { margin-top: var(--a3); }

/* „+ Position hinzufuegen" — eine ZEILE, kein Griff (X-Auftrag).
   Bewusst 15px und Meta-Farbe: Der Eintrag steht unter der Summenzeile
   und darf ihr nicht den Rang ablaufen. `type="button"`, also greift
   die rote Submit-Grundregel nicht. */
.position-hinzu {
  display: block;
  width: 100%;
  min-height: 0;
  margin: var(--a2) 0 0;
  padding: var(--a1) var(--a2);
  border: none;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-2);
  font-family: inherit;
  font-size: var(--groesse-s);
  text-align: left;
  cursor: pointer;
}
.position-hinzu:hover, .position-hinzu:focus-visible {
  background: var(--hover-flaeche);
  color: var(--akzent);
}

/* ══ NUR SICHTBAR, WENN DIE POSITIONSLISTE OFFEN IST (Y, 07.08.2026) ══
   Entscheid Eric: Man soll keine Position anlegen, ohne einmal durch
   die bestehenden gegangen zu sein.

   ⚠ DAS IST BEDIENFUEHRUNG, KEINE REGEL — und der Unterschied ist
   wichtig genug fuer diesen Absatz. Aufklappen ist EIN Klick, und der
   Block steht ohnehin `open` da; wer den Knopf will, hat ihn sofort.
   Erzwungen wird hier gar nichts: Die Route
   `/auftraege/{id}/positionen/neu` nimmt einen POST unveraendert
   entgegen, ganz gleich, was die Oberflaeche gerade zeigt. Wer hier je
   eine Sperre hineinliest und sich darauf verlaesst, verlaesst sich auf
   Anzeige-CSS. Soll es wirklich eine Bedingung werden, gehoert sie in
   den Service — nicht hierher.

   ══ WARUM GESCHWISTER-SELEKTOR UND NICHT UMHAENGEN ══
   Der nächstliegende Weg waere, den Knopf INS `<details>` zu ziehen —
   dann verschwaende er mit ihm, ganz ohne Regel. Er ist trotzdem
   falsch: Die Summenzeile liegt AUSSERHALB der Liste (sie muss auch
   zugeklappt sichtbar bleiben), der Knopf stuende drinnen damit ueber
   ihr, und eine Summe gehoert unter die Posten, nicht unter eine
   Bedienung. Genau die Reihenfolge, die der X-Auftrag festgeschrieben
   hat.

   `~` statt Umhaengen laesst die Reihenfolge, wie sie ist: details,
   Summen, Knopf, Dialog stehen als Geschwister in
   `.positionen-abschnitt` (am 07.08.2026 am gerenderten HTML
   nachgesehen, Waechter dazu in test_panel_kompakt).

   ⚠ DER SELEKTOR NENNT `.position-hinzu` AUSDRUECKLICH und nicht `~ *`.
   Der Dialog ist derselben Ebene und wuerde sonst mit ausgeblendet —
   er wird per `showModal()` in die oberste Ebene gehoben, aber
   `display: none` schlaegt das. Wer beim Zuklappen den Dialog offen
   hat, saehe ihn verschwinden. */
details.positionen-block:not([open]) ~ .position-hinzu { display: none; }

/* Übergabe-Kommentar im Zuweisungs-Verlauf: eigene Zeile, abgesetzt. */
.zuweisung-kommentar { display: block; padding-left: var(--a3); }

/* Termin-Doppel: Tagesdatum ODER Kalenderwoche nebeneinander
   (partials/termin_feld.html; initTerminFelder leert das Gegenstück). */
.termin-doppel .termin-zeile { display: flex; gap: var(--a2); flex-wrap: wrap; }
.termin-doppel .termin-kw { max-width: 11rem; }

input, select, textarea {
  font-family: inherit;
  font-size: var(--groesse-m);
  color: var(--text);
  background: var(--flaeche-2);
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: 10px var(--a3);
  width: 100%;
  min-height: 44px;
  margin-top: var(--a1);
  transition: background var(--dauer) var(--kurve),
              border-color var(--dauer) var(--kurve),
              box-shadow var(--dauer) var(--kurve);
}
input:hover, select:hover, textarea:hover { background: #eaeaed; }
input:focus, select:focus, textarea:focus {
  outline: none;
  background: var(--flaeche);
  border-color: var(--akzent);
  box-shadow: 0 0 0 3px var(--akzent-flaeche);
}
textarea { resize: vertical; min-height: 66px; }
/* Mahnentwurf (Stufe 10): der Text zum Kopieren, über die ganze Breite. */
.entwurf-text { width: 100%; }

/* ══ DER AUFKLAPP-PFEIL ALLER <select> — EINE REGEL, HAUSWEIT ══
   (U5, 07.08.2026 — Eric: „groesser und deutlich sichtbarer")

   GEMESSEN VOR DER AENDERUNG: 38 <select> in 18 Vorlagen, und der Pfeil
   kommt fuer alle aus GENAU DIESER Regel — `M1 1l5 5 5-5` steht kein
   zweites Mal im Stylesheet. Es gibt also nichts zu vereinheitlichen;
   die Aenderung geschieht an einer Stelle und erreicht alle 38.

   Was sich aendert: 12x8 -> 16x11 px, Strich 1.8 -> 2.2, Farbe
   --text-2 (#6e6e73) -> --text (#111114). Der Wert steht als Literal
   da, weil eine data-URI keine CSS-Variablen liest — es ist trotzdem
   eine HAUSFARBE, kein neuer Ton.

   ⚠ VIER REGELN VERENGEN DAS RECHTE POLSTER und muessen den groesseren
   Pfeil noch fassen. Nachgerechnet (Pfeil sitzt 10px vom Rand, ist
   16px breit, belegt also bis 26px):
     .filterleiste select                        32px -> 6px Luft  ok
     td select                                   30px -> 4px Luft  ok
     .position-fuss select                       30px -> 4px Luft  ok
     .positionen-abschnitt .position-fuss select 26px -> 0px       KOLLISION
   Nur die letzte war zu eng; sie steht bei ihrer Regel auf 30px und
   ist die EINZIGE Stelle ausser dieser hier, die angefasst wurde.

   Die Wandanzeige ist NICHT betroffen: templates/anzeige/stil.html
   bringt ihr eigenes <style> mit und laedt app.css bewusst nicht — sie
   enthaelt ohnehin kein einziges <select> (beides am 07.08.2026
   nachgesehen). Die Lagertafel (lageruebersicht.html) enthaelt
   ebenfalls keins; die Lager-Detailliste hat drei, die ueber
   `td select` laufen und in der Rechnung oben stehen. */
/* ══ AUFKLAPP-PFEIL, 50 % GRÖSSER (Wunsch Team, 11.08.2026) ══
   16x11 -> 20x13.75. Der Pfeil ist an GENAU DIESER Stelle definiert
   (gemessen: zwei SVG-Hintergrundbilder im ganzen Stylesheet, das
   zweite ist die Lupe der Suche) — es ist eine Änderung, keine
   Vereinheitlichung.

   ⚠ `viewBox` IST PFLICHT UND WAR VORHER NICHT DA. Ohne ihn sind
   `width`/`height` nur die Leinwand: Der Pfad bliebe bei seinen
   Koordinaten für 16x11 stehen, säße links oben in einer größeren
   Fläche und wäre KEINEN Millimeter größer. Mit `viewBox='0 0 16 11'`
   skaliert alles mit, auch die Strichstärke.

   ⚠ DIE FARBE BLEIBT `#111114` — REINES SCHWARZ WÄRE FALSCH GEWESEN.
   Gewünscht war „deutlich kontrastreicher, notfalls schwarz". Gerechnet
   gegen den Feldhintergrund `--flaeche-2` (#f0f0f2): #111114 steht bei
   16,6:1, reines Schwarz bei 18,5:1 — beide weit über der AA-Schwelle
   von 4,5:1, der Unterschied ist rechnerisch klein und sichtbar keiner.
   Der Pfeil war nicht zu blass, sondern zu KLEIN.

   Dazu kommt eine Hausregel, die ein bestehender Wächter festhält
   (`test_panel_kompakt.test_w3_der_pfeil_ist_groesser_als_vorher`):
   Die Farbe MUSS eine Hausfarbe sein — #111114 ist `--text`, reines
   Schwarz wäre eine erfundene. Für 1,9 Punkte Kontrast, die niemand
   sieht, eine Palette aufzubrechen, wäre der schlechtere Handel.

   ⚠ DIE RESERVE RECHTS MUSS MITWACHSEN — sonst läuft Text unter den
   Pfeil. Gemessen (Pfeil sitzt 10px vom Rand, belegt also 10..34px
   statt bisher 10..26px):
       Grundregel                 38px bleibt   (Luft  8px)
       .filterleiste select       32px -> 34px  (Luft  4px)
       td select                  30px -> 34px  (Luft  4px)
       select.zustaendig-waehler  30px -> 34px  (Luft  4px)
       .positionen-abschnitt .position-fuss select
                                  30px -> 34px  (Luft  4px)
   Ohne die vier Nachzüge wären es 2, 0, 0 und 0px Luft gewesen — der
   Mindestabstand ist 4px (`--a1`), „berührt sich gerade noch nicht" ist
   kein brauchbares Kriterium für Lesbarkeit (Begründung ausführlich in
   test_panel_kompakt, W3).

   ⚠ 25 %, NICHT 50 %: Die erste Fassung vom 11.08.2026 ging auf 24x16.5
   und war zu gross (Befund Eric an den echten Seiten). Die Farbe war
   von Anfang an in Ordnung — geändert hat sich nur die Grösse.
   Wächter: test_dropdown_pfeil. */
select {
  appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='13.75' viewBox='0 0 16 11'%3E%3Cpath d='M1.6 1.6L8 8l6.4-6.4' fill='none' stroke='%23111114' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  padding-right: 38px;
}

input[type="checkbox"], input[type="radio"] {
  width: 20px; height: 20px; min-height: 0;
  margin: 0; padding: 0;
  /* Die Element-Grundregel (input { … }) gibt sonst auch dem nativen
     Kästchen Fläche, 10px-Radius und Hover-Grau — das native Rendering
     zeichnet darüber und es entstehen unsaubere Ränder (dieselbe
     Falle wie einst button[type=submit] vs. .leise). Gilt für Radios
     (Liefertermin-Vorgaben) genauso. */
  background: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  accent-color: var(--akzent);
  vertical-align: -4px;
}
input[type="checkbox"]:hover, input[type="radio"]:hover { background: none; }
/* Der Reset nimmt auch den box-shadow-Fokus-Ring — Tastatur-Fokus
   stattdessen als Outline ums native Element (Auswahl-Optik selbst
   kommt weiter vom accent-color-Rendering). */
input[type="checkbox"]:focus-visible, input[type="radio"]:focus-visible {
  outline: 2px solid var(--akzent);
  outline-offset: 2px;
}
.inline-label {
  display: flex; align-items: center; gap: var(--a2);
  color: var(--text); font-weight: 400;
  min-height: 44px; cursor: pointer;
}

.feldraster {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 0 var(--a5);
  max-width: 76rem;  /* keine meterbreiten Eingabefelder in breiten Kästen */
}
.feldraster .breit { grid-column: 1 / -1; }

/* Fieldsets: der Browser-Default min-inline-size: min-content lässt ein
   Fieldset NICHT unter die Wunschbreite seines Inhalts schrumpfen — mit
   einem feldraster darin ragte es aus dem Kasten (Anschrift-Feld der
   Auftrag-Vorschau). Schrumpfen erlauben wie jedem anderen Block. */
fieldset { min-inline-size: 0; }

.optional { color: var(--text-3); font-weight: 400; font-size: var(--groesse-xs); }

.aktionen {
  display: flex;
  align-items: center;
  gap: var(--a4);
  margin-top: var(--a5);
}

.feldfehler {
  color: var(--fehler);
  font-size: var(--groesse-s);
  margin-top: var(--a2);
}

/* Gleichzeitiges Schreiben: der Hinweis an den Verlierer.
   Er trägt `feldfehler` mit und erbt Farbe und Größe daher — hier steht
   nur, was ihn davon unterscheidet: Er ist LÄNGER (Name, Wert, Uhrzeit)
   und trägt einen Knopf, braucht also eine Fläche und Luft statt einer
   nackten Zeile.

   ⚠ DIE KLASSE STAND ZUERST OHNE REGEL IM TEMPLATE. Sie wäre still auf
   `.feldfehler` allein zurückgefallen — kein Fehler, kein Log, nur ein
   Knopf, der am Text klebt. Genau die Fehlerklasse, die in CLAUDE.md
   unter „CSS meldet nichts" steht (`.stumpf` an einem Knopf, vier
   erfundene Variablen). Gefunden beim Nachzählen der benutzten gegen
   die deklarierten Namen. Wächter: test_schreibkonflikt.
   test_die_klassen_des_hinweises_haben_regeln. */
.konflikt-hinweis {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--a3);
  margin-top: var(--a3);
  padding: var(--a3);
  border-radius: var(--radius);
  background: var(--warnung-flaeche);
  /* NICHT --fehler: Ein gleichzeitiger Schreibvorgang ist kein
     Regelverstoß, sondern ein Hinweis. Rot hiesse „du hast etwas falsch
     gemacht" — hier hat nur jemand anderes schneller geklickt. */
  color: var(--text-1);
}
.konflikt-hinweis button { flex: none; }

/* ---------- Meta & Kleinkram ---------- */

.meta { color: var(--text-3); font-size: var(--groesse-xs); }
.hinweis { color: var(--text-2); font-size: var(--groesse-s); }
.rechts { text-align: right; }

/* ---------- Status-Farbcodierung — die EINE Quelle ----------
   Phasenfarbe = Bedeutung (Grau Warten/neutral, Blau in Arbeit, Amber
   bereit/Übergabe, Grün abgeschlossen, Rot NUR Storniert), Abstufung
   hell→dunkel = Reihenfolge innerhalb der Phase. Dropdown, Board-Karten
   und Details-Panel konsumieren ausschließlich diese Variablen — Farben
   NIE an anderer Stelle pflegen. Text/BG-Kontrast aller Paare ≥ 7,4:1
   (AA geprüft am 16.07.2026). Klassenname = Status-Enum-Wert. */
/* ---- Statuspalette (Board-Neuentwurf, 2. Fassung 20.07.2026) ----
   PRINZIP: Ein zusammenhängender AUSSCHNITT DES FARBKREISES bildet den
   Fortschritt ab — Violett (264°) -> Blau (209°) -> Türkis (188°) ->
   Grün-Türkis (165°) -> Grün (128°). Der Farbton wandert also mit dem
   Vorgang, das macht den Verlauf lesbar und die Palette harmonisch.
   Innerhalb einer Spalte wird zusätzlich abgestuft: heller = früher,
   dunkler = weiter.
     Büro = neutrales Grau (noch nicht gestartet, bewusst KÜHL statt
     beige, damit es zum kalten Bogen passt)
     Storniert = gedämpftes Rot. Seit dem 31.07.2026 erscheint der
     Status gar nicht mehr auf dem Board (models.BOARD_AUSGENOMMEN);
     die Farbe trägt er weiterhin in Liste und Detailseite.

   HARTE REGEL — FARBFAMILIEN TRENNEN:
   Warme Töne (Gelb/Orange/Rot) gehören AUSSCHLIESSLICH den Warnungen
   (--fehler/--warnung: überfällig, Termin naht, eilig, offene
   Vorkasse). Kalte Töne gehören ausschließlich den Prozess-Status.
   Damit ist der frühere Bernstein-Konflikt bei Logistik erledigt.
   Einzige Ausnahme: „storniert“ — deutlich entsättigt (Buntheit 0.22
   gegen 0.63 beim Alarmrot), damit ein Abbruch nie wie ein Alarm wirkt.

   Alle Werte nachgerechnet: Pillentext >= 4.5:1, Punkt >= 3:1 gegen die
   Spaltenfläche, Abstufung monoton, Bogen monoton fallend, kein
   Prozess-Status im warmen Sektor — Wächter test_statusfarben.py.
   Klassenname = Status-Enum-Wert. */
.s-auftrag_angelegt        { --s-bg: #E3E5E9; --s-punkt: #7B7F86; --s-text: #3A3D42; }
.s-warten_auf_vorkasse     { --s-bg: #D0D3D9; --s-punkt: #5C6067; --s-text: #33363B; }
.s-bestellt_bei_lieferant  { --s-bg: #E4D8F8; --s-punkt: #7B3FD2; --s-text: #3F1E7A; }
.s-warten_auf_wareneingang { --s-bg: #D0BCF2; --s-punkt: #5D22B6; --s-text: #32136A; }
.s-arbeitsschein_im_lager  { --s-bg: #D3E4F8; --s-punkt: #1F76C6; --s-text: #0A4176; }
.s-fertig_gemeldet         { --s-bg: #B7D5F2; --s-punkt: #0C5DA6; --s-text: #063256; }
/* ⚠ VON TÜRKIS AUF BLAU, 11.08.2026 — das ist ein UMZUG, keine
   verlorene Farbe. „Lieferschein & Etiketten" gehörte zur Spalte
   Logistik und trug deren Türkis; seit dem Entscheid Eric gehört der
   Status ins LAGER, und der Farbton kommt aus der SPALTE, nicht aus der
   Geschichte des Status. Wer hier Türkis vermisst, sucht die Farbe der
   alten Spalte.

   Gerechnet, nicht gegriffen: Die Spalte staffelt mit fortschreitendem
   Stand DUNKLER (Wächter `test_farbton_je_spalte_und_abstufung`).
   Leuchtdichte 0,1733 -> 0,1066 -> 0,0484; die Schritte 0,0667 und
   0,0582 sind damit annähernd gleich gross, und Logistik hält mit
   0,0519 denselben Takt. Ein helleres Blau hätte die Reihenfolge zwar
   auch erfüllt, aber einen Stolperschritt gelassen (0,0331 gegen
   0,0667).
   Text auf Fläche 9,07:1, Punkt auf Fläche 5,55:1. */
.s-lieferschein_etiketten  { --s-bg: #96BFE9; --s-punkt: #073F73; --s-text: #031B31; }
.s-versandbereit           { --s-bg: #B6DFE6; --s-punkt: #0B7285; --s-text: #063E48; }
.s-versendet               { --s-bg: #9CD2DC; --s-punkt: #075B6C; --s-text: #04303A; }
.s-abgerechnet             { --s-bg: #C0E6D7; --s-punkt: #0E8869; --s-text: #064E3C; }
/* ⚠ AUFGETEILT AM 14.08.2026 — `bezahlt_abgeschlossen` wurde zu zwei
   Status, und beide stehen in der Spalte „Fertig". `bezahlt` ERBT das
   Grün unverändert; für ihn ändert sich optisch nichts.

   ⚠ `abgeschlossen` IST AM SELBEN TAG NEU GERECHNET WORDEN, und der
   Grund ist eine Regel, die vorher nicht galt. Ein erster Entwurf gab
   ihm einen GEDÄMPFTEN Ton (#BAC3B6/#497D2F) — passend zu „niemand
   arbeitet mehr daran", nach dem Vorbild von `storniert`. Damals stand
   der Status in BOARD_AUSGENOMMEN. Mit der Berichtigung kommt er zurück
   aufs Board, und damit greift `test_prozessfarben_sind_kraeftig_genug`:
   Punkt-Buntheit ≥ 0,35 und Flächen-Buntheit ≥ 0,10. Gemessen war der
   Entwurf bei 0,31 und 0,05 — er wäre an BEIDEN Schwellen gescheitert.
   „Gedämpft" und „Prozessfarbe" schliessen einander aus; die Spalte
   entscheidet, welche Regel gilt.

   Die Spalte gibt den TON vor, die Status sind Abstufungen — deshalb
   bleibt `abgeschlossen` im Grün und wird nicht bunt abgesetzt. Der
   PUNKT ist die Stufe: #4F7915 ist dunkler als #2C8C38, wie
   `test_farbton_je_spalte_und_abstufung` es für den fortschreitenden
   Stand verlangt.

   Gemessen: Punkt-Buntheit 0,52, Flächen-Buntheit 0,15, Punkt gegen
   Spaltenfläche 4,52:1, Text auf der Fläche 7,54:1.

   ⚠ ΔE 6,8 ZWISCHEN DEN BEIDEN FLÄCHEN, und das ist KEIN Versäumnis.
   Die ΔE-20-Forderung gilt der PILLE der Bürotafel (dort 22,3, siehe
   `anzeige/stil.html`) — dort steht die Farbe allein. Hier tragen die
   Karten zusätzlich den Punkt in zwei Stufen und das Statuswort, und
   Stufen einer Spalte liegen absichtlich nah beieinander: Das engste
   Bestandspaar der Datei liegt bei ΔE 4,2 (`auftrag_angelegt` gegen
   `warten_auf_vorkasse`), `versandbereit` gegen `versendet` bei 4,5. */
.s-bezahlt                 { --s-bg: #C6E5C2; --s-punkt: #2C8C38; --s-text: #1A5620; }
.s-abgeschlossen           { --s-bg: #C9D4B9; --s-punkt: #4F7915; --s-text: #283F07; }
.s-storniert               { --s-bg: #E8D9D9; --s-punkt: #96625F; --s-text: #5C3532; }

.status-punkt {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: var(--radius-voll);
  vertical-align: 1px;
  background: var(--s-punkt, var(--text-3));
}

.warnzeichen {
  font-size: var(--groesse-xs);
  color: var(--warnung);
  cursor: default;
}

.chip {
  display: inline-block;
  font-size: var(--groesse-xs);
  font-weight: 500;
  border-radius: var(--radius-voll);
  padding: 2px 10px;
  background: var(--flaeche-2);
  color: var(--text-2);
  white-space: nowrap;
}
.chip-warnung { background: var(--warnung-flaeche); color: var(--warnung); }
.chip-fehler  { background: var(--fehler-flaeche);  color: var(--fehler); }
.chip-ok      { background: var(--ok-flaeche);      color: var(--ok); }

/* ---------- Toasts ---------- */

#toasts {
  position: fixed;
  bottom: var(--a5);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--a2);
  z-index: 100;
  width: min(480px, calc(100vw - 32px));
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  background: var(--text);
  color: #fff;
  font-size: var(--groesse-s);
  padding: var(--a3) var(--a4);
  border-radius: var(--radius);
  box-shadow: var(--schatten-hebt);
  max-width: 100%;
  animation: toast-rein 220ms var(--kurve);
}
.toast.fehler  { background: var(--fehler); }
.toast.warnung { background: var(--warnung); }
.toast.geht {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 250ms var(--kurve), transform 250ms var(--kurve);
}
@keyframes toast-rein {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}

/* ---------- Board ---------- */

/* Werkzeugzeile überm Board (Jira-Anordnung): Board-Suche links,
   Filter rechts. */
.board-werkzeuge {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--a3);
  flex-wrap: wrap;
  margin-bottom: var(--a4);
}
.board-werkzeuge .filterleiste { margin-bottom: 0; justify-content: flex-end; }
/* Nachtrag 6: dezenter Hinweis, dass das Board reine Anzeige ist. */
.board-hinweis {
  color: var(--text-2);
  font-size: var(--groesse-xs);
  margin: calc(-1 * var(--a3)) 0 var(--a3);
}
#board-suche {
  width: 200px;
  min-height: 36px;
  margin: 0;
  padding: 6px var(--a3) 6px 32px;
  font-size: var(--groesse-s);
  background-color: var(--flaeche);
  box-shadow: var(--schatten-ruhe);
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%236e6e73' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m21 21-4.35-4.35'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 10px center;
  transition: width var(--dauer) var(--kurve),
              background-color var(--dauer) var(--kurve),
              border-color var(--dauer) var(--kurve),
              box-shadow var(--dauer) var(--kurve);
}
/* Die ID-Spezifität schlägt input:focus — Fokus-Ring darum explizit
   (gleiche Optik wie alle Eingaben), dazu weitet sich das Feld leicht. */
#board-suche:focus {
  width: 280px;
  border-color: var(--akzent);
  box-shadow: 0 0 0 3px var(--akzent-flaeche);
}

.filterleiste {
  display: flex;
  flex-wrap: wrap;
  gap: var(--a2);
  align-items: center;
  margin-bottom: var(--a5);
}
/* Nur echte Eingabefelder der Leiste — NICHT die Checkboxen/Radios in
   den Filter-Dropdowns (die Menüs liegen im selben form.filterleiste):
   diese Regel steht NACH dem Kästchen-Reset und gewann sonst per
   Quellreihenfolge — weiße Box + Schatten-Ring ÜBER dem nativen
   Element = mehrfache Geister-Umrisse. :where() hält die Spezifität
   bei (0,1,1), sonst würde die Ausnahme ihrerseits die Feldregeln der
   Menüs (.mehrfach-suche, .termin-feld) übersteuern. */
.filterleiste select,
.filterleiste input:where(:not([type="checkbox"]):not([type="radio"])) {
  width: auto;
  min-height: 36px;
  margin: 0;
  padding: 6px var(--a3);
  font-size: var(--groesse-s);
  background: var(--flaeche);
  box-shadow: var(--schatten-ruhe);
}
.filterleiste select { padding-right: 34px; }  /* Pfeil-Reserve, s. o. */
.filterleiste button { min-height: 36px; padding: 6px var(--a4); }

/* Mehrfach-Filter (Übersicht): Knopf in der Select-Optik der Leiste,
   gewählte Werte als Chips im Knopf, darunter ein Combobox-Menü
   (Checkbox-Liste + Eingrenzungs-Feld) im .vorschlaege-Stil. */
.mehrfach-filter { position: relative; }
.filterleiste .mehrfach-knopf {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--a1);
  min-height: 36px;
  padding: 4px var(--a3);
  font-size: var(--groesse-s);
  color: var(--text);
  background: var(--flaeche);
  border: none;
  border-radius: var(--radius);
  box-shadow: var(--schatten-ruhe);
  cursor: pointer;
}
/* Farbe war hier schon --text-2 (5,1:1) — nur die Grösse zieht mit. */
.mehrfach-knopf::after { content: "▾"; color: var(--text-2); font-size: calc(var(--groesse-xs) * 1.25); }
.mehrfach-titel { color: var(--text-2); font-weight: 500; }
.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--a1);
  padding: 1px var(--a2);
  border-radius: var(--radius);
  background: var(--akzent-flaeche);
  color: var(--akzent-hover);
  font-weight: 550;
}
.filter-chip .chip-x {
  padding: 0 2px;
  border-radius: var(--radius);
  cursor: pointer;
  line-height: 1;
}
.filter-chip .chip-x:hover, .filter-chip .chip-x:focus-visible { background: var(--flaeche); }
.mehrfach-menue {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: var(--a1);
  min-width: 240px;
  padding: var(--a2);
  background: var(--flaeche);
  border-radius: var(--radius);
  box-shadow: var(--schatten-hebt);
  z-index: 50;
}
.filterleiste .mehrfach-suche {
  width: 100%;
  min-height: 32px;
  margin-bottom: var(--a2);
  box-shadow: none;
  border: 1px solid var(--linie);
}
.mehrfach-liste {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: min(50vh, 320px);
  overflow-y: auto;
}
.mehrfach-liste label {
  display: flex;
  align-items: center;
  gap: var(--a2);
  padding: var(--a1) var(--a2);
  border-radius: var(--radius);
  font-size: var(--groesse-s);
  cursor: pointer;
}
.mehrfach-liste label:hover { background: var(--hover-flaeche); }
.mehrfach-liste input[type="checkbox"] { margin: 0; }

/* Liefertermin-Filter: gleiche Komponente wie die Mehrfach-Filter —
   Radio-Vorgaben oben, darunter IMMER sichtbar der freie Zeitraum,
   per Linie abgetrennt. Felder in der Optik des Tipp-Felds; der
   native Datums-Picker des Browsers bleibt (bewusste Grenze). */
.termin-zeitraum {
  display: flex;
  flex-direction: column;
  gap: var(--a2);
  margin-top: var(--a2);
  padding: var(--a3) var(--a2) var(--a1);
  border-top: 1px solid var(--linie);
}
.termin-feld {
  display: flex;
  align-items: center;
  gap: var(--a2);
  font-weight: 400;
}
.termin-feld .hinweis { flex: 0 0 26px; }
.termin-feld input[type="date"] {
  min-height: 32px;
  margin: 0;
  padding: 4px var(--a2);
  font-size: var(--groesse-s);
  box-shadow: none;
  border: 1px solid var(--linie);
}
.filterleiste .filter-zuruecksetzen { align-self: center; }

/* Gruppen-Spalten (Neuentwurf): Sie teilen sich die Breite, statt zu
   scrollen — das Board passt ohne Querscrollen auf den Schirm. Leere
   Spalten bleiben stehen (feste Positionen = räumliche Orientierung),
   nur gedämpft. */
.board-gruppen { overflow: visible; }
/* Der Kopf steht in EINER Zeile. Ungünstigster Fall: längster Name
   („Controlling“ ~99px) + Trichter + × + Zähler + Polster + Gaps
   = 209px. Darunter kürzt die Ellipse den Namen. */
.board-gruppen .spalte { flex: 1 1 0; min-width: 210px; }
/* Die offene Spalte nach vorn holen: Ohne das läge das Menü unter den
   Karten der NACHFOLGENDEN Spalten (spätere Geschwister gewinnen bei
   gleichem z-index). :has() macht das ohne JS. */
.board-gruppen .spalte:has(.spalten-filter[open]) {
  position: relative;
  z-index: 50;
}

.board {
  display: flex;
  gap: var(--a3);
  overflow-x: auto;
  /* Das Board ist das Hauptelement der Übersicht: Spalten strecken sich,
     die Ablageflächen füllen die Höhe (großzügige Drop-Zonen). */
  align-items: stretch;
  min-height: calc(100vh - 300px);
  padding: var(--a1) var(--a1) var(--a5);
  -webkit-overflow-scrolling: touch;
}
/* Jira-Kanban-Optik: die Spalte ist eine ruhige graue Fläche, die
   weißen Karten liegen mit konsistentem Abstand darauf. */
.spalte {
  flex: 0 0 272px;
  display: flex;
  flex-direction: column;
  background: var(--flaeche-2);
  border-radius: var(--radius-gross);
  padding: var(--a1);
  transition: flex-basis var(--dauer) var(--kurve);
}
.spalte > header { flex: none; }
.spalte .karten { flex: 1; }
.spalte.leer { flex-basis: 160px; }
.spalte > header {
  /* EINE Zeile: Name | Trichter | (×) | Zähler. Nur der Name schrumpft
     (min-width:0 + Ellipse), Bedienung und Zähler behalten ihre Breite. */
  display: flex;
  align-items: center;
  gap: var(--a1);
  min-height: 30px;
  padding: var(--a2) var(--a3) var(--a2);
  white-space: nowrap;
  /* KEIN overflow:hidden — das schnitt das Quickfilter-Menü ab (es ist
     ein Kind des Headers). Die Ellipse braucht nur der Titel, der sie
     über .spalte-titel selbst mitbringt. */
}
.spalte-zaehler {
  flex: none;
  margin-left: auto;      /* immer ganz rechts, egal wie kurz der Name */
  display: flex;
  align-items: baseline;
  gap: 4px;
  font-size: var(--groesse-xs);
}
.spalte .anzahl { color: var(--rolle-meta-farbe); font-weight: 650; }
/* Spalten-Quickfilter (Board-Neuentwurf) */
.spalte > header { gap: var(--a1); }
/* Die Spaltenüberschrift trägt jetzt die zentrale Titel-Rolle (16px)
   statt der XS-Größe — die Spalte soll auf einen Blick erfassbar sein.
   nowrap + Ellipse: „Controlling“ — der längste verbliebene Name —
   bricht nie um; die Spaltenbreiten unten sind so gewählt, dass er
   auch nicht kürzt. („Abgebrochen“ war bis zum 31.07.2026 der zweite
   Fall; die Spalte gibt es nicht mehr.) */
.spalte-titel {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--a2);
  font-size: var(--rolle-titel-groesse);
  font-weight: 700;
  color: var(--rolle-titel-farbe);
  letter-spacing: -0.01em;
  overflow: hidden;
  text-overflow: ellipsis;
}
.spalte-titel .status-punkt { flex: none; }
.anzahl-gesamt { color: var(--text-3); font-weight: 400; }
.spalten-filter { flex: none; position: relative; }
.spalten-filter > summary {
  list-style: none;
  cursor: pointer;
  /* Mindestens 26px Ziel — mit der Maus und am Touchgerät treffbar,
     optisch aber ruhiger als die Überschrift daneben. */
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius);
  color: var(--text-3);
}
.spalten-filter > summary::-webkit-details-marker { display: none; }
.spalten-filter > summary .nav-icon {
  width: 18px;
  height: 18px;
  display: block;
  color: inherit;
}
/* Ein-Klick-Rückweg neben dem Trichter — nur bei aktivem Filter da. */
.filter-loeschen {
  flex: none;
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--akzent);
  font-size: var(--groesse-m);
  font-weight: 700;
  line-height: 1;
  border-radius: var(--radius);
  text-decoration: none;
}
.filter-loeschen:hover {
  background: var(--akzent-flaeche);
  text-decoration: none;
}
.spalten-filter > summary:hover { background: var(--hover-flaeche); color: var(--text); }
.spalten-filter.aktiv > summary {
  color: var(--akzent);
  background: var(--akzent-flaeche);
}
.spalten-filter.aktiv > summary .nav-icon { stroke-width: 2.4; }
.spalten-filter[open] > summary { background: var(--hover-flaeche); }
.spalten-filter .menue {
  position: absolute;
  z-index: 60;
  top: calc(100% + 4px);
  left: 0;
  min-width: 200px;
  background: var(--flaeche);
  border-radius: var(--radius);
  box-shadow: var(--schatten-hebt, 0 8px 24px rgb(0 0 0 / 0.18));
  padding: var(--a2);
  font-weight: 400;
  white-space: normal;
}
/* Rechte Spalten: Menü rechtsbündig, sonst ragt es aus dem Board.
   Betraf „Fertig" und die schmale „Abgebrochen"-Spalte; seit deren
   Wegfall (31.07.2026) sind es „Controlling" und „Fertig". Die Regel
   greift über nth-last-child und passt sich von selbst an. */
.board-gruppen .spalte:nth-last-child(-n+2) .spalten-filter .menue {
  left: auto;
  right: 0;
}
.spalten-filter fieldset { border: 0; padding: 0; margin: 0 0 var(--a2); }
.spalten-filter legend {
  font-size: 11px;
  color: var(--rolle-label-farbe);
  font-weight: 650;
  padding: 0 0 2px;
}
.spalten-filter .menue-zeile {
  display: flex;
  align-items: center;
  gap: var(--a2);
  padding: 3px var(--a1);
  border-radius: var(--radius);
  font-size: var(--groesse-xs);
  cursor: pointer;
}
.spalten-filter .menue-zeile:hover { background: var(--hover-flaeche); }
.spalten-filter .menue-aktionen { display: flex; justify-content: flex-end; }
/* Aktiver Filter bleibt am Spaltenkopf sichtbar — samt Rückweg. */
.spalte-filterhinweis {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--a2);
  padding: 2px var(--a3) var(--a2);
  font-size: 11px;
  color: var(--akzent);
}
.spalte-filterhinweis a { color: var(--text-3); }
.karten {
  min-height: 56px;
  border-radius: var(--radius);
  padding: var(--a1);
  transition: background var(--dauer) var(--kurve);
}
.karten.zieht-drueber { background: var(--akzent-flaeche); }

.karte {
  background: var(--flaeche);
  border-radius: var(--radius);
  box-shadow: var(--schatten-ruhe);
  /* Status-Streifen in der Punktfarbe der .s-<status>-Klasse —
     bewusst schmal (ruhige Optik), gleiche Breite wie .karte.warnt. */
  border-left: 3px solid var(--s-punkt, transparent);
  padding: var(--a3);
  margin-bottom: var(--a2);
  cursor: pointer;  /* ganze Karte klickbar (führt zum Auftrag) */
  transition: box-shadow var(--dauer) var(--kurve),
              transform var(--dauer) var(--kurve);
}
.karte:hover { box-shadow: var(--schatten-hover); }

/* Kartenstruktur nach Jira-Vorbild: Titel (Kunde) → Material →
   Warn-Chips → Fußzeile (Kennung + Termin links, Avatar rechts). */
/* ---- Kartenaufbau (Neuentwurf 20.07.2026) ----
   Kopfzeile: Auftragsnummer links (die dominante Information der
   Karte), Status-Pille rechts. Die Pille trägt seit der Gruppierung
   nach Zuständigkeit die Status-Information, die vorher die Spalte gab. */
.karte-kopf {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--a2);
}
.karte-nummer {
  /* Bewusst die größte Schrift der Karte: In StaWiKon und am Telefon
     wird über die Auftragsnummer identifiziert. */
  font-size: var(--groesse-m);
  font-weight: 700;
  line-height: 1.2;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}
.karte-nummer:hover { color: var(--akzent); text-decoration: none; }
.status-pille {
  flex: 0 0 auto;
  background: var(--s-bg, var(--flaeche-2));
  color: var(--s-text, inherit);
  border-radius: var(--radius-voll);
  padding: 2px var(--a2);
  font-size: 11px;
  font-weight: 550;
  line-height: 1.5;
  white-space: nowrap;
}
.pille-zeichen { margin-right: 3px; font-weight: 700; }
.karte-kunde {
  font-size: var(--groesse-s);
  color: var(--text-2);
  margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Kundentyp vor dem Kundennamen auf der Lagerkarte (Stufe 9, 23.09.2026). */
.karte-kundentyp { font-weight: 600; color: var(--text-1); }
.karte-positionen {
  color: var(--text-3);
  font-size: var(--groesse-xs);
  margin-top: var(--a1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.karte-positionen-mehr { color: var(--text-3); font-style: italic; }
.karte-chips {
  display: flex;
  align-items: center;
  gap: var(--a1);
  margin-top: var(--a2);
}
.karte-fuss {
  display: flex;
  align-items: center;
  gap: var(--a2);
  margin-top: var(--a2);
  font-size: var(--groesse-xs);
  color: var(--text-3);
}
.karte-fuss:empty { display: none; }
.karte-termin { color: var(--text-2); font-weight: 550; }
.karte-termin-leer { color: var(--text-3); font-weight: 400; font-style: italic; }
.karte-termin.termin-ueber { color: var(--fehler); font-weight: 550; }
.karte-termin.termin-naht { color: var(--warnung); }
/* Zuweisungs-Bubble unten rechts (Jira-Assignee); ohne Zuständigen
   neutral grau mit „–“ — title trägt die Bedeutung. */
.karte-avatar { flex: 0 0 26px; margin-left: auto; margin-right: 0; }
.avatar-leer { background: var(--flaeche-2); color: var(--text-3); }

/* ---------- Tabellen (Liste, Bestellungen, Stammdaten) ---------- */

.tabelle-umschlag {
  background: var(--flaeche);
  border-radius: var(--radius-gross);
  box-shadow: var(--schatten-ruhe);
  overflow-x: auto;
  margin-bottom: var(--a5);
}
table { border-collapse: collapse; width: 100%; font-size: var(--groesse-s); }
th {
  text-align: left;
  font-size: var(--groesse-xs);
  font-weight: 500;
  color: var(--text-3);
  padding: var(--a3) var(--a4);
  border-bottom: 1px solid var(--linie);
  white-space: nowrap;
}
th a { color: var(--text-2); }
th a:hover { color: var(--akzent); text-decoration: none; }
td {
  padding: var(--a3) var(--a4);
  border-bottom: 1px solid var(--linie);
  vertical-align: middle;
  height: 52px;
}
tr:last-child td { border-bottom: none; }
tbody tr { transition: background var(--dauer) var(--kurve); }
tbody tr:hover { background: var(--hover-flaeche); }
td form { margin: 0; }
td select { min-height: 36px; width: auto; margin: 0; padding: 4px 34px 4px var(--a3); font-size: var(--groesse-s); }
td .knopf, td button { min-height: 32px; }

/* ---------- Leere Zustände ---------- */

.leerzustand {
  text-align: center;
  padding: var(--a7) var(--a5);
  color: var(--text-2);
}
.leerzustand p { margin-bottom: var(--a4); }
.leerzustand .gross-symbol { font-size: 2rem; display: block; margin-bottom: var(--a3); }

/* ---------- Seitenpanel "Erfordert Aufmerksamkeit" ----------
   Overlay von rechts über die aktuelle Seite (position: fixed — sitzt
   unabhängig von Seitenleisten-Zustand und Monitorbreite). Zustand nur
   im DOM: hidden + Klasse .offen für die Transition. */
.seitenpanel { position: fixed; inset: 0; z-index: 200; }
.seitenpanel-schleier {
  position: absolute;
  inset: 0;
  background: rgba(20, 18, 16, 0.35);
  opacity: 0;
  transition: opacity var(--dauer) var(--kurve);
}
.seitenpanel-inhalt {
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: min(440px, 92vw);
  background: var(--flaeche);
  box-shadow: var(--schatten-hebt);
  transform: translateX(100%);
  transition: transform var(--dauer) var(--kurve);
  padding: var(--a4) var(--a5) var(--a5);
  overflow-y: auto;
}
.seitenpanel.offen .seitenpanel-schleier { opacity: 1; }
.seitenpanel.offen .seitenpanel-inhalt { transform: none; }
.seitenpanel-kopf {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--a3);
}
.seitenpanel-kopf h3 { margin: 0; }
.seitenpanel-zu { font-size: 1.1rem; padding: 4px 10px; }

/* ---------- Neuer Auftrag ---------- */

.combobox { position: relative; }
.vorschlaege {
  position: absolute;
  top: 100%;
  left: 0; right: 0;
  margin-top: var(--a1);
  background: var(--flaeche);
  border-radius: var(--radius);
  box-shadow: var(--schatten-hebt);
  overflow: hidden;
  z-index: 50;
}
.vorschlaege:empty { display: none; }
.vorschlag {
  padding: var(--a3) var(--a4);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.vorschlag:hover { background: var(--hover-flaeche); }
.vorschlag.gewaehlt { background: var(--akzent-flaeche); }
.vorschlag-name { font-weight: 500; font-size: var(--groesse-s); }
.vorschlag-leer { padding: var(--a3) var(--a4); color: var(--text-2); font-size: var(--groesse-s); }

/* "aus KW"-Kennzeichen am Liefertermin (Freitag der erkannten KW). */
.aus-kw {
  display: inline-block;
  margin-left: var(--a1);
  padding: 1px var(--a2);
  border-radius: var(--radius);
  background: var(--flaeche-2);
  color: var(--text-2);
  font-size: var(--groesse-xs);
  font-weight: 400;
  vertical-align: middle;
  cursor: help;
}

/* Formcode-Feld: gleiche Combobox-Optik wie die Kundensuche. Die schmale
   Spalte der Positionszeile darf die Vorschlagsliste nicht einquetschen. */
.freitext-combobox .vorschlaege { min-width: 220px; right: auto; }
/* Preiseinheit-Feld in der Positionszeile: schmaler als der Formcode,
   die Marken sind hoechstens fuenf Zeichen lang. */
.feld-preiseinheit .freitext-combobox { min-width: 7ch; }
.feld-preiseinheit .vorschlaege { min-width: 9ch; }
.freitext-hinweis {
  margin-top: var(--a1);
  font-size: var(--groesse-xs);
  color: var(--text-2);
}

.kunden-hinweis {
  display: flex;
  align-items: center;
  gap: var(--a2);
  margin-top: var(--a2);
  font-size: var(--groesse-s);
  color: var(--text-2);
}
.kunden-hinweis .abweichend-link {
  font-size: var(--groesse-xs);
}

details.abweichend { margin-top: var(--a3); }
details.abweichend > summary {
  cursor: pointer;
  color: var(--text-2);
  font-size: var(--groesse-s);
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: var(--a1);
  min-height: 32px;
}
details.abweichend > summary::-webkit-details-marker { display: none; }
/* ══ AUFKLAPP-CHEVRONS: GRÖSSER UND KRÄFTIGER (Team, 11.08.2026) ══
   Farbe `--text-3` -> `--text-2`, Grösse +25 % — einheitlich mit dem
   Select-Pfeil derselben Runde.

   ⚠ ES WAR NICHT GESCHMACK, ES WAR ZU BLASS: `--text-3` (#a1a1a6) auf
   Weiss ergibt 2,6:1 und liegt damit UNTER der 3:1-Schwelle für
   grafische Elemente (WCAG 1.4.11). `--text-2` (#6e6e73) bringt 5,1:1 —
   verdoppelt und darüber. `--text` (#111114, 18,8:1) wäre neben grauer
   Beschriftung zu laut; ein Marker soll führen, nicht rufen.

   FÜNF STELLEN, alle in dieser Runde mitgezogen: die beiden Chevrons
   hier (`details.abweichend`, `.zeile-chevron`), die zwei
   Menü-Pfeilchen (`.status-menue`, `.mehrfach-knopf`) — und die
   `.labels-block`-Regel, die dabei ersatzlos entfiel (siehe dort). Zwei
   davon standen nicht auf der gemeldeten Liste; sie auszulassen hätte
   die Oberfläche uneinheitlich gemacht. */
details.abweichend > summary::before {
  content: "›";
  transition: transform var(--dauer) var(--kurve);
  color: var(--text-2);
  /* 1.25em statt einer festen Zahl: Das <summary> steht auf
     `--groesse-s` (15px), der Marker also auf 18,75px — und er wächst
     mit, falls die Schriftgrösse der Zeile je geändert wird. */
  font-size: 1.25em;
}
details.abweichend[open] > summary::before { transform: rotate(90deg); }

/* ARBEITSFLAECHEN (28.07.2026): „Positionen (n)", „Position hinzufuegen"
   und „Auftragsdaten bearbeiten" sind das, WOMIT man arbeitet — im
   Unterschied zu den Detailzeilen darueber, die nur berichten. Sie sehen
   deshalb untereinander gleich aus und heben sich von den Labels ab.

   „Positionen (n)" trug vorher .bs-kopf-titel und sah damit aus wie
   „Status" oder „Kunde" — also wie eine Anzeige, nicht wie ein Griff. */
details.arbeitsflaeche > summary {
  color: var(--text-1);
  font-size: var(--groesse-m);
  font-weight: 600;
}
details.arbeitsflaeche > summary::before { color: var(--text-2); }
details.arbeitsflaeche { margin-top: var(--a4); }
details.abweichend fieldset {
  border: none;
  padding: var(--a3) 0 0;
  margin: 0;
}

/* Positionszeilen im Formular */
.position-zeile {
  border-bottom: 1px solid var(--linie);
  padding: var(--a3) 0;
}
.position-zeile:first-child { padding-top: 0; }
.zeile-kompakt {
  display: grid;
  grid-template-columns: 2.2fr 0.9fr 1.8fr 0.9fr 0.8fr 36px 36px;
  gap: var(--a2);
  align-items: center;
}
.zeile-kompakt input, .zeile-kompakt select { margin: 0; min-height: 40px; font-size: var(--groesse-s); }
.zeile-chevron, .zeile-entfernen {
  min-height: 36px; width: 36px;
  padding: 0;
  background: transparent;
  /* Farbe und Grösse: siehe die Chevron-Begründung weiter oben
     (2,6:1 -> 5,1:1; 16px -> 20px). Die Fläche bleibt 36px — nur das
     Zeichen darin wächst, die Zeile also nicht. */
  color: var(--text-2);
  font-size: 1.25rem;
  border-radius: var(--radius);
}
.zeile-chevron:hover, .zeile-entfernen:hover { background: var(--hover-flaeche); color: var(--text); }
.zeile-chevron { transition: transform var(--dauer) var(--kurve); }
.position-zeile.offen .zeile-chevron { transform: rotate(90deg); }
.zeile-mehr {
  display: none;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--a2) var(--a4);
  padding-top: var(--a3);
}
.position-zeile.offen .zeile-mehr { display: grid; }
.zeile-mehr label { font-size: var(--groesse-xs); }
.zeile-mehr input, .zeile-mehr select { min-height: 40px; font-size: var(--groesse-s); margin-top: 2px; }

/* ---------- Auftragsdetail ---------- */

.detail-kopf { padding: var(--a5); }
.detail-kopf .nummer {
  font-size: var(--groesse-s);
  color: var(--text-3);
}
.detail-kopf .kunde {
  font-size: var(--groesse-xl);
  font-weight: 650;
  letter-spacing: -0.01em;
  margin: 2px 0 var(--a3);
}
.detail-kopf .fakten {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--a2) var(--a4);
  color: var(--text-2);
  font-size: var(--groesse-s);
}

/* Status-Pille mit Popover (natives details-Element) */
.status-menue { position: relative; display: inline-block; }
.status-menue > summary {
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: var(--a2);
  cursor: pointer;
  /* Statusfarbe der Pille kommt aus der .s-<status>-Klasse am details. */
  background: var(--s-bg, var(--flaeche-2));
  color: var(--s-text, inherit);
  border-radius: var(--radius-voll);
  padding: 6px var(--a4);
  font-size: var(--groesse-s);
  font-weight: 500;
  min-height: 36px;
  transition: box-shadow var(--dauer) var(--kurve);
}
.status-menue > summary:hover {
  box-shadow: inset 0 0 0 1.5px var(--s-punkt, var(--text-3));
}
.status-menue > summary::-webkit-details-marker { display: none; }
/* Farbe und Grösse: siehe Chevron-Begründung (--text-3 lag bei 2,6:1). */
.status-menue > summary::after { content: "▾"; color: var(--text-2); font-size: calc(var(--groesse-xs) * 1.25); }
.status-menue .menue {
  position: absolute;
  top: calc(100% + var(--a1));
  left: 0;
  min-width: 260px;
  max-height: 380px;
  overflow-y: auto;
  background: var(--flaeche);
  border-radius: var(--radius);
  box-shadow: var(--schatten-hebt);
  padding: var(--a1);
  z-index: 50;
}
.menue-eintrag {
  display: flex;
  align-items: center;
  gap: var(--a2);
  width: 100%;
  text-align: left;
  background: transparent;
  font-weight: 400;
  font-size: var(--groesse-s);
  padding: var(--a2) var(--a3);
  min-height: 40px;
  border-radius: 7px;
}
.menue-eintrag:hover { background: var(--hover-flaeche); }
.menue-eintrag.aktuell { font-weight: 650; }
.menue-eintrag.aktuell::after { content: "✓"; margin-left: auto; color: currentColor; }

/* Status-Dropdown: jeder Eintrag in seiner Statusfarbe (heller Grund,
   farbiger Punkt, dunkler Text). Die doppelte Klasse in der Selektor-
   Spezifität ist Absicht: sie schlägt die rote Grundregel für
   button[type="submit"] — kein weißer Text auf satter Fläche mehr. */
.status-menue .menue-eintrag {
  background: var(--s-bg, transparent);
  color: var(--s-text, inherit);
  margin-bottom: 2px;
}
.status-menue .menue-eintrag:last-child { margin-bottom: 0; }
.status-menue .menue-eintrag:hover,
.status-menue .menue-eintrag.aktuell {
  box-shadow: inset 0 0 0 1.5px var(--s-punkt, var(--text-3));
  background: var(--s-bg, var(--flaeche-2));
}

/* Positionen als ruhige Liste */
/* Positionen-Abschnitt im Details-Panel: bewusst dicht — 1–3 Positionen
   sollen das Panel nicht sprengen. Nur Optik, alle Elemente
   (Beschaffungs-Select, Preise, Summen, Nebenposten) unverändert. */
.positionen-abschnitt .positionsliste .position { padding: var(--a2) 0; }
.positionen-abschnitt .position-zeile1 { gap: 2px var(--a3); }
.positionen-abschnitt .position-fuss {
  flex-wrap: wrap;               /* schmale Spalte: Preis/Select dürfen umbrechen */
}
.positionen-abschnitt .position-fuss select {
  min-height: 30px;
  /* 26px waren zu eng, seit der Aufklapp-Pfeil 16px breit ist (U5):
     Er sitzt 10px vom Rand und reichte damit exakt bis an die
     Textkante.
     ⚠ 30 -> 38px am 11.08.2026: Der Pfeil ist auf 24px gewachsen und
     reicht jetzt bis 34px herein; 30px liessen 4px MINUS. Gefunden hat
     es nicht ich, sondern der bestehende Waechter
     test_w3_kein_select_polster_ist_zu_eng_fuer_den_pfeil — mein
     eigener Zeilen-Scan hatte diese Regel uebersehen. */
  padding: 2px 34px 2px var(--a2);
  font-size: var(--groesse-xs);
}
.positionen-abschnitt .auftrag-summen {
  margin-top: var(--a2);
  padding-top: var(--a2);
  gap: var(--a3);
}
.positionen-abschnitt .abweichend { margin-top: var(--a2); }
.positionen-abschnitt .leerzustand { padding: var(--a3) 0; }

.positionsliste .position {
  border-bottom: 1px solid var(--linie);
  padding: var(--a3) 0;
}
.positionsliste .position:last-child { border-bottom: none; }
.position-zeile1 {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) 36px;
  grid-template-areas:
    "nr was  chevron"
    "nr fuss fuss";
  gap: var(--a1) var(--a3);
  align-items: start;
}
/* Notiz und Lager-Felder liegen seit dem 06.08.2026 in der immer
   sichtbaren Kopfzeile (Entscheid Eric, Weg a).

   ⚠ ABSICHTLICH OHNE grid-area UND OHNE EIGENE ZEILE IN
   grid-template-areas. Beides stünde nahe, ist aber falsch: Eine in
   `grid-template-areas` benannte Zeile gehoert zum EXPLIZITEN Raster
   und existiert auch dann, wenn kein Element darin steht — leer zwar
   0 px hoch, aber der `row-gap` davor faellt trotzdem an. Bei einem
   Auftrag wie 3017142 mit 13 Nebenposten (keine Lager-Felder, keine
   Notiz) waeren das zwei Luecken je Zeile fuer nichts.

   `grid-column: 2 / -1` ohne Zeilenangabe laesst die Elemente
   stattdessen automatisch platzieren. Die Spalten 2 und 3 sind in
   Zeile 1 (was/chevron) und Zeile 2 (fuss) belegt, also entsteht je
   Element eine IMPLIZITE Zeile — und nur dann, wenn es das Element
   ueberhaupt gibt. Fehlt es, gibt es die Zeile nicht. */
.position-notiz,
.position-zeile1 .lager-eingaben { grid-column: 2 / -1; }
.position-notiz {
  font-size: var(--groesse-s);
  color: var(--text-2);
  overflow-wrap: anywhere;
}
.position-nr { grid-area: nr; color: var(--rolle-meta-farbe); font-size: var(--rolle-meta-groesse); padding-top: 2px; }
.position-was { grid-area: was; min-width: 0; overflow-wrap: anywhere; padding-top: 2px; }
.position-was .haupt { font-weight: 500; font-size: var(--rolle-titel-groesse); color: var(--rolle-titel-farbe); }
.position-was .neben { color: var(--rolle-meta-farbe); font-size: var(--rolle-meta-groesse); }
.position-zeile1 .zeile-chevron { grid-area: chevron; }
.position-fuss {
  grid-area: fuss;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--a3);
}
.position-menge { font-size: var(--rolle-meta-groesse); color: var(--rolle-meta-farbe); white-space: nowrap; }
.position-fuss select {
  margin: 0;
  width: auto;
  min-width: 0;
  max-width: 220px;
  min-height: 36px;
  font-size: var(--groesse-s);
  padding: 4px 38px 4px var(--a3);
}
.position-mehr {
  display: none;
  padding: var(--a3) 0 0 40px;
  color: var(--text-2);
  font-size: var(--groesse-s);
}
.position.offen .position-mehr { display: block; }
.position-mehr .zeile { margin-bottom: var(--a1); }

/* ══ BESTELLKACHELN IM AUFTRAGSPANEL (U2, 07.08.2026) ══

   `auto-fit`, nicht `auto-fill`: Leere Spuren fallen weg, damit EINE
   Kachel die vollen 540px der Wertspalte bekommt und einzeilig bleibt
   (42px) statt in einer 168px-Spur zu stehen und dreizeilig zu werden.
   Mit `auto-fill` waere der haeufigste Fall — eine einzige Bestellung —
   HOEHER geworden als die alte Zeilenform, also genau verkehrt herum.

   230px als Untergrenze ist gerechnet, nicht geraten: Bei 540px Spalte
   ergibt das zwei Spuren a 266px, und 266px sind die Breite, bei der
   Nummer + Statuschip zuverlaessig in eine Zeile passen (65 + 8 + 136 =
   209px Inhalt bei 226px Platz). Eine dritte Spur (175px) haette den
   Chip auf eine eigene Zeile gedrueckt und jede Kachelreihe von 63 auf
   87px gebracht — drei schmale Kacheln waren in der Messung nicht
   besser als zwei breite. */
.bs-kacheln {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: var(--a2);
}
.bs-kachel {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px var(--a2);
  min-width: 0;
  padding: var(--a2);
  /* Rechts Platz fuer das X, das absolut in der Ecke sitzt — ohne
     dieses Polster liefe die erste Zeile darunter durch. */
  padding-right: calc(var(--a2) + 22px + var(--a1));
  border: 1px solid var(--linie);
  border-radius: var(--radius);
  background: var(--flaeche);
}
.bs-kachel-nr {
  font-size: var(--rolle-titel-groesse);
  font-weight: 650;
  white-space: nowrap;
}
/* Kleinerer Chip als hausueblich, NUR in der Kachel: Mit den 13px und
   2px/10px der Grundregel misst „Wareneingang gebucht" 152px und passt
   neben der Nummer nicht mehr in eine 226px-Zeile. Der Status wird
   NICHT abgeschnitten — er ist die Auskunft, wegen der die Kachel da
   ist; abgeschnitten wird allenfalls der Lieferantenname darunter. */
.bs-kachel .chip {
  font-size: 12px;
  padding: 1px 6px;
}
.bs-kachel-lieferant {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--rolle-meta-groesse);
  color: var(--rolle-meta-farbe);
}
/* C6: Der zugesagte Termin steht in Zeile 2 hinter dem Lieferanten.
   `flex-shrink: 0` ist der Kern der Sache — schrumpfen darf der
   LIEFERANT (er hat den `title` mit dem vollen Namen), nicht das
   Datum. Ein halb abgeschnittenes Datum waere schlimmer als kein
   Datum: „14.08.20…" liest sich wie ein Wert, ist aber keiner. */
.bs-kachel-termin {
  flex: 0 0 auto;
  font-size: var(--rolle-meta-groesse);
  color: var(--rolle-meta-farbe);
  white-space: nowrap;
}
.bs-kachel-leer { border-style: dashed; }
.bs-kachel-x-form { position: absolute; top: var(--a1); right: var(--a1); margin: 0; }
/* ⚠ DER DOPPELTE SELEKTOR IST PFLICHT, NICHT GESCHMACK. `.bs-kachel-x`
   allein hätte die Regel `button[type="submit"]` nicht geschlagen — das
   X wäre ein roter Vollton-Balken in der Kachelecke geworden. Gefunden
   hat das nicht das Auge, sondern der Wächter test_waechter_knopfstile
   beim ersten vollen Lauf am 07.08.2026; CSS meldet so etwas nicht. */
.bs-kachel-x,
button[type="submit"].bs-kachel-x {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  min-height: 0;
  padding: 0;
  border: none;
  border-radius: var(--radius-voll);
  background: transparent;
  color: var(--text-3);
  font-size: var(--groesse-m);
  line-height: 1;
  cursor: pointer;
}
.bs-kachel-x:hover, .bs-kachel-x:focus-visible,
button[type="submit"].bs-kachel-x:hover,
button[type="submit"].bs-kachel-x:focus-visible {
  background: var(--fehler-flaeche);
  color: var(--fehler);
}

/* Begleitschein (Papier-Nachbau) */
.bs-kopf {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--a3);
  margin: var(--a3) 0;
}
.bs-kopf-spalte {
  background: var(--hintergrund);
  border-radius: var(--radius);
  padding: var(--a3) var(--a4);
  min-width: 0;              /* lange Namen sprengen die Spalte nicht */
  overflow-wrap: anywhere;
}
.bs-kopf-titel {
  font-size: var(--rolle-label-groesse);
  font-weight: 550;
  color: var(--rolle-label-farbe);
  margin-bottom: 2px;
}
.bs-kopf-name {
  font-size: var(--groesse-l);
  font-weight: 650;
  letter-spacing: -0.01em;
}
.bs-kopf-name.bs-kopf-leer { color: var(--text-3); font-weight: 400; }
.bs-kopf-meta { color: var(--rolle-meta-farbe); font-size: var(--rolle-meta-groesse); }
/* Belegzitat unter dem Liefertermin: nachgeordnet, kursiv, damit auf den
   ersten Blick erkennbar ist, dass es ein ZITAT ist und keine zweite
   Zusage. Das Datum darueber fuehrt. */
.termin-zitat { font-style: italic; }

.bs-forderungen { margin-top: var(--a4); max-width: 56rem; }
.bs-forderungen textarea { min-height: 56px; font-size: var(--groesse-s); }
.bs-forderungen .feld { margin-bottom: var(--a2); }

/* Reine To-do-Optik (17.07.2026): die frühere nummerierte Achse
   (CSS-Zähler-Kreise + ::after-Liniensegmente, gefärbt über die
   bs-f-*-Zustände aus fortschritt_zustaende) ist bewusst entfernt —
   die Schritte werden nicht zwingend chronologisch abgearbeitet, die
   Nummerierung suggerierte eine falsche Reihenfolge. Beide Listen
   (Begleitschein + Weitere Schritte) fluchten dadurch linksbündig. */
.begleitschein {
  list-style: none;
}
.begleitschein > .bs-zeile {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0 var(--a2);
  border-bottom: 1px solid var(--linie);
}
.begleitschein > .bs-zeile:last-child { border-bottom: none; }
.begleitschein .bs-zeile label {
  flex: 1;
  display: flex;
  flex-wrap: wrap;   /* das rechte Erledigt-Meta darf notfalls umbrechen */
  gap: var(--a3);
  align-items: flex-start;
  min-height: 44px;
  padding: var(--a2);
  border-radius: var(--radius);
  color: var(--rolle-titel-farbe);
  font-weight: 500;
  font-size: var(--rolle-titel-groesse);
  cursor: pointer;
  transition: background var(--dauer) var(--kurve);
}
.begleitschein .bs-zeile label:hover { background: var(--hover-flaeche); }
.begleitschein .bs-zeile input[type="checkbox"] { margin-top: 3px; }
.begleitschein .bs-zeile .meta {
  display: block;
  font-weight: 400;
  font-size: var(--rolle-meta-groesse);
  color: var(--rolle-meta-farbe);
}
/* Erledigt-Meta einzeilig rechts: Titel links | Datum · Person rechts,
   dünne Trennlinie, vertikal zentriert (beide Listen). */
.begleitschein .bs-erledigt-meta,
.meilensteine .bs-erledigt-meta {
  margin-left: auto;
  align-self: center;
  padding-left: var(--a3);
  border-left: 1px solid var(--linie);
  font-weight: 400;
  font-size: var(--rolle-meta-groesse);
  color: var(--rolle-meta-farbe);
  text-align: right;
  white-space: nowrap;
  /* ══ ZWEIZEILIG (Entscheid Eric, 12.08.2026) ══
     Vorher stand „10.08.2026 · Dilexen" in EINER Zeile und brauchte die
     volle Breite. Der NAME steht oben — er wird haeufiger gesucht als
     das Datum, und das Datum darf kleiner sein.
     ⚠ HIER und nicht als zweite Regel weiter unten: Zwei Bloecke fuer
     denselben Namen sind zwei Wahrheiten, und welche gewinnt, haengt an
     der Reihenfolge in der Datei. */
  display: inline-flex;
  flex-direction: column;
  line-height: 1.15;
}
.begleitschein .erledigt label { color: var(--text-2); }
.begleitschein .erledigt .stein-name {
  text-decoration: line-through;
  text-decoration-color: var(--text-3);
}
/* Ausgegraute Zeilen: klar als deaktiviert erkennbar — gedämpft PLUS
   ausgeschriebener Grund (WCAG AA: der Grund-Text behält vollen Kontrast). */
.begleitschein .gesperrt label,
.meilensteine .gesperrt label { opacity: 0.55; cursor: not-allowed; }
.begleitschein .gesperrt label:hover,
.meilensteine .gesperrt label:hover { background: transparent; }
.gesperrt-grund {
  display: block;
  font-size: var(--rolle-meta-groesse);
  font-weight: 500;
  color: var(--rolle-meta-farbe);
}
.gesperrt .gesperrt-grund { opacity: 1; }
.bs-entsperren { flex: 0 0 auto; align-self: center; }
/* S4 (21.09.2026): Rückgängig am eigenen, frischen Haken — steht wie
   „Entfernen" am Zeilenende, nur deklarierte Hausvariablen. */
/* Hinzufügen oder Ersetzen? — ZWEI GLEICH GROSSE Knöpfe (Vorgabe Eric,
   21.09.2026): keine Aufklappliste, kein kleiner Link, keine Voreinstellung. */
.bs-beleg-frage { max-width: 720px; width: 92vw; }
.bs-frage-liste { list-style: none; margin: var(--a3) 0; padding: 0; }
.bs-frage-liste li {
  display: flex; align-items: baseline; gap: var(--a2); flex-wrap: wrap;
  padding: var(--a2) 0; border-bottom: 1px solid var(--linie);
}
.bs-frage-name { font-size: var(--groesse-s); }
/* Vorhandenen Beleg an eine Zeile legen (partials/belegwahl.html). */
.bs-beleg-waehlen {
  background: none; border: 0; padding: 0; min-height: 0;
  color: var(--text-2); font-size: var(--groesse-xs);
  text-decoration: underline; cursor: pointer;
}
.belegwahl { max-width: 760px; width: 92vw; }
.belegwahl-liste { list-style: none; margin: var(--a3) 0; padding: 0; }
.belegwahl-liste li {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: center; column-gap: var(--a4);
  padding: var(--a2) 0; border-bottom: 1px solid var(--linie);
}
.belegwahl-angaben { min-width: 0; overflow-wrap: anywhere; }
.belegwahl-angaben .meta { display: block; }
.belegwahl-liste li > button { justify-self: end; white-space: nowrap; }

/* DAS EINE Vorschau-Fenster (base.html, partials/vorschau_makro.html). */
.beleg-vorschau { width: 92vw; max-width: 1100px; padding: var(--a3); }
.beleg-vorschau-kopf {
  display: flex; align-items: baseline; gap: var(--a4); margin-bottom: var(--a2);
}
.beleg-vorschau-kopf strong { flex: 1 1 auto; overflow-wrap: anywhere; }
.beleg-vorschau-rahmen iframe {
  width: 100%; height: 78vh; border: 1px solid var(--linie);
  border-radius: var(--radius); background: var(--flaeche-2);
}
.bs-frage-alt { margin: var(--a3) 0; }
.bs-frage-alt label { display: block; padding: var(--a1) 0; }
.bs-frage-knoepfe { display: flex; gap: var(--a3); margin: var(--a4) 0 var(--a3); }
.bs-frage-knoepfe button {
  flex: 1 1 0;
  min-height: 64px;
  font-size: var(--groesse-m);
  font-weight: 600;
}
.bs-frage-abbrechen { display: block; margin: 0 auto; }
.bs-ersetzt-hinweis {
  flex-basis: 100%;
  font-size: var(--groesse-xs);
  color: var(--warnung);
}
.bs-rueckgaengig { flex: 0 0 auto; align-self: center; color: var(--akzent); }
.meilensteine li { display: flex; align-items: center; gap: var(--a2); }
.meilensteine li > label { flex: 1; min-width: 0; }
/* Lieferschein-Zeile als Dreiteiler: Titel links (Label nur so breit
   wie nötig), Eingabefeld in der Mitte, Erledigt-Meta ganz rechts.
   Das Meta ist hier ein Zeilen-Kind statt im Label — margin-right
   gleicht das Label-Padding aus, damit die rechte Fluchtlinie mit den
   übrigen erledigten Zeilen exakt durchgeht. */
.bs-wert {
  width: 170px;
  min-height: 36px;
  font-size: var(--groesse-s);
  margin: var(--a1) 0;
  align-self: center;
}
.bs-apz {
  align-items: center;
  min-height: 44px;
}
.bs-apz .stein-name { font-weight: 500; font-size: var(--groesse-s); padding: var(--a2); }
.bs-jn { display: flex; gap: var(--a1); margin-left: auto; padding: var(--a1) 0; }
.bs-jn button {
  min-height: 32px;
  padding: 2px var(--a3);
  font-size: var(--groesse-xs);
  font-weight: 600;
  border-radius: var(--radius-voll);
}
.bs-jn button.aktiv { background: var(--akzent); color: #fff; }
/* .bs-vorschlag / .bs-blockiert entfielen mit Nachtrag 7 — das Abhaken
   setzt den Status selbst, es gibt keinen Vorschlags-Kasten mehr. */

/* Material-Blockade (Nachtrag 7): Häkchen sitzt, Status wartet — die
   blockierenden Positionen einzeln zum Nachziehen (Teillieferung). */
.bs-blockade { display: block; }
.bs-blockade form { margin-top: var(--a3); }
.bs-blockade-frage {
  margin: 0 0 var(--a2);
  font-size: var(--groesse-xs);
  color: var(--rolle-label-farbe);
  font-weight: 550;
}
.bs-blockade-liste { margin: 0 0 var(--a3); }
.bs-blockade-liste li { padding: 2px 0; }
.bs-blockade-liste label {
  display: flex;
  align-items: baseline;
  gap: var(--a2);
  font-size: var(--groesse-s);
}

/* Meilensteine */
.meilensteine li { padding: 2px 0; }
.meilensteine label {
  display: flex;
  flex-wrap: wrap;
  gap: var(--a3);
  align-items: flex-start;
  min-height: 40px;
  padding: var(--a2) var(--a2);
  margin: 0 calc(-1 * var(--a2));
  border-radius: var(--radius);
  color: var(--rolle-titel-farbe);
  font-weight: 400;
  font-size: var(--rolle-titel-groesse);
  cursor: pointer;
  transition: background var(--dauer) var(--kurve);
}
.meilensteine label:hover { background: var(--hover-flaeche); }
.meilensteine input[type="checkbox"] { margin-top: 2px; }
.meilensteine .erledigt { color: var(--text-2); }
.meilensteine .erledigt .stein-name { text-decoration: line-through; text-decoration-color: var(--text-3); }
.meilensteine .meta { display: block; font-size: var(--rolle-meta-groesse); color: var(--rolle-meta-farbe); }

/* Dokumente */
.dok-liste { margin-bottom: var(--a4); list-style: none; padding: 0; }
.dok-item {
  padding: var(--a2) 0;
  border-bottom: 1px solid var(--linie);
  font-size: var(--groesse-s);
}
/* Die reduzierte Zeile ist zugleich <summary> des Aufklapp-Dropdowns:
   Symbol/Thumbnail · Name · (Datum · Person) · Pfeil. */
summary.dok-zeile {
  display: flex;
  align-items: center;
  gap: var(--a3);
  cursor: pointer;
  list-style: none;
  padding: var(--a1) 0;
}
summary.dok-zeile::-webkit-details-marker { display: none; }
summary.dok-zeile:focus-visible {
  outline: 2px solid var(--akzent);
  outline-offset: 2px;
  border-radius: var(--radius);
}
.dok-symbol { flex: 0 0 auto; display: inline-flex; color: var(--text-3); }
.dok-symbol svg { width: 22px; height: 22px; }
.dok-thumb {
  flex: 0 0 auto;
  width: 36px; height: 36px;
  border: 1px solid var(--linie);
  border-radius: var(--radius);
  overflow: hidden;
  display: block;
}
.dok-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Name + (Datum · Person) als Stapel, nimmt den freien Platz. */
.dok-haupt { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.dok-meta {
  color: var(--text-3);
  font-size: var(--groesse-xs);
  overflow-wrap: anywhere;
}
/* Aufklapp-Pfeil ganz rechts, dreht beim Öffnen. */
.dok-pfeil { flex: 0 0 auto; color: var(--text-3);
  transition: transform var(--dauer) var(--kurve); }
.dok-aufklapp[open] .dok-pfeil { transform: rotate(180deg); }
/* Aufgeklappter Bereich: Erkennung, Warnungen, Größe, Aktionen. Inhalt
   linksbündig unter dem Dateinamen (Symbolbreite + Abstand). */
.dok-ausklapp {
  padding: var(--a2) 0 var(--a2) calc(22px + var(--a3));
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--a1);
  font-size: var(--groesse-xs);
}
.dok-erk-felder { overflow-wrap: anywhere; }
.dok-ausklapp-fuss {
  display: flex;
  align-items: center;
  gap: var(--a2);
  margin-top: var(--a1);
}
.dok-groesse { color: var(--text-3); }
.dok-aktionen-text { display: inline-flex; align-items: center; gap: var(--a1); }
.dok-aktionen-text form { margin: 0; }
/* Transienter Hinweis, solange die Erkennung läuft. */
.dok-status { margin-top: var(--a1); }
.dok-hinweis {
  flex-basis: 100%;
  color: var(--warnung);
  font-size: var(--groesse-xs);
}
/* Handlungsaufforderung direkt unter der Dokumentzeile — schmal und bündig
   unter dem Dateinamen (gleicher Einzug wie der Aufklapp-Inhalt). */
.dok-vorschlag {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--a2);
  flex-wrap: wrap;
  background: var(--akzent-flaeche);
  border-radius: var(--radius);
  padding: 2px var(--a2) 2px var(--a3);
  margin: 2px 0 var(--a1) calc(22px + var(--a3));
  font-size: var(--groesse-xs);
}
.dok-vorschlag-aktionen { display: flex; gap: var(--a1); }
/* Vorschlag aus Scan/niedriger Konfidenz: sichtbar anders als "hoch". */
.dok-vorschlag.mit-vorbehalt { background: var(--warnung-flaeche); }
.vorschlag-vorbehalt {
  display: block;
  font-size: var(--groesse-xs);
  color: var(--warnung);
}
.dok-item:last-child { border-bottom: none; }
.dok-name {
  min-width: 0;
  overflow-wrap: anywhere;
  font-weight: 500;
}
/* Betreff einer abgelegten Mail: zwischen Dateiname und Metazeile, eine
   Stufe leiser als der Name, aber lesbarer als die Meta-Angaben. Der
   Dateiname einer .msg ist der Betreff mit ersetzten Sonderzeichen
   („Re_ Order Confirmation  3017063.msg") — der echte Betreff sagt mehr. */
.dok-betreff {
  color: var(--text-2);
  font-size: var(--groesse-s);
  overflow-wrap: anywhere;
}
.dok-upload { display: flex; align-items: center; gap: var(--a3); flex-wrap: wrap; }
.dok-upload input[type="file"] { font-size: var(--groesse-s); min-width: 0; flex: 1; }
/* Mehrfach-Upload: das Formular ist zugleich Ablagefläche fürs Ziehen. */
.dok-upload {
  border: 1px dashed var(--linie);
  border-radius: var(--radius);
  padding: var(--a3);
  transition: border-color var(--dauer) var(--kurve),
              background-color var(--dauer) var(--kurve);
}
.dok-upload.zieht {
  border-color: var(--akzent);
  background: var(--akzent-flaeche);
}
.dok-upload-hinweis {
  flex-basis: 100%;
  font-size: var(--groesse-xs);
  color: var(--text-3);
}

/* Weg A: Erkennungs-Dropzone + Ergebnisblock der manuellen Anlege-Seite.
   Die Dropzone erbt die dok-upload-Mechanik (dashed, .zieht). */
.erkennung-upload { margin-bottom: var(--a4); background: var(--flaeche); }
.erkennung-upload-text {
  display: flex;
  align-items: center;
  gap: var(--a3);
  flex-wrap: wrap;
  font-size: var(--groesse-s);
  font-weight: 400;
  color: var(--text-2);
  cursor: pointer;
}
.erkennung-laeuft {
  display: flex;
  align-items: center;
  gap: var(--a2);
  margin-bottom: var(--a4);
}
.erkennung-ergebnis { margin-bottom: var(--a4); }
.erkennung-ergebnis .chip-warnung { margin: var(--a2) 0; }
.abgleich-warnung { color: var(--warnung); font-weight: 550; }

/* Kommentare als Verlauf */
.nachrichten { margin-bottom: var(--a4); }
.nachricht {
  padding: var(--a3) var(--a4);
  background: var(--hintergrund);
  border-radius: var(--radius);
  margin-bottom: var(--a2);
  font-size: var(--groesse-s);
  overflow-wrap: anywhere;
}
.nachricht .meta { margin-bottom: 2px; }
.nachricht.system {
  background: transparent;
  color: var(--text-2);
  font-size: var(--groesse-xs);
  text-align: center;
  padding: var(--a1);
}
.nachricht-form textarea {
  min-height: 44px;
  font-size: var(--groesse-s);
}
.nachricht-form { display: flex; flex-direction: column; align-items: flex-end; gap: var(--a2); }
.nachricht-form textarea { align-self: stretch; }
/* Seit „neueste zuerst“: Eingabefeld OBEN zwischen Tab-Leiste und
   Strom — die Trennlinie (volle Breite, --linie wie überall) plus Luft
   darüber/darunter macht es als eigenen Bereich kenntlich, damit es
   nicht wie der erste Listeneintrag wirkt. */
.nachricht-form-oben {
  padding-bottom: var(--a4);
  border-bottom: 1px solid var(--linie);
  margin-bottom: var(--a4);
}

/* Verlauf (Aktivität) */
details.verlauf > summary {
  list-style: none;
  cursor: pointer;
  color: var(--akzent);
  font-size: var(--groesse-s);
  min-height: 40px;
  display: inline-flex;
  align-items: center;
}
details.verlauf > summary::-webkit-details-marker { display: none; }
details.verlauf[open] > summary { color: var(--text-2); }
.verlauf-liste { margin-top: var(--a3); }
.verlauf-liste li {
  padding: var(--a2) 0;
  border-bottom: 1px solid var(--linie);
  font-size: var(--groesse-s);
  color: var(--text-2);
  overflow-wrap: anywhere;   /* lange Alt/Neu-Werte, z. B. Forderungstexte */
}
.verlauf-liste li:last-child { border-bottom: none; }
.verlauf-liste .aenderung { color: var(--text); }

/* Tab-Leiste des Verlaufs (Jira-Vorbild): dezente Knöpfe, der aktive
   trägt eine 2px-Akzentlinie unten. */
.verlauf-tabs {
  display: flex;
  gap: var(--a1);
  flex-wrap: wrap;
  border-bottom: 1px solid var(--linie);
  margin-bottom: var(--a3);
}
.verlauf-tab {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  padding: var(--a1) var(--a2);
  font-size: var(--groesse-s);
  color: var(--text-2);
  cursor: pointer;
  min-height: 36px;
}
.verlauf-tab:hover { color: var(--text); background: var(--hover-flaeche, transparent); }
.verlauf-tab.aktiv {
  color: var(--text);
  font-weight: 550;
  border-bottom-color: var(--akzent);
}

/* Der EINE Verlauf (18.07.2026): Kommentare als Kästen (.nachricht,
   unverändert), automatische Einträge als dezente Einzeiler — optisch
   klar voneinander abgesetzt. */
.verlauf-strom .verlauf-eintrag {
  padding: var(--a1) var(--a2);
  font-size: var(--groesse-s);
  color: var(--text-2);
  overflow-wrap: anywhere;      /* lange Alt/Neu-Werte */
}
.verlauf-strom .verlauf-eintrag .meta { margin-right: var(--a2); }
.verlauf-strom .verlauf-eintrag .aenderung { color: var(--text); }
/* Übergabe-Kommentare tragen denselben .nachricht-Kasten wie echte
   Kommentare — nur die Kontextzeile nennt die Zuweisung. */
.nachricht .zuweisung-kontext { margin-bottom: 2px; }
.nachricht .nachricht-text { white-space: pre-wrap; }  /* Klartext */

/* Detailseiten-Raster */
.detail-raster {
  display: grid;
  /* 1.2:1 statt 2:1 — auf breiten Schirmen bekommen Positionen/Kommentare
     echte Arbeitsbreite, der Begleitschein bleibt trotzdem führend. */
  grid-template-columns: minmax(0, 1.2fr) minmax(19rem, 1fr);
  gap: var(--a5);
  align-items: start;
}


/* ---------- Anmeldung ---------- */

/* Login-Bühne: Foto full-bleed hinter einer hellen, zentrierten Karte.
   Dezentes dunkles Overlay gibt dem Foto Tiefe und hebt die Karte ab. */
.anmeldung-buehne {
  position: fixed;
  inset: 0;
  display: flex;
  overflow: auto;
  padding: var(--a4);
  background:
    linear-gradient(rgba(15, 17, 20, 0.34), rgba(15, 17, 20, 0.34)),
    url("/static/img/login_hintergrund.jpg") center / cover no-repeat;
}
/* Anmeldekarte: Wortmarke, Button UND Logo liegen bewusst auf der hellen
   Karte — die schwarze Wortmarke und das Basedo-Logo wären direkt auf dem
   Foto nicht zuverlässig lesbar. margin:auto zentriert overflow-sicher
   (schmales/niedriges Fenster: Foto wird beschnitten, Karte nie). */
.anmeldung {
  margin: auto;
  width: 100%;
  max-width: 380px;
  background: var(--flaeche);
  border-radius: var(--radius-gross);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
  padding: var(--a6);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--a5);
  text-align: center;
}
.anmeldung form { width: 100%; }
.anmeldung button[type="submit"] { width: 100%; }
.anmeldung-logo { display: block; width: 70%; max-width: 240px; height: auto; }
/* ODIN-Wortmarke — futuristisch (Orbitron), groß, technisch, schwarz. */
.wortmarke {
  font-family: "Orbitron", var(--schrift, sans-serif);
  font-weight: 700;
  font-size: clamp(2.75rem, 11vw, 4.25rem);
  line-height: 1;
  letter-spacing: 0.14em;
  text-indent: 0.14em;  /* optischer Ausgleich des Letter-Spacings rechts */
  color: var(--text);
  margin: 0;
}

/* Offizieller „Mit Microsoft anmelden“-Button (Microsoft-Branding-Richtlinie).
   Dunkle Variante — kontrastiert klar auf der hellen Anmeldekarte. Vier-
   Quadrate-Logo als lokales SVG, Segoe UI, quadratische Ecken. */
.anmeldung .ms-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  height: 41px;
  min-height: 41px;
  padding: 0 12px;
  background: #2f2f2f;
  color: #ffffff;
  border: 1px solid #2f2f2f;
  border-radius: 0;
  font-family: "Segoe UI", var(--schrift, sans-serif);
  font-size: 15px;
  font-weight: 600;
}
.anmeldung .ms-button:hover { background: #1f1f1f; border-color: #1f1f1f; text-decoration: none; }
.ms-button-logo { display: block; flex: 0 0 auto; }

/* ---------- Mobil / Tablet ---------- */

@media (max-width: 900px) {
  main { padding: var(--a4); }
  .feldraster { grid-template-columns: 1fr; }
  .detail-raster { grid-template-columns: 1fr; }
  .bs-kopf { grid-template-columns: 1fr; }
  .zeile-kompakt {
    grid-template-columns: 1fr 1fr 36px 36px;
  }
  .zeile-kompakt .f-werkstoff { grid-column: 1 / 3; }
  .zeile-kompakt .f-abmessung { grid-column: 1 / 3; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* --------------------------------------------- Seitenleiste: Upload-Knopf
   Großer Zugang zum Dokumenteneingang, zugleich Drop-Fläche: eine
   hierher gezogene PDF wird sofort hochgeladen (form.dok-upload-JS). */
.leiste-upload {
  display: block;
  margin-top: auto;   /* drückt den Knopf ans Leisten-Ende */
  border: none;
  padding: 0;
}
/* ── PDF-Werkzeug: ein LINK, keine Ablagefläche (11.08.2026) ────────
   ⚠ BLAU ALS VERWECHSLUNGSSCHUTZ. Die rote Fläche darunter liest
   Belege ein, die blaue öffnet ein Werkzeug. Ein Beleg, der im
   PDF-Werkzeug landet statt in der Erkennung, wird nicht erkannt und
   nicht zugeordnet — und es entsteht kein Fehler, an dem es auffiele.
   Abstand zur roten Fläche: ΔE 44,4 (CIEDE2000).

   ⚠ DIE FARBE IST EIN HAUSBLAU, KEINE ERFUNDENE: `#0C5DA6` ist der
   Punktton der Lager-Statusfamilie. Er bekommt hier einen EIGENEN
   Namen, weil er an dieser Stelle keinen Status bedeutet — wer
   `--werkzeug` liest, sucht nicht in der Statustabelle.
   Kontrast: 6,70:1 gegen den weissen Leistengrund (Schwelle 3:1 für
   grafische Objekte), weisse Schrift darauf ebenfalls 6,70:1
   (Schwelle 4,5:1).

   ⚠ ZEILENHÖHE, NICHT FLÄCHE, und das ist Absicht: Die Ablagefläche
   darunter ist 96 px hoch, weil man etwas hineinzieht. Hier zieht
   niemand etwas hinein — Ziehen nach Stirling ist nicht möglich
   (`types.includes("Files")`-Riegel, am Bundle gemessen). Ein Knopf,
   der wie ein Ziel aussieht und keines ist, kostet einen Versuch und
   eine Erklärung. Die 40 px sind die Höhe der Menüpunkte, und genau
   das ist er: ein Link. */
.werkzeug-knopf {
  --werkzeug: #0C5DA6;
  display: flex;
  align-items: center;
  gap: var(--a2);
  min-height: 40px;
  padding: 0 var(--a3);
  border-radius: var(--radius);
  background: var(--werkzeug);
  color: #fff;
  font-weight: 600;
  text-decoration: none;
  transition: background-color var(--dauer) var(--kurve);
}
.werkzeug-knopf:hover { background: #0A4176; }
.werkzeug-knopf .nav-icon { flex: none; }

.upload-knopf {
  /* QUADRATISCH statt Zeile (28.07.2026): Das Plus steht mittig, der
     Text darunter. Der Knopf ist der einzige sichtbare Anlageweg und
     darf deshalb Fläche beanspruchen — er soll das Ziel sein, das man
     beim Blick in die Leiste zuerst findet. */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* ⚠ VERKLEINERT AM 11.08.2026 (Eric: „riesig"). Vorher stand hier
     `aspect-ratio: 1` — bei 240 px Leistenbreite minus 2 × 12 px
     Polster waren das 216 × 216 px, also rund ein Fünftel der
     Leistenhöhe auf einem 1080er Schirm.

     ⚠ ES IST NICHT NUR EIN KNOPF, SONDERN DIE ABLAGEFLÄCHE FÜR BELEGE
     — der Hauptweg, auf dem PDFs ins Haus kommen. Deshalb NICHT auf
     Zeilenhöhe wie die Menüpunkte, sondern 96 px hoch bei voller
     Breite: 216 × 96 px sind 20 736 px², also 44 % der alten Fläche,
     aber ein Ziel, das man ohne Zielen trifft. Nach Fitts zählt für
     einen Zug aus dem Explorer die kürzere Achse, und die volle
     Leistenbreite bleibt erhalten — waagerecht muss niemand zielen.

     ⚠ WER SIE WEITER VERKLEINERT, prüft zuerst, ob sie noch als
     Fläche gelesen wird: Der gestrichelte Rand beim Ziehen und die
     Zeile „oder hierher ziehen" brauchen Platz. Ohne beides ist es
     ein Knopf, und ein Knopf lädt nicht zum Ablegen ein. */
  min-height: 96px;
  gap: var(--a1);
  padding: var(--a3);
  border-radius: var(--radius);
  background: var(--akzent);
  color: #fff;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  border: 1px dashed transparent;
  transition: background-color var(--dauer) var(--kurve);
}
.upload-plus {
  font-size: 2.75rem;
  font-weight: 300;   /* dünn — ein fettes Plus wirkt wie ein Fehlerzeichen */
  line-height: 1;
}
.upload-knopf:hover { background: var(--akzent-hover); color: #fff; }
.upload-knopf .nav-icon { flex: none; }
.upload-knopf .nav-text { display: flex; flex-direction: column; line-height: 1.3; }
.upload-knopf .nav-text small {
  font-weight: 400;
  font-size: var(--groesse-xs);
  opacity: .85;
}
.leiste-upload.zieht { background: none; border: none; }
.leiste-upload.zieht .upload-knopf {
  background: var(--akzent-hover);
  border-color: #fff;
}
/* Eingeklappte Leiste (64px): Der Text ist ohnehin ausgeblendet
   (body.leiste-zu .nav-text), das Plus trägt den Knopf allein. Das
   Seitenverhältnis bleibt quadratisch, nur kleiner. */
body.leiste-zu .upload-knopf { padding: var(--a2); }
body.leiste-zu .upload-plus { font-size: 1.75rem; }

/* Auftrags-Vorschau: Positionszeilen in AB-Reihenfolge, Nebenposten
   (ohne Pos.-Nr.) leicht abgesetzt. */
.vorschau-position { margin-bottom: var(--a4); }
.vorschau-pos-kopf {
  font-size: var(--groesse-s);
  font-weight: 650;
  margin-bottom: var(--a1);
}
.vorschau-nebenposten .vorschau-pos-kopf { color: var(--text-2); font-weight: 500; }
.vorschau-nebenposten { padding-left: var(--a4); border-left: 2px solid var(--linie); }

/* Auftrags-Summen unter der Positionsliste (Preise vom AB). */
.auftrag-summen {
  display: flex;
  flex-wrap: wrap;
  gap: var(--a4);
  justify-content: flex-end;
  padding: var(--a3) var(--a2) 0;
  border-top: 1px solid var(--linie);
  margin-top: var(--a3);
  font-size: var(--groesse-s);
  color: var(--text-2);
}
.auftrag-summen strong { color: var(--text); }
.position-preis { white-space: nowrap; }

/* „×" an einer Positionszeile der Vorschau (28.07.2026). Die Zeile wird
   GELEERT, nicht entfernt — der Formular-Index muss bleiben, sonst
   meldet die Verlustprüfung E1a einen technischen Verlust, der Absicht
   war. Der abgeblendete Zustand zeigt: hier stand etwas, es ist weg. */
.zeile-leeren {
  float: right;
  border: none;
  background: none;
  color: var(--text-leise);
  font-size: var(--groesse-l);
  line-height: 1;
  cursor: pointer;
  padding: 0 var(--a1);
}
.zeile-leeren:hover { color: var(--gefahr); }
.position-zeile.zeile-geleert { opacity: .45; }

/* ---- Kundenfilter: EIN Knopf, Dropdown darunter (28.07.2026) --------
   Die Chips liegen IM Dropdown. Vorher standen sie darunter in der
   Filterleiste und schoben bei langen Firmennamen den Bestellware-Filter
   aus dem Bild. Der Knopf hat feste Hoehe; die Leiste bleibt ruhig,
   egal wie viele Kunden gewaehlt sind. */
.kundenfilter { position: relative; display: inline-block; }
.kundenfilter-knopf { max-width: 22rem; overflow: hidden;
                      text-overflow: ellipsis; white-space: nowrap; }
.kundenfilter-menue { position: absolute; top: calc(100% + .25rem); left: 0;
                      z-index: 40; min-width: 24rem; padding: .5rem;
                      background: var(--flaeche); border: 1px solid var(--rand);
                      border-radius: .4rem;
                      box-shadow: 0 .5rem 1.5rem rgba(0,0,0,.18); }
.kundenfilter-suche { width: 100%; }
.kundenfilter-chips { display: flex; flex-wrap: wrap; gap: .25rem;
                      margin-top: .5rem; }
.kundenfilter-chips:empty { display: none; }
.kundenfilter .vorschlaege { margin: .5rem 0 0; padding: 0; list-style: none;
                             max-height: 16rem; overflow-y: auto; }
.kundenfilter .vorschlaege:empty { display: none; }
.kundenfilter .vorschlag { padding: .3rem .5rem; cursor: pointer;
                           border-radius: .25rem; }
.kundenfilter .vorschlag.gewaehlt,
.kundenfilter .vorschlag:hover { background: var(--auswahl, rgba(0,0,0,.06)); }

/* ===================== Lagerübersicht (Lagermodul, 31.07.2026) ========
   Das AUSSEHEN ist mit der bestehenden Übersicht geteilt: .board,
   .spalte, .karten und .karte kommen unverändert von dort. Neu ist nur,
   was die Lagerkarte zusätzlich trägt — die Positionsliste.

   BREITE, gerechnet (berichte/lagermodul-messung.md, L12): sechs Spalten
   zu 238px bei 1496px Board-Innenbreite auf Full HD; abzüglich Spalten-
   und Kartenpolster bleiben rund 195px Textbreite. Deshalb je Position
   EINE Zeile mit Ellipse — der volle Text steht im title. */
.board-lager .spalte { flex: 1 1 0; min-width: 210px; }

.lager-zaehler {
  flex: 0 0 auto;
  font-size: var(--groesse-xs);
  font-weight: 650;
  color: var(--text-2);
}
.lager-zaehler-gesamt { color: var(--text-3); font-weight: 400; }

.lager-positionen {
  list-style: none;
  margin: var(--a2) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.lager-position {
  display: flex;
  align-items: baseline;
  gap: var(--a1);
  font-size: var(--groesse-xs);
  line-height: 1.35;
  min-width: 0;
}
.lager-pos-nr {
  flex: 0 0 auto;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.lager-pos-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Priorität als schmales Merkmal ganz links. Ein ausgeschriebenes „Hoch“
   kostet ein Drittel der Zeilenbreite; der Klartext steht im title. */
.prio-strich {
  flex: 0 0 3px;
  align-self: stretch;
  border-radius: 2px;
  background: transparent;
}
.lager-position.p-hoch .prio-strich { background: var(--fehler); }
.lager-position.p-niedrig .prio-strich { background: var(--text-3); }
/* „normal“ trägt bewusst KEINE Farbe: Wenn vier von fünf Zeilen
   eingefärbt sind, hebt die Farbe nichts mehr hervor. */

/* Fertig gemeldet: bleibt STEHEN (Fach-Entscheid E7), gedämpft und
   durchgestrichen. Beides zusammen, nicht nur die Dämpfung — die Nutzer
   sitzen über RDP in einem sehr hellen Raum, und die Kompression frisst
   schwache Kontraste. Die Linie trägt die Aussage auch dann, wenn die
   Farbe untergeht. Deckkraft bewusst nicht unter 0.6. */
.lager-position.fertig {
  opacity: .62;
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}
.lager-position.fertig .prio-strich { background: transparent; }

.lager-leer {
  margin-top: var(--a2);
  font-size: var(--groesse-xs);
  color: var(--text-3);
  font-style: italic;
}

/* Lager-Eingaben in der Positionszeile: Bearbeiter, Priorität und
   Bearbeitungsstand stehen in EINER Zeile. Sie erscheinen nur an
   Materialpositionen (oder an Positionen mit Zuteilung/Fertigmeldung,
   sonst gäbe es keinen Rückweg).

   ⚠ SEIT DEM 06.08.2026 IN DER IMMER SICHTBAREN KOPFZEILE, nicht mehr
   im Aufklapper (Entscheid Eric, Weg a, alle drei Felder, alle
   Rollen). Damit sind `margin-top`, `padding-top` und die `border-top`
   ENTFALLEN: Sie trennten den Block vom Aufklapp-Inhalt darüber. In
   der Kopfzeile zögen sie eine Linie quer durch die Zeile, mitten
   zwischen Preis und Feldern.

   Der Abstand zur Zeile darüber kommt jetzt vom `row-gap` des
   Rasters. Breite: die drei Felder brauchen zusammen 371 px
   (Bearbeiter 141, Priorität 103, Bearbeitung 111, zweimal 8 px
   Abstand), gemessen 06.08.2026 in Arimo mit den Vorgabe-Spaltennamen.
   Zur Verfügung stehen seit der gleichen Rasterbreite 604 px — 233 px
   Reserve. Deutlich längere Bearbeiter-Namen zehren daran; bei
   Überlauf bricht `flex-wrap` in eine zweite Zeile, was 53,5 px
   kostet, aber nichts abschneidet. */
.lager-eingaben {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: var(--a2);
}
.lager-feld {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: var(--groesse-xs);
  color: var(--text-2);
}
.lager-feld select { min-height: 32px; margin: 0; }
.lager-fertig-meta {
  font-size: var(--groesse-xs);
  color: var(--text-2);
  align-self: center;
}

/* Sprung von der Board-Spalte „Lager" auf die Lagerübersicht. Dezent:
   Der Spaltenkopf ist keine Navigationsleiste, der Link soll nur beim
   Hinsehen als solcher erkennbar sein. */
.spalte-sprung { color: inherit; text-decoration: none; }
.spalte-sprung:hover { color: var(--akzent); text-decoration: underline; }

/* Umbenennen der Bearbeiter-Spalten (B7): ein <details> im Spaltenkopf,
   wie die Quickfilter der Übersicht — Öffnen/Schließen ohne JS. Die
   Überschrift sieht im geschlossenen Zustand aus wie die der übrigen
   Spalten; erst der Zeiger verrät, dass sie anklickbar ist. */
.spalte-umbenennen { min-width: 0; }
.spalte-umbenennen > summary {
  list-style: none;
  cursor: pointer;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.spalte-umbenennen > summary::-webkit-details-marker { display: none; }
.spalte-umbenennen > summary:hover { color: var(--akzent); }
.spalte-umbenennen[open] > summary { color: var(--akzent); }
.spalte-umbenennen .menue { min-width: 15rem; }

/* Untermenü der Lagerübersicht (C3): die fünf Detaillisten. Für das
   Lager dauerhaft offen, für andere zugeklappt. */
.nav-unter { margin: 0; }
.nav-unter > summary {
  list-style: none;
  cursor: pointer;
  padding: var(--a1) var(--a3);
  font-size: var(--groesse-xs);
  color: var(--text-3);
}
.nav-unter > summary::-webkit-details-marker { display: none; }
.nav-unterpunkt { padding-left: var(--a6); font-size: var(--groesse-xs); }

/* Detailliste (C2) */
.lagerliste { width: 100%; border-collapse: collapse; font-size: var(--groesse-s); }
.lagerliste th, .lagerliste td { padding: var(--a1) var(--a2); text-align: left; }
.lagerliste thead th { font-size: var(--groesse-xs); color: var(--text-2);
                       border-bottom: 1px solid var(--linie); }
.lagerliste-auftrag th { padding-top: var(--a4); border-bottom: 1px solid var(--linie); }
.lagerliste-auftrag .meta { margin-left: var(--a3); font-weight: 400; }
.lager-zeile select { min-height: 30px; margin: 0; font-size: var(--groesse-xs); }
.lager-zeile.p-hoch .lz-prio { border-left: 3px solid var(--fehler); }
.lager-zeile.p-niedrig .lz-prio { border-left: 3px solid var(--text-3); }
.lager-zeile.fertig { opacity: .62; }
.lager-zeile.fertig .lz-pos, .lager-zeile.fertig td:nth-child(3),
.lager-zeile.fertig td:nth-child(4), .lager-zeile.fertig td:nth-child(5) {
  text-decoration: line-through;
}

/* ================= Zuständig-Zelle in den Listen (04.08.2026) =========
   Das Dropdown sitzt in einer Tabellenzeile, die ab Schritt 3 als GANZES
   klickbar ist. Die ZELLE wird deshalb vom Zeilenlink ausgenommen, nicht
   nur das Bedienelement: Sonst träfe ein Klick auf den Leerraum daneben
   wieder den Link und öffnete den Vorgang, während man zuweisen wollte.
   `position: relative` + `z-index` heben sie über das ::after des
   Stretched Link. */
td.zustaendig-zelle { position: relative; z-index: 1; }

/* Konflikthinweis IN DER ZELLE (09.08.2026) — als Blase, nicht als
   Block. Ein Block mit Name, Wert, Uhrzeit und Knopf wäre drei Zeilen
   hoch; bei 24 Zeilen springt dann die halbe Liste, und zwar genau die,
   in der man gerade arbeitet. Die Blase liegt darüber, die Zeilenhöhe
   bleibt.

   `position: relative` steht oben schon (für den Stretched Link) — die
   Voraussetzung war da, es braucht keine neue Regel dafür.

   ⚠ DER Z-INDEX DER ZELLE (1) REICHT NICHT gegen die NACHFOLGENDEN
   Zeilen: Bei gleichem Wert gewinnt das spätere Geschwister. `:has()`
   hebt die Zelle heraus, solange die Blase steht — dieselbe Technik wie
   beim Spalten-Quickfilter der Übersicht (`.board-gruppen .spalte:has(
   .spalten-filter[open])`). */
td.zustaendig-zelle:has(.konflikt-blase) { z-index: 50; }

.konflikt-blase {
  position: absolute;
  top: calc(100% + var(--a1));
  right: 0;
  z-index: 60;
  width: max-content;
  /* Genug für zwei Namen und eine Uhrzeit, aber nie breiter als der
     halbe Bildschirm — sonst deckt die Blase die Zeile zu, um die es
     geht. */
  max-width: min(38rem, 50vw);
  padding: var(--a3);
  border-radius: var(--radius);
  /* NICHT --fehler: Ein gleichzeitiger Schreibvorgang ist kein
     Regelverstoß, sondern ein Hinweis. Rot hiesse „du hast etwas falsch
     gemacht" — hier hat nur jemand anderes schneller geklickt.
     Dieselbe Wahl wie bei `.konflikt-hinweis` an den Positionen. */
  background: var(--warnung-flaeche);
  color: var(--text-1);
  font-size: var(--groesse-s);
  box-shadow: var(--schatten-hebt);
  text-align: left;
  white-space: normal;
}
.konflikt-blase-knoepfe {
  display: flex;
  gap: var(--a2);
  margin-top: var(--a3);
}
/* ⚠ SICHTBAR IM GRUNDZUSTAND, nicht erst bei Hover (Entscheid Eric,
   04.08.2026). Die erste Fassung war dezent — zu dezent: Auf dem
   Screenshot stand „Admin" viermal untereinander und war von der
   Statusspalte daneben nicht zu unterscheiden.

   ZWEI GEMESSENE GRÜNDE, die schwerer wiegen als die Ruhe der Liste:
     * Die Arbeitsumgebung ist Full HD über RDP, ~92 PPI, sehr heller
       Raum. Ein 1-px-Rand bei 1,05:1 war dort in der Design-Analyse
       NICHT sichtbar.
     * Niemand hovert über eine Spalte, von der er nicht weiß, dass sie
       bedienbar ist. Ein Erkennungszeichen, das man erst beim Berühren
       sieht, ist keins.

   Der sichtbare Rahmen bringt den AUFKLAPP-PFEIL des <select> mit
   (Grundregel `select { background-image: … }`) — und der ist das
   eigentliche Erkennungszeichen.

   HAUSFARBEN, nichts Neues: `--linie` ist derselbe Rahmen wie an
   Kästen und Tabellen, `--text` dieselbe Schriftfarbe wie in jedem
   anderen Eingabefeld. */
.zustaendig-waehler {
  font: inherit;
  color: var(--text);
  background: transparent;
  border: 1px solid var(--linie);
  /* `--radius` ist der Hausradius; `--radius-s` gibt es nicht — die
     erste Fassung hatte ihn erfunden, und CSS meldet so etwas nicht. */
  border-radius: var(--radius);
  max-width: 14ch;
}
/* ⚠ DAS POLSTER STEHT AM TYPSELEKTOR, UND DAS IST DER GANZE PUNKT.
   (07.08.2026)

   Hier stand `padding: 2px 4px` — in der einzigen Verwendung dieser
   Klasse WIRKUNGSLOS: Das Element sitzt ausnahmslos in
   `td.zustaendig-zelle`, und `td select` (Spezifitaet 0,1,1) schlaegt
   `.zustaendig-waehler` (0,1,0). Gerendert wurde also nie 4px, sondern
   die 30px aus der Tabellenregel.

   Aufgefallen ist das erst beim Nachmessen der Uebertragbarkeit: 4px
   rechts gegen einen Pfeil, der 26px hereinreicht, waeren 22px
   Ueberlappung auf dem Namen gewesen. Dass nichts passierte, verdankte
   sich einer Regel, die niemand zu diesem Zweck geschrieben hat — und
   die naechste Verwendung ausserhalb einer Tabellenzelle haette den
   Pfeil auf den Text gelegt, lautlos.

   `select.zustaendig-waehler` hat dieselbe Spezifitaet wie `td select`
   und steht spaeter im Stylesheet, gewinnt also. Die Werte sind die,
   die `td select` heute liefert — die Anzeige aendert sich NICHT. Die
   kompakten 2px/4px der alten Zeile zu uebernehmen waere eine
   Aenderung an jeder Listenzeile gewesen, die niemand bestellt hat.

   Die 30px rechts sind gerechnet: Pfeil 10px vom Rand + 16px breit +
   4px Luft zum Text (Waechter test_w3_kein_select_polster_ist_zu_eng). */
select.zustaendig-waehler { padding: 4px 34px 4px var(--a3); }
.zustaendig-waehler:hover,
.zustaendig-waehler:focus { border-color: var(--text-3); }
.zustaendig-herausgewiesen { opacity: 0.62; }
.zustaendig-herausgewiesen .meta { display: block; font-size: var(--groesse-xs); }

/* ================= Die ganze Zeile öffnet den Vorgang (04.08.2026) =====
   ⚠ EIN ECHTES <a href>, KEIN JavaScript-Klickhandler. Der Unterschied
   ist nicht kosmetisch: Mittelklick und „In neuem Tab öffnen" bleiben
   erhalten. Bei einer Liste, aus der man mehrere Aufträge nacheinander
   ansieht, ist das ein spürbarer Verlust — und ein Handler nähme ihn
   weg, ohne dass es jemand meldet. Wächter: tests/test_zeilenlink.py.

   Der Trick ist ein „Stretched Link": Das ::after des vorhandenen Links
   in der ersten Zelle wird über die ganze Zeile gespannt. Kein
   Build-Schritt, kein Framework — eine Regel. */
tbody tr { position: relative; }
a.zeilenlink::after {
  content: "";
  position: absolute;
  inset: 0;
}
/* ⚠ ALLES, WAS IN DER ZEILE BEDIENBAR BLEIBEN SOLL, BRAUCHT DIESE
   KLASSE — sonst liegt es unter dem ::after und der Klick öffnet den
   Vorgang, statt zu tun, was daraufsteht. Still, ohne Fehlermeldung.
   Deshalb prüft ein Wächter JEDES interaktive Element der
   Zeilen-Templates gegen eine namentliche Ausnahmeliste. */
tbody tr .zeilen-ausnahme { position: relative; z-index: 1; }
/* Die Zeile als Ganzes soll sich anfassbar anfühlen. */
tbody tr:has(a.zeilenlink):hover { background: var(--flaeche-2); }

/* ══ Dokumentenfeld der Begleitscheinzeile (10.08.2026) ══
   In der Zeile steht NUR der Dateiname als Link — keine Knöpfe, keine
   Symbole (Vorgabe Eric). Das Lösen läuft über das Häkchen.
   Alle hier benutzten Variablen sind gegen die Deklarationen geprüft
   (--a1/--a2/--groesse-xs/--linie/--akzent/--text-2/--radius) — ein
   erfundener Name fiele still auf den Erbwert zurück. */
/* ══ FESTE BREITE, damit die Spalte ruhig steht (Eric, 11.08.2026) ══
   Vorher `flex: 0 1 auto` mit `max-width` — jedes Feld war so breit wie
   sein Inhalt, und die rechte Kante wanderte von Zeile zu Zeile.

   DIE ZAHL IST GEMESSEN, NICHT GESCHAETZT:
     * Laengstes Feldwort: „Auftragsbestaetigung" = 19 Zeichen.
     * Laengster Dateiname im Devbox-Bestand: 12 Zeichen
       („A3016864.pdf"); im Beispielverzeichnis 26
       („A3017129_arbeitsschein.pdf").
   `ch` ist die Breite der Ziffer „0" — bei proportionaler Schrift sind
   Kleinbuchstaben schmaler, 20ch traegt die 19 Zeichen also mit Rand.
   Laengere Dateinamen werden mit Auslassungspunkten gekuerzt (siehe
   `.bs-dokument-name`); der volle Name steht im `title`.

   ⚠ `flex: 0 0 auto` UND `width`: Ohne die Null in der Mitte schrumpft
   das Feld bei enger Zeile wieder, und die feste Breite waere nur eine
   Empfehlung. */
.bs-dokument {
  /* ⚠ KEINE FESTE BREITE MEHR (Entscheid Eric, 12.08.2026). Hier stand
     `width: 20ch` — 145 px, aus der Zeit der gestrichelten Kachel. Der
     Dateiname bekam davon nur 52 px, weil „+n", „+" und das X den Rest
     nahmen: Von „O3017190 (1).pdf" (102 px) war die Hälfte zu sehen.
     Jetzt nimmt das Feld, was die Zeile übrig hat. */
  /* ⚠ `0 1 auto`, NICHT `1 1 auto`. Mit `1` wuchs das Feld auf Kosten der
     BESCHRIFTUNG, und „Ausgangsrechnung Kunde" brach in zwei Zeilen um
     (gesehen am Schirm). So nimmt es nur, was der Name braucht; die
     Beschriftung behält ihr `flex: 1` und schiebt das Feld ans Zeilenende.
     Die Obergrenze fängt den umgekehrten Fall ab: Ein sehr langer
     Dateiname darf die Beschriftung nicht erdrücken — dann greift die
     Ellipse. */
  flex: 0 1 auto;
  /* ⚠ 55 % IST GEMESSEN, NICHT GESCHÄTZT (12.08.2026). Bei 45 % war die
     Grenze BINDEND: Das Feld war auf 258 px gedeckelt, obwohl sein Inhalt
     293 px gebraucht hätte. Durchprobiert wurden 45/55/60/65 und ohne
     Grenze — ab 55 % erreicht das Feld seine natürliche Breite und wächst
     nicht weiter, und die BESCHRIFTUNG bricht in keiner der dreizehn
     Zeilen um. Die Grenze bleibt trotzdem stehen: Sie fängt den langen
     Dateinamen ab, der sonst die Beschriftung erdrückt. */
  max-width: 55%;
  align-self: center;
  min-width: 0;
  justify-content: flex-end;
  font-size: var(--groesse-xs);
  /* ══ EINE ZEILE, AUCH MIT MEHREREN BELEGEN (12.08.2026) ══
     Name, „+n" und das X stehen NEBENEINANDER. Vorher war der Name ein
     Block und schob beides unter sich — die Zeile war damit dreizeilig,
     bevor jemand etwas angeklickt hatte. `flex-wrap` gibt es nur, damit
     die AUFGEKLAPPTE Liste eine eigene Zeile bekommt. */
  /* ⚠ KEIN `flex-wrap`. In einem umbrechenden Kasten wird VOR dem
     Schrumpfen umgebrochen: Der volle Dateiname drängt „+n" und das X in
     die nächste Zeile, und die Zeile ist dreizeilig, bevor jemand etwas
     angeklickt hat. Ohne Umbruch schrumpft stattdessen der Name (mit
     Ellipse) — genau die Reihenfolge, die hier richtig ist. */
  display: flex;
  align-items: center;
  gap: var(--a1);
  position: relative;   /* Bezug fuer die aufgeklappte Liste */
}
.bs-dokument-name {
  /* Schrumpft als einziges Element — das X und die Zahl sind kurz und
     dürfen nicht ausweichen. `min-width: 0` ist die Voraussetzung dafür,
     dass die Ellipse in einem Flex-Kind überhaupt greift. */
  /* `flex-basis: 0` statt `auto`: Der Name beansprucht NICHT erst seine
     volle Breite und weicht dann — er nimmt von vornherein nur, was nach
     „+n" und X uebrig bleibt. */
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--akzent);
}
/* Leere Ablagefläche: gestrichelt, damit sie als Ziel erkennbar ist,
   ohne wie ein Knopf auszusehen. Das Datei-Feld liegt darin und ist
   unsichtbar — die Fläche selbst ist das Label, also auch per Tastatur
   erreichbar. */
/* ══ KEINE KACHEL, NUR DAS WORT (Entscheid Eric, 12.08.2026) ══
   `.bs-dokument-ablage` (gestrichelter Kasten, 145 px) ist gefallen. Was
   bleibt, ist das erwartete Belegwort als gedämpfter Text — es sagt,
   welcher Beleg hier hingehört, UND ist der Klickweg zum Dateifeld.
   Zugleich ist es das Erkennungszeichen: Nur die dreizehn Zeilen mit
   Pflicht zeigen es, die übrigen vierzehn nichts. */
.bs-dokument-wort {
  flex: 0 0 auto;
  cursor: pointer;
  color: var(--text-3);
}
.bs-dokument-wort:hover { color: var(--akzent); }
.bs-dokument-wort input[type="file"] { display: none; }
/* Ereignisdatum an der erledigten Zeile (Stufe 7, 23.09.2026): leise,
   neben dem Haken. Das `<label>` hier ist NICHT das der Zeile — die
   Zeilenregel (`.begleitschein .bs-zeile label`) gäbe ihm sonst flex: 1,
   44 px Höhe und die Titelschrift; deshalb die Rücksetzung. */
.begleitschein .bs-zeile label.bs-ereignis {
  flex: 0 0 auto;
  min-height: 0;
  padding: 0 var(--a2);
  gap: var(--a1);
  align-items: center;
  font-size: var(--groesse-xs);
  font-weight: 400;
  cursor: default;
}
.begleitschein .bs-zeile label.bs-ereignis:hover { background: none; }
.bs-ereignis input[type="date"] { font-size: var(--groesse-xs); padding: 2px var(--a1); }

/* „steht aus" hinter dem Belegwort (23.09.2026): abgehakt ohne Beleg,
   der Beleg wird nachgereicht. LEISE (Vorgabe Eric: „minimal invasiv,
   kein Störfaktor") — gleiche Grösse wie das Belegwort, nur die
   Warnfarbe; kein Kasten, kein Rand, keine eigene Zeile. `nowrap`, damit
   die zwei Wörter nicht einzeln umbrechen.
   ⚠ GRÖSSE UND STÄRKE AUSDRÜCKLICH: Das Belegwort ist ein `<label>` und
   bekommt beides aus `.begleitschein .bs-zeile label` (16 px, 500), NICHT
   aus `.bs-dokument` (13 px). Ohne diese zwei Zeilen stand der Hinweis
   kleiner hinter dem Wort — gemessen in der Bedienprobe am 23.09.2026,
   13 px gegen 16 px. */
.bs-beleg-aussteht {
  flex: 0 0 auto;
  white-space: nowrap;
  font-size: var(--rolle-titel-groesse);
  font-weight: 500;
  color: var(--warnung);
}

/* ══ DIE GANZE ZEILE LEUCHTET AUF ══
   Vorher war es die Kachel. Jetzt der Zeilenhintergrund plus eine
   deutliche linke Kante — die Kante trägt die Aussage auch dann, wenn
   der Hintergrund auf einem blassen Schirm untergeht. */
.bs-zeile.ablage-aktiv {
  background: var(--akzent-flaeche);
  box-shadow: inset 3px 0 0 0 var(--akzent);
}
.bs-dokument-datei {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
/* Vorschlag: der gedämpfte Dateiname IST das Angebot — er sieht bewusst
   NICHT wie ein Knopf aus (keine Fläche, kein Rahmen), ist aber einer,
   damit ein Klick genügt und die Tastatur ihn erreicht. */
.bs-dokument-vorschlag {
  display: block;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: var(--a1) var(--a2);
  border: 0;
  background: none;
  color: var(--text-3);
  font-size: var(--groesse-xs);
  font-style: italic;
  text-align: left;
  cursor: pointer;
}
.bs-dokument-vorschlag:hover { color: var(--akzent); font-style: normal; }
/* „noch 1 weiterer" — die Zahl neben dem Vorschlag. Eigene Zeile unter
   dem Dateinamen, damit die Begleitscheinzeile nicht breiter wird. */
.bs-dokument-weitere {
  display: block;
  padding: 0 var(--a2);
  font-size: var(--groesse-xs);
  color: var(--text-3);
}
/* Vorbehalt am Vorschlag (13.08.2026): „aus Scan gelesen" oder
   „Konfidenz niedrig". Dieselbe Farbgebung wie im Dokumenteneingang
   (`.dok-vorschlag.mit-vorbehalt` / `.vorschlag-vorbehalt`) — derselbe
   Sachverhalt soll nicht an zwei Stellen verschieden aussehen. Eigene
   Klassennamen, weil die Zeile ein anderes Gerüst hat: Der Knopf ist
   hier `display:block` mit Ellipse, dort steht der Text in einem Kasten. */
.bs-dokument-vorschlag.mit-vorbehalt { background: var(--warnung-flaeche); }
.bs-vorschlag-vorbehalt {
  display: block;
  padding: 0 var(--a2);
  font-size: var(--groesse-xs);
  color: var(--warnung);
}

/* ══════ Begleitschein: mehrere Nachweise je Zeile (12.08.2026) ══════
   Entscheid Eric: Die Zeile bleibt EINZEILIG, auch mit mehreren Belegen.
   Sichtbar ist der erste; „+2" klappt die uebrigen auf. Als <details>,
   also ohne eine Zeile JavaScript und mit Tastatur bedienbar. */
/* ⚠ `display: contents` — das <details> selbst verschwindet aus dem
   Layout, `summary` und Liste werden zu Flex-Kindern von `.bs-dokument`.
   Nur so steht die Zahl NEBEN dem Namen und die aufgeklappte Liste
   DARUNTER. Ein `display: inline` liess beides in einer Zeile kleben. */
.bs-dokument-mehr { display: contents; }
.bs-dokument-mehr > summary {
  display: inline-block; cursor: pointer; list-style: none;
  font-size: .85em; font-weight: 600; color: var(--text-2);
  padding: 0 var(--a1); border-radius: var(--radius);
  background: var(--flaeche-2);
}
.bs-dokument-mehr > summary::-webkit-details-marker { display: none; }
.bs-dokument-mehr > summary:hover { color: var(--text-1); }
/* Die Liste steht UNTER der Zeile und schiebt sie nicht auseinander,
   solange sie zu ist — das ist der ganze Zweck des Aufklappers. */
.bs-dokument-liste {
  /* ⚠ AUS DEM FLUSS GENOMMEN. Die Liste liegt UEBER dem, was folgt,
     statt die Zeile auseinanderzuschieben — „die Zeile bleibt einzeilig,
     ein Klick zeigt, welche da sind" (Vorgabe Eric). Bliebe sie im
     Fluss, waere die Begleitschein-Zeile beim Aufklappen so hoch wie
     die Liste, und die Zeilen darunter sprängen weg. */
  list-style: none; margin: 0; padding: var(--a2);
  position: absolute; top: calc(100% + 2px); right: 0; z-index: 5;
  min-width: 24ch;
  background: var(--flaeche);
  border: 1px solid var(--linie);
  border-radius: var(--radius);
  box-shadow: var(--schatten-hover);
}
.bs-dokument-liste li {
  display: flex; align-items: center; gap: var(--a1);
  padding: 2px 0;
}
/* Das X loest NUR die Zuordnung. Gedaempft, damit es die Zeile nicht
   dominiert — es ist eine Korrektur, keine Hauptgeste. */
/* ══ EIN X JE DOKUMENT, KLEIN UND OBEN RECHTS AM NAMEN
   (Nachtrag Eric, 12.08.2026) ══
   Vorher stand EIN X am Zeilenende; bei zwei Nachweisen war nicht zu
   sehen, welchen es löst — bei einer Löschgeste die falsche Art von
   Unklarheit.

   GRÖSSE: 0,72 em der Zeilenschrift. Bei `--groesse-xs` sind das rund
   9 px gegen 12,8 px des Dateinamens — deutlich unauffälliger und über
   die Klickfläche (Innenabstand) trotzdem treffbar. */
.bs-beleg {
  display: inline-flex;
  align-items: flex-start;
  min-width: 0;
  max-width: 100%;
}
.bs-beleg > .bs-dokument-name { min-width: 0; }
.bs-dokument-weg {
  flex: 0 0 auto;
  align-self: flex-start;
  border: 0; background: none; cursor: pointer;
  color: var(--text-3);
  font-size: 0.72em;
  /* ⚠ `min-height: 0` MUSS HIER STEHEN. Die Grundregel fuer Knoepfe setzt
     44 px Mindesthoehe (Fingerziel) — der Kasten des X war damit 40 px
     hoch, und der 9 px kleine Strich sass in seiner MITTE, also unter der
     Mitte des Dateinamens statt oben rechts daran. Gemessen, nicht
     geraten. Dasselbe Muster wie `.filter-chip .chip-x`, das aus
     demselben Grund ohne Mindesthoehe auskommt. */
  min-height: 0;
  height: auto;
  line-height: 1;
  padding: 2px 4px;
  margin-left: 1px;
}
.bs-dokument-weg:hover { color: var(--fehler); }

/* Name oben, Datum darunter — siehe `.bs-erledigt-meta`. */
.bs-meta-wer  { font-weight: 600; }
.bs-meta-wann { font-size: .85em; color: var(--text-3); }


/* ══════════ Materialbeschaffung (13.08.2026, S4) ══════════
   Zweispaltig: LINKS der PDF-Betrachter ueber die volle Hoehe, RECHTS
   das Panel mit Feldern und Kommentaren.

   ⚠ NICHT `.ticket-raster` WIEDERVERWENDET, und das ist gemessen: Jenes
   ist 2 x 1fr und spannt das Panel ueber zwei Zeilen — gebaut fuer
   Begleitschein oben, Verlauf unten. Hier gibt es links genau EIN
   Element, das die volle Hoehe fuellen soll. Mit `.ticket-raster` waere
   der Betrachter so hoch wie sein Inhalt (ein iframe ohne Hoehe ist
   150 px hoch) und der Rest der Spalte leer.

   Die Hoehe kommt deshalb aus dem Sichtfenster und nicht aus dem
   Inhalt. `--mb-kopf` ist der Platz, den Kopfleiste und Seitenpolster
   darueber brauchen. */
/* ⚠ EIGENE SEITENBREITE STATT `seite-breit` (Freigabe Eric,
   14.08.2026). Begründung und Messwerte stehen an der Vorlage. Kein
   eigener Deckel: `main` begrenzt ohnehin auf 100rem, und ein zweiter
   Wert hier wäre eine Zahl, die niemand mehr begründen kann. */
.mb-seite { margin: 0 auto; }
.mb-raster {
  --mb-kopf: 9rem;
  display: grid;
  /* `minmax(0, …)` links: Ohne die 0 als Minimum wächst eine Grid-Spalte
     mit ihrem Inhalt, und der `<iframe>` hat keine natürliche Breite, an
     der er sich bremsen würde. */
  grid-template-columns: minmax(0, 3fr) minmax(22rem, 2fr);
  gap: var(--a4);
  align-items: start;
  margin-bottom: var(--a5);
}
/* Unter 60rem untereinander: Ein 22rem-Panel neben einem Betrachter
   ergibt auf einem schmalen Schirm zwei unlesbare Spalten. */
@media (max-width: 60rem) {
  .mb-raster { grid-template-columns: minmax(0, 1fr); }
  .mb-betrachter { height: 70vh; }
}
/* ⚠ 1:1 ERST AB 90rem, UND DIE SCHWELLE IST GEMESSEN (14.08.2026).
   Die rechte Spalte trägt seit heute das mehrzeilige Materialfeld und
   war mit 2fr zu schmal. Ein pauschales 1:1 wäre aber ein Rückschritt
   auf kleineren Schirmen: Dort band der alte 76rem-Deckel gar nicht,
   1:1 gewinnt also nichts und nimmt dem Betrachter nur weg.

   ⚠ UND DIE BEIDEN STELLSCHRAUBEN WIRKEN VERSCHIEDEN, was ich beim
   ersten Bericht zu grosszügig zusammengefasst hatte: Der DECKEL zu
   fallen hilft BEIDEN Spalten. Das Verhältnis auf 1:1 zu stellen nimmt
   dem Betrachter und gibt es dem Panel — immer. Gemessen bei 1920px:

       Deckel   Raster    Betrachter   Panel
       76rem    3fr:2fr        720      480     (vorher)
       keiner   3fr:2fr        902      601
       keiner   1:1            744      744     (jetzt)

   Das 1:1 ist also eine bewusste Umverteilung zugunsten des
   Materialfelds (Freigabe Eric), kein Gewinn aus dem Nichts.

   Die SCHWELLE ist gemessen, nicht gegriffen — Betrachter-Breite:

       Fenster   3fr:2fr   1:1
       1366px      616     513    <- 103px Verlust, kein Ausgleich
       1440px      668     556    <- immer noch Verlust
       1920px      902     744    <- hier trägt die Umverteilung

   Bei 100rem greift sie erst, wenn die Seite breit genug ist, dass
   beide Spalten über 600px behalten. */
@media (min-width: 100rem) {
  .mb-raster { grid-template-columns: minmax(0, 1fr) minmax(22rem, 1fr); }
}
.mb-betrachter {
  display: flex; flex-direction: column;
  height: calc(100vh - var(--mb-kopf));
  min-height: 30rem;
  background: var(--flaeche);
  border: 1px solid var(--linie);
  border-radius: var(--radius);
  overflow: hidden;
}
.mb-betrachter-kopf {
  display: flex; align-items: center; gap: var(--a3);
  padding: var(--a2) var(--a3);
  border-bottom: 1px solid var(--linie);
  flex: 0 0 auto;
}
/* Der Dateiname gibt nach, die Blaetterleiste nicht — sie ist die
   Bedienung, er ist die Auskunft. */
.mb-dateiname {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--groesse-xs); color: var(--text-2);
}
.mb-blaettern {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: var(--a2);
}
.mb-seitenstand { font-size: var(--groesse-xs); color: var(--text-2); }
/* `flex: 1 1 auto` UND `min-height: 0`: Ohne das zweite waechst der
   iframe ueber den Kasten hinaus, statt zu schrumpfen — Flex-Kinder
   haben `min-height: auto`. */
.mb-rahmen {
  flex: 1 1 auto; min-height: 0;
  width: 100%; border: 0;
}
.mb-leer { margin: auto; }
.mb-panel { align-self: start; }
.mb-titel {
  font-size: var(--groesse-l); margin: var(--a2) 0 0;
  overflow-wrap: anywhere;
}
.mb-upload { display: flex; gap: var(--a2); flex-wrap: wrap;
             margin-bottom: var(--a3); }
/* Das Materialfeld: Schreibmaschinenschrift, damit kopierte
   Positionsangaben untereinander stehen wie im Beleg. Ziehbar in der
   Höhe, nicht in der Breite — die Breite gehört dem Raster. */
.mb-material {
  width: 100%;
  /* ⚠ 18rem, GEMESSEN UND NICHT GEGRIFFEN (14.08.2026). `rows="10"`
     allein genügt nicht: Mit `pre-wrap` bricht eine kopierte Zeile auf
     schmalen Schirmen um, und ein Block aus zwei Positionen (8 Zeilen im
     Beleg) belegt bei 330px Feldbreite rund 13 Zeilen. Mit 14rem
     scrollte das Feld bei 1280px Fensterbreite senkrecht — genau das,
     was die Grösse verhindern soll. 18rem fassen es bis hinunter zur
     schmalsten zweispaltigen Lage. */
  min-height: 18rem;
  resize: vertical;
  /* ⚠ KEINE ERFUNDENE VARIABLE. Ein `var(--schrift-mono, …)` stand hier
     im ersten Entwurf — die Variable gibt es im Haus NICHT, und CSS
     meldet das nicht: Der Wert fiele still auf den Rückfall zurück und
     sähe richtig aus. Das Haus hat genau zwei Schriften (`--schrift`
     und Orbitron für die Anzeige) und keine feste Breite; sie steht
     deshalb hier ausgeschrieben und nur an dieser einen Stelle. */
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               monospace;
  font-size: var(--groesse-s);
  line-height: 1.45;
  /* ⚠ `pre-wrap`, NICHT `pre` — gemessen am 14.08.2026. Mit `pre` lief
     das Feld bei 1280px Fensterbreite waagerecht über (die Zeile
     „MATERIAL: X6CrNiMoTi17-12-2 (1.4571)" passt dort nicht in 330px),
     und der Nutzer hätte innerhalb des Feldes scrollen müssen. Genau
     das sollte die Grösse verhindern. Umgebrochen bleibt alles
     sichtbar; die Einrückung kopierter Zeilen trägt weiterhin, weil
     führende Leerzeichen erhalten bleiben. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
/* Die Listenzelle: eine Zeile, der Rest steht im `title`. */
.mb-material-zelle {
  max-width: 22rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--text-2);
}

/* Die drei Status. Farbe UND Wort — die Farbe traegt nie allein. */
.mbs-offen       { background: var(--flaeche-2);      color: var(--text-2); }
.mbs-in_klaerung { background: var(--warnung-flaeche); color: var(--warnung); }
.mbs-erledigt    { background: var(--ok-flaeche);      color: var(--ok); }


/* ══ SPIEGEL-INSTANZ (20.09.2026) ══ Das Band steht über JEDER Seite der
   dritten Instanz. Bewusst laut: Verwechslung mit Prod ist der Schaden,
   gegen den es steht. Nur deklarierte Hausvariablen. */
.spiegel-band {
  position: sticky; top: 0; z-index: 1000;
  padding: var(--a1) var(--a5);
  background: var(--warnung); color: var(--hintergrund);
  font-size: var(--groesse-s); text-align: center;
  border-bottom: 2px solid var(--text);
}
.spiegel-band.spiegel-veraltet { background: var(--fehler); }

/* ══ Hilfe / Anwenderhandbuch (21.09.2026) ══
   Links die Kapitel, rechts der Text. Nur deklarierte Variablen — CSS
   meldet nichts, wenn ein Name nicht existiert. */
.hilfe { display: grid; grid-template-columns: 220px minmax(0, 1fr);
         gap: var(--a5); align-items: start; }
.hilfe-kapitel { display: flex; flex-direction: column; gap: var(--a1);
                 position: sticky; top: var(--a5); }
.hilfe-kapitel a { padding: var(--a2) var(--a3); border-radius: var(--radius);
                   color: var(--text-2); text-decoration: none; }
.hilfe-kapitel a:hover { background: var(--flaeche-2); color: var(--text); }
.hilfe-kapitel a.hilfe-aktiv { background: var(--akzent-flaeche);
                               color: var(--akzent); }
.hilfe-text { background: var(--flaeche); border: 1px solid var(--linie);
              border-radius: var(--radius-gross); padding: var(--a5) var(--a6);
              max-width: 860px; line-height: 1.6; }
.hilfe-text h1 { font-size: var(--groesse-xl); margin-top: 0; }
.hilfe-text h2 { font-size: var(--groesse-l); margin-top: var(--a6); }
.hilfe-text table { border-collapse: collapse; width: 100%; margin: var(--a3) 0; }
.hilfe-text th, .hilfe-text td { text-align: left; vertical-align: top;
                                 padding: var(--a2) var(--a3);
                                 border-bottom: 1px solid var(--linie); }
.hilfe-text code { background: var(--flaeche-2); padding: 0 var(--a1);
                   border-radius: var(--a1); }
@media (max-width: 900px) {
  .hilfe { grid-template-columns: 1fr; }
  .hilfe-kapitel { position: static; flex-direction: row; flex-wrap: wrap; }
}

/* Das Fragezeichen im Seitenkopf — führt auf das Kapitel der Hilfe. */
.hilfe-fragezeichen { display: inline-flex; align-items: center;
  justify-content: center; width: 1.5em; height: 1.5em;
  margin-left: var(--a2); border: 1px solid var(--linie);
  border-radius: var(--radius-voll); font-size: var(--groesse-s);
  font-weight: 600; color: var(--text-2); text-decoration: none;
  vertical-align: middle; }
.hilfe-fragezeichen:hover { color: var(--akzent); border-color: var(--akzent); }

/* Zitat aus einem Beleg oder Freitext neben einem gelesenen Wert
   (Anfragepositionen, Schmelze): Die Textstelle ist der Beleg für den
   Vorschlag und soll als solche erkennbar sein. */
.mb-zitat { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
            font-size: var(--groesse-xs); color: var(--text-2);
            background: var(--flaeche-2); padding: 1px var(--a1);
            border-radius: var(--a1); }
/* Warnung über einer Vorschlagsliste („aus Scan gelesen, bitte prüfen"). */
.warnhinweis { background: var(--warnung-flaeche); color: var(--warnung);
               border: 1px solid var(--warnung); border-radius: var(--radius);
               padding: var(--a2) var(--a3); margin: var(--a3) 0; }
.schmelze-lesen { display: flex; align-items: center; gap: var(--a3);
                  flex-wrap: wrap; margin: var(--a3) 0; }
.schmelze-tabelle select { max-width: 340px; }

/* ══ Loki — das Fenster unten rechts (22.09.2026) ══ */
.loki-knopf { position: fixed; right: var(--a5); bottom: var(--a5); z-index: 60;
  padding: var(--a2) var(--a4); border-radius: var(--radius-voll);
  border: 1px solid var(--linie); background: var(--flaeche);
  color: var(--text); font-weight: 600; cursor: pointer;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.12); }
.loki-knopf:hover { border-color: var(--akzent); color: var(--akzent); }
.loki-fenster { position: fixed; right: var(--a5); bottom: calc(var(--a5) + 48px);
  z-index: 60; width: min(420px, calc(100vw - 2 * var(--a5)));
  max-height: min(560px, calc(100vh - 120px)); display: flex;
  flex-direction: column; background: var(--flaeche);
  border: 1px solid var(--linie); border-radius: var(--radius-gross);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18); }
.loki-fenster[hidden] { display: none; }
.loki-kopf { display: flex; align-items: baseline; gap: var(--a2);
  padding: var(--a3) var(--a4); border-bottom: 1px solid var(--linie); }
.loki-kopf .hinweis { flex: 1; font-size: var(--groesse-xs); }
.loki-zu { border: 0; background: none; font-size: var(--groesse-l);
  line-height: 1; cursor: pointer; color: var(--text-2); }
.loki-verlauf { list-style: none; margin: 0; padding: var(--a3) var(--a4);
  overflow-y: auto; flex: 1; display: flex; flex-direction: column;
  gap: var(--a2); }
.loki-verlauf li { white-space: pre-wrap; padding: var(--a2) var(--a3);
  border-radius: var(--radius); font-size: var(--groesse-s); }
.loki-frage-zeile { align-self: flex-end; background: var(--akzent-flaeche); }
.loki-antwort-zeile { align-self: flex-start; background: var(--flaeche-2); }
.loki-wartet { color: var(--text-3); }
.loki-formular { display: flex; gap: var(--a2); align-items: flex-end;
  padding: var(--a3) var(--a4); border-top: 1px solid var(--linie); }
.loki-formular textarea { flex: 1; resize: none; }

/* ══════════════════════════════════════════════════════════════════════
   ZUSCHNITTRECHNER (/rechner/zuschnitt, 22.09.2026)

   ⚠ KEINE EIGENEN DESIGN-TOKENS, KEIN EIGENER DUNKELMODUS. Die Vorlage
   aus dem Paket brachte beides mit (`--brand`, `--ink`, `--steel`, ein
   eigenes `prefers-color-scheme`). Sie sind ERSETZT durch ODINs Palette:
   `--akzent` statt `--brand`, `--text`/`--text-2`/`--text-3` statt
   `--ink`/`--muted`/`--steel`, `--linie` statt `--line`,
   `--flaeche`/`--flaeche-2` statt `--surface`. Zwei Paletten in einer
   Datei wären zwei Wahrheiten — und die zweite fällt erst auf, wenn
   jemand die erste ändert.

   ⚠ AUCH DIE GRAFIK KOMMT OHNE NEUE FARBE AUS. Der „Stahl" der
   Vorlage (vier Grautöne) ist auf `--text-3` (Körper), `--text-2`
   (Kontur) und `--flaeche-2` (Glanz) abgebildet. Wer hier eine Farbe
   ergänzt, ergänzt sie in `:root` oben — nicht als Literal.

   ⚠ JEDE KLASSE, DIE DIE SEITE BENUTZT, STEHT HIER. Eine Klasse ohne
   Regel fällt still auf den Erbwert zurück (CLAUDE.md, „CSS meldet
   nichts"); Wächter:
   `test_zuschnittrechner.test_jede_klasse_der_seite_hat_eine_css_regel`
   am gerenderten HTML und die Bedienprobe am gefüllten DOM.
   ══════════════════════════════════════════════════════════════════ */

.zr { max-width: 1400px; }
.zr .seite-kopf { margin-bottom: var(--a4); }

/* ---------- Reiter ---------- */
/* M1 (28.09.2026): Seitenreiter als echte Verweise (Kalkulation). Optik wie `.zr-reiter`. */
.seiten-reiter { display: flex; gap: var(--a1); flex-wrap: wrap; align-items: center;
  border-bottom: 1px solid var(--linie); margin-bottom: var(--a4); }
.seiten-reiter a { font-weight: 600; font-size: var(--groesse-m); padding: var(--a3) var(--a4); color: var(--text-2);
  text-decoration: none; border-bottom: 3px solid transparent; margin-bottom: -1px; transition: color var(--dauer) var(--kurve); }
.seiten-reiter a:hover { color: var(--text); }
.seiten-reiter a[aria-current="page"] { color: var(--akzent); border-bottom-color: var(--akzent); }
.seiten-reiter a:focus-visible { outline: 2px solid var(--akzent); outline-offset: -2px; }
.zr-reiter {
  display: flex;
  gap: var(--a1);
  flex-wrap: wrap;
  align-items: center;
  border-bottom: 1px solid var(--linie);
  margin-bottom: var(--a5);
}
.zr-reiter button {
  appearance: none;
  border: 0;
  background: none;
  font: inherit;
  font-weight: 600;
  font-size: var(--groesse-m);
  padding: var(--a3) var(--a4);
  color: var(--text-2);
  cursor: pointer;
  border-bottom: 3px solid transparent;
  margin-bottom: -1px;
  transition: color var(--dauer) var(--kurve);
}
.zr-reiter button:hover { color: var(--text); }
.zr-reiter button[aria-selected="true"] {
  color: var(--akzent);
  border-bottom-color: var(--akzent);
}
.zr-reiter button:focus-visible {
  outline: 2px solid var(--akzent);
  outline-offset: -2px;
  border-radius: var(--radius);
}
.zr-schalter {
  display: flex;
  align-items: center;
  gap: var(--a2);
  font-size: var(--groesse-xs);
  color: var(--text-2);
  cursor: pointer;
}
.zr-schalter input { accent-color: var(--akzent); }
/* Der Animations-Schalter sitzt am rechten Rand der Reiterzeile. */
.zr-schalter-rechts { margin-left: auto; }

/* ---------- Grundriss: Eingaben links, Ergebnis rechts ---------- */
.zr-layout {
  display: grid;
  grid-template-columns: 380px 1fr;
  gap: var(--a5);
  align-items: start;
}
@media (max-width: 1000px) { .zr-layout { grid-template-columns: 1fr; } }
.zr-stapel { display: grid; gap: var(--a5); min-width: 0; }

/* ---------- Kästen ---------- */
.zr-kasten {
  background: var(--flaeche);
  border: 1px solid var(--linie);
  border-radius: var(--radius);
  box-shadow: var(--schatten-ruhe);
  min-width: 0;
}
.zr-kasten-kopf {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--a3);
  padding: var(--a3) var(--a4);
  border-bottom: 1px solid var(--linie);
}
.zr-kasten-kopf h2 { font-size: var(--groesse-m); font-weight: 600; margin: 0; }
.zr-kasten-kopf small {
  color: var(--text-2);
  font-size: var(--groesse-xs);
  text-align: right;
}
.zr-kasten-rumpf { padding: var(--a4); }

/* ---------- Felder ---------- */
.zr-gruppe { border: 0; padding: 0; margin: 0 0 var(--a4); }
.zr-gruppe legend {
  font-size: var(--groesse-xs);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-2);
  margin-bottom: var(--a2);
  padding: 0;
}
.zr-raster2, .zr-raster3 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--a2) var(--a3);
}
.zr-feld label {
  display: block;
  font-size: var(--rolle-label-groesse);
  color: var(--rolle-label-farbe);
  margin-bottom: var(--a1);
}
.zr-feld-breit { grid-column: 1 / -1; }
/* Trefferzahl der Werkstoffsuche, rechts in der Beschriftung. */
.zr-feld-zahl { float: right; color: var(--text-2); font-size: var(--groesse-xs); }
.zr-eingabe {
  display: flex;
  align-items: center;
  border: 1px solid var(--linie);
  border-radius: var(--radius);
  background: var(--flaeche-2);
  overflow: hidden;
}
.zr-eingabe:focus-within {
  border-color: var(--akzent);
  box-shadow: 0 0 0 3px var(--akzent-flaeche);
}
.zr-eingabe input, .zr-eingabe select {
  width: 100%;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-variant-numeric: tabular-nums;
  padding: var(--a2) var(--a3);
  min-width: 0;
}
.zr-eingabe input:focus, .zr-eingabe select:focus { outline: none; }
.zr-einheit {
  font-size: var(--groesse-xs);
  color: var(--text-2);
  padding: 0 var(--a2);
  border-left: 1px solid var(--linie);
  align-self: stretch;
  display: flex;
  align-items: center;
  white-space: nowrap;
}
.zr-erweitert { border-top: 1px solid var(--linie); margin-top: var(--a1); padding-top: var(--a3); }
.zr-erweitert summary {
  cursor: pointer;
  font-size: var(--groesse-xs);
  color: var(--text-2);
}
.zr-erweitert .zr-raster2 { margin-top: var(--a3); }

/* ---------- Bühne (SVG) ---------- */
.zr-buehne { padding: var(--a3) var(--a4) var(--a1); }
.zr-buehne svg { width: 100%; height: auto; display: block; }
.zr-legende {
  display: flex;
  gap: var(--a4);
  flex-wrap: wrap;
  padding: var(--a1) var(--a4) var(--a3);
  font-size: var(--groesse-xs);
  color: var(--text-2);
}
.zr-punkt {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 2px;
  vertical-align: -2px;
  margin-right: var(--a1);
}
.zr-punkt-teil     { background: var(--akzent); }
.zr-punkt-material { background: var(--text-3); }
.zr-punkt-schnitt  { background: var(--akzent-hover); }
.zr-punkt-extra    { background: var(--text-2); }

/* ---------- Kacheln ---------- */
/* ⚠ DIE TRENNLINIEN SITZEN AN DEN KACHELN, NICHT AM RASTER. Die
   Vorlage legte `background: var(--linie)` auf den Container und liess
   1px Fugen durchscheinen — elegant, solange die letzte Reihe VOLL ist.
   Ist sie es nicht (sechs Kacheln, fünf je Reihe), steht neben der
   letzten eine graue Fläche über die halbe Breite und sieht aus wie ein
   Fehler. Gesehen am 22.09.2026 im Browser, nicht von einem Test:
   „CSS meldet nichts“ — die Regel war gültig, das Bild trotzdem falsch.
   `inset`-Schatten zeichnen die Linien INNERHALB der Kachel; wo keine
   Kachel ist, ist auch keine Linie. */
.zr-kacheln {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  border-top: 1px solid var(--linie);
}
.zr-kachel {
  background: var(--flaeche);
  padding: var(--a3) var(--a4);
  min-height: 86px;
  box-shadow: inset 1px 1px 0 var(--linie);
}
.zr-kachel-label {
  font-size: var(--groesse-xs);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-2);
}
.zr-kachel-wert {
  font-size: var(--groesse-xl);
  font-weight: 700;
  line-height: 1.05;
  margin-top: var(--a1);
  font-variant-numeric: tabular-nums;
}
.zr-kachel-zusatz { font-size: var(--groesse-xs); color: var(--text-2); margin-top: var(--a1); }
.zr-kachel-akzent   .zr-kachel-wert { color: var(--akzent); }
.zr-kachel-gut      .zr-kachel-wert { color: var(--ok); }
.zr-kachel-warnung  .zr-kachel-wert { color: var(--warnung); }
.zr-kachel-schlecht .zr-kachel-wert { color: var(--fehler); }

/* ---------- Vermerke unter dem Ergebnis ---------- */
.zr-vermerk {
  margin: var(--a3) 0 0;
  padding: var(--a3);
  border-left: 3px solid var(--warnung);
  background: var(--warnung-flaeche);
  font-size: var(--groesse-s);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.zr-vermerk:first-child { margin-top: 0; }
.zr-vermerk-gut      { border-left-color: var(--ok); background: var(--ok-flaeche); }
.zr-vermerk-schlecht { border-left-color: var(--fehler); background: var(--fehler-flaeche); }
.zr-vermerk-info     { border-left-color: var(--text-3); background: var(--flaeche-2); }

/* ---------- Tabellen (Varianten, Profile) ---------- */
.zr-tabelle-rahmen { overflow-x: auto; }
.zr-tabelle {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--groesse-s);
  font-variant-numeric: tabular-nums;
}
.zr-tabelle th {
  font-size: var(--groesse-xs);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-2);
  text-align: right;
  padding: var(--a2) var(--a3);
  border-bottom: 1px solid var(--linie);
  font-weight: 500;
}
.zr-tabelle td { text-align: right; padding: var(--a2) var(--a3); border-bottom: 1px solid var(--linie); }
.zr-tabelle th:first-child, .zr-tabelle td:first-child { text-align: left; }
.zr-tabelle tbody tr { cursor: pointer; }
.zr-tabelle tbody tr:hover td { background: var(--hover-flaeche); }
/* AUSWAHL, nicht Hover: die Akzentfläche ist dem gewählten Zustand
   vorbehalten — dieselbe Regel wie im übrigen Haus. */
.zr-tabelle tr.zr-gewaehlt td,
.zr-tabelle tr.zr-gewaehlt:hover td { background: var(--akzent-flaeche); }
.zr-marke {
  display: inline-block;
  font-size: var(--groesse-xs);
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: 0 var(--a2);
  border-radius: var(--radius-voll);
  background: var(--ok-flaeche);
  color: var(--ok);
  margin-left: var(--a2);
}
.zr-leer { color: var(--text-2); }

/* ---------- Positionstext ---------- */
.zr-text { padding: var(--a4); }
.zr-text textarea {
  width: 100%;
  min-height: 130px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--groesse-xs);
  line-height: 1.5;
  color: var(--text);
  background: var(--flaeche-2);
  border: 1px solid var(--linie);
  border-radius: var(--radius);
  padding: var(--a3);
  resize: vertical;
}
.zr-zeile {
  display: flex;
  gap: var(--a3);
  margin-top: var(--a3);
  flex-wrap: wrap;
  align-items: center;
}
.zr-kopiert { font-size: var(--groesse-xs); color: var(--ok); }
.zr-fuss { margin-top: var(--a5); max-width: 80ch; }

/* ---------- Die Grafik ---------- */
.zr-koerper { fill: var(--text-3); stroke: var(--text-2); stroke-width: 1.2; }
.zr-hell { fill: var(--flaeche-2); opacity: .5; }
.zr-hell-schwach { opacity: .3; }
/* Der Hohlraum im Rohr: die Flächenfarbe, damit er als Loch liest. */
.zr-hohlraum { fill: var(--flaeche); stroke: var(--text-2); stroke-width: 1.2; }
.zr-teil { fill: var(--akzent); fill-opacity: .85; stroke: var(--akzent-hover); stroke-width: 1; }
/* Mögliche weitere Teile: da, aber nicht bestellt. */
.zr-teil-extra { fill: var(--text-2); fill-opacity: .5; stroke: var(--text-2); }
.zr-schnitt { stroke: var(--akzent); stroke-width: 1.5; fill: none; }
.zr-mass { stroke: var(--text-2); stroke-width: 1; fill: none; }
.zr-mass-gestrichelt { stroke-dasharray: 4 3; }
.zr-masstext { font-size: 12px; font-weight: 600; fill: var(--text); }
.zr-masstext-leise { fill: var(--text-2); }
.zr-titel {
  font-size: 13px;
  font-weight: 600;
  fill: var(--text-2);
  letter-spacing: .06em;
  text-transform: uppercase;
}
.zr-schraffur { fill: url(#zr-hatch); }
.zr-schraffur-strich { stroke: var(--text-2); stroke-width: 1; stroke-opacity: .5; }
.zr-saege { fill: var(--akzent); opacity: .9; }
.zr-saege-blatt { fill: var(--flaeche); opacity: .5; }

/* ---------- Bewegung ----------
   Nur unter `.zr-anim` — der Schalter in der Reiterzeile nimmt die
   Klasse weg, und `prefers-reduced-motion` ebenfalls. */
.zr-anim .zr-pop {
  transform-box: fill-box;
  transform-origin: center;
  animation: zr-pop .5s var(--kurve) both;
  animation-delay: calc(var(--i, 0) * 22ms);
}
.zr-anim .zr-zeichnen {
  stroke-dasharray: 1400;
  stroke-dashoffset: 1400;
  animation: zr-zeichnen 1.1s ease-out forwards;
  animation-delay: var(--d, .35s);
}
.zr-anim .zr-lauf { animation: zr-lauf var(--t, 6s) linear infinite; }
.zr-anim .zr-blende { animation: zr-blende .6s ease both; animation-delay: var(--d, .2s); }
@keyframes zr-pop { from { opacity: 0; transform: scale(.55); } to { opacity: 1; transform: scale(1); } }
@keyframes zr-zeichnen { to { stroke-dashoffset: 0; } }
@keyframes zr-lauf { from { transform: translateX(0); } to { transform: translateX(var(--len, 300px)); } }
@keyframes zr-blende { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .zr-anim .zr-pop, .zr-anim .zr-zeichnen, .zr-anim .zr-lauf, .zr-anim .zr-blende {
    animation: none;
    opacity: 1;
    stroke-dashoffset: 0;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   Vertrieb / CRM (24.09.2026) — Anfrage-Queue, Mein Tag, Kundenakte.
   Nur Variablen, die oben deklariert sind (Hausregel „CSS meldet
   nichts"; Wächter test_zustaendig_zelle prüft benutzte gegen
   deklarierte Namen).
   ══════════════════════════════════════════════════════════════════════ */
.vt-reiter {
  display: flex; flex-wrap: wrap; gap: var(--a3); align-items: center;
  margin-bottom: var(--a4);
}
.vt-gruppe { display: inline-flex; flex-wrap: wrap; gap: var(--a1); align-items: center; }
.vt-reiter a:not(.meta) {
  padding: 4px var(--a3); border-radius: var(--radius-voll);
  background: var(--flaeche-2); color: var(--text-2);
  font-size: var(--groesse-xs); text-decoration: none;
}
.vt-reiter a.aktiv { background: var(--akzent-flaeche); color: var(--akzent); font-weight: 650; }
.vt-reiter select { min-height: 32px; font-size: var(--groesse-xs); }
/* ═══ L1 (28.09.2026): die kompakte Filterleiste des Vertriebs ═══
   `partials/vt_filterleiste.html`. EINE Zeile ab 1200 px: Chips, Felder
   mit Beschriftung LINKS, rechts klein der Seitenverweis. Alles in einer
   Höhe (--vf-hoehe), damit Chips und Felder auf einer Linie stehen.
   Die Felder sind nur so breit wie ihr Inhalt (gedeckelt bei 180 px) —
   die Grundregel `input, select { width: 100% }` gilt hier NICHT,
   auch nicht unterhalb von 1200 px, wo die Leiste nur umbricht. */
.vt-filter {
  --vf-hoehe: 30px;
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--a2) var(--a3);
  margin-bottom: var(--a4);
  font-size: var(--groesse-xs);
}
.vf-gruppe { display: inline-flex; flex-wrap: wrap; gap: var(--a1); align-items: center; }
.vf-chip {
  display: inline-flex; align-items: center; height: var(--vf-hoehe);
  padding: 0 var(--a3); border-radius: var(--radius-voll);
  background: var(--flaeche-2); color: var(--text-2);
  font-size: var(--groesse-xs); text-decoration: none; white-space: nowrap;
}
.vf-chip:hover { background: var(--hover-flaeche); color: var(--text); text-decoration: none; }
.vf-chip.aktiv { background: var(--akzent-flaeche); color: var(--akzent); font-weight: 650; }
.vf-feld { display: inline-flex; align-items: center; gap: var(--a1); white-space: nowrap; }
.vf-label { color: var(--text-2); font-size: var(--groesse-xs); margin: 0; font-weight: 500; }
.vt-filter select,
.vt-filter input:where(:not([type="checkbox"]):not([type="radio"])) {
  width: auto; min-width: 0; max-width: 180px;
  height: var(--vf-hoehe); min-height: 0;
  margin: 0; padding: 0 var(--a2);
  font-size: var(--groesse-xs);
  background-color: var(--flaeche); box-shadow: var(--schatten-ruhe);
}
.vt-filter select { padding-right: 30px; background-position: right 8px center; background-size: 14px auto; }
.vt-filter input[type="search"] { max-width: 240px; }
.vt-filter input[type="date"] { max-width: 150px; }
.vf-bis { color: var(--text-3); }
/* Der Rückfall-Knopf: ohne JavaScript sichtbar, mit JavaScript per
   `hidden` weg (app.js). `display` des Hauses darf `hidden` nicht
   aushebeln — dieselbe Falle wie `.kommentar-bearbeiten[hidden]`. */
.vt-filter .vf-absenden { height: var(--vf-hoehe); min-height: 0; padding: 0 var(--a3); font-size: var(--groesse-xs); }
.vt-filter .vf-absenden[hidden] { display: none; }
.vf-zuruecksetzen { color: var(--text-2); white-space: nowrap; }
/* Platzhalter für den Out-of-Band-Tausch — leer kostet er keinen Abstand. */
.vf-platz { display: contents; }
.vf-rechts { margin-left: auto; color: var(--text-2); font-size: var(--groesse-xs); white-space: nowrap; }
/* „Weitere Filter": zugeklappt ein Chip; offen eine eigene Zeile unter
   der Leiste (nur dann kostet sie Höhe). Aktiv = mindestens einer
   gesetzt, dann in Akzentfarbe mit Zahl. */
details.vf-weitere { display: inline-flex; }
details.vf-weitere:not([open]) + .vf-weitere-felder { display: none; }
details.vf-weitere > summary {
  list-style: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: var(--a1); height: var(--vf-hoehe);
  padding: 0 var(--a3); border-radius: var(--radius-voll);
  background: var(--flaeche-2); color: var(--text-2); white-space: nowrap;
}
details.vf-weitere > summary::-webkit-details-marker { display: none; }
details.vf-weitere > summary::after { content: "▾"; font-size: 10px; }
details.vf-weitere[open] > summary::after { content: "▴"; }
details.vf-weitere > summary.aktiv { background: var(--akzent-flaeche); color: var(--akzent); font-weight: 650; }
.vf-anzahl {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--radius-voll);
  background: var(--akzent); color: var(--flaeche); font-size: 11px;
}
.vf-weitere-felder {
  order: 99; flex-basis: 100%;
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--a2) var(--a3);
  padding: var(--a2) var(--a3); border-radius: var(--radius); background: var(--flaeche-2);
}

/* ═══ L1 Punkt 5 und Nachbesserung: Die Tafel teilt die Breite ═══
   Aktive Spalten (mit Karten) teilen sich die Breite GLEICHMÄSSIG:
   `flex: 1 1 0` mit Mindestbreite 180 px — alle gleich breit, zusammen
   genau die Breite der Tafel. SCHMAL (44 px, senkrechter Titel und
   Zahl) sind leere Spalten und „Erledigt"; ein Klick klappt sie auf
   (app.js nimmt `schmal` weg). Erst wenn eine aktive Spalte schmaler als
   180 px würde, scrollt die Tafel waagrecht; dann zeigt ein Schatten am
   Rand, dass es weitergeht (`.vt-tafel-rahmen`, Klassen aus app.js).
   Flex statt Grid: Die Spalten sind verschieden breit (aktiv/schmal),
   und das Grid bräuchte dafür eine Spaltenliste im Stil-Attribut.
   NUR die Vertriebstafel: `.board`/`.spalte` teilt sie mit dem
   Auftragsboard und der Lagertafel, die hier nicht angefasst werden. */
.vt-tafel-rahmen { position: relative; }
.vt-tafel { display: flex; overflow-x: auto; }
.vt-tafel > .spalte { flex: 1 1 0; min-width: 180px; }
.vt-tafel > .spalte.schmal { flex: 0 0 44px; min-width: 44px; padding-left: 0; padding-right: 0; cursor: pointer; }
/* Hover im Hausmuster: die Akzentfläche gehört der Auswahl (test_board_karte). */
.vt-tafel > .spalte.schmal:hover { box-shadow: inset 0 0 0 1px var(--linie); }
.vt-tafel > .spalte.schmal:hover .spalte-titel { color: var(--akzent); }
.vt-tafel > .spalte.schmal > .karten { display: none; }
.vt-tafel > .spalte.schmal > header { padding: var(--a2) 0; justify-content: center; }
/* Der Kopf einer klappbaren Spalte ist ein Knopf — ohne die Knopf-Optik
   des Hauses (Fläche, Polster, Mindesthöhe, Druck-Verkleinerung). */
.vt-spalte-knopf {
  display: flex; align-items: center; gap: var(--a1); width: 100%;
  margin: 0; padding: 0; min-height: 0; border: 0; border-radius: 0;
  background: none; box-shadow: none; color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.vt-spalte-knopf:hover, .vt-spalte-knopf:active { background: none; transform: none; }
.vt-spalte-knopf:hover .spalte-titel { color: var(--akzent); }
.spalte.schmal .vt-spalte-knopf { flex-direction: column; align-items: center; gap: var(--a2); }
.spalte.schmal .spalte-titel { writing-mode: vertical-rl; flex: none; }
.spalte.schmal .spalte-zaehler { order: -1; margin-left: 0; }
.vt-leer-hinweis { margin: var(--a2) var(--a3); }
.vt-erledigt-gruppe + .vt-erledigt-gruppe { margin-top: var(--a3); }
.vt-erledigt-titel {
  display: flex; align-items: center; gap: var(--a1);
  margin: var(--a2) var(--a2) var(--a1); font-size: var(--groesse-xs); font-weight: 650; color: var(--text-2);
}
.vt-erledigt-gruppe.leer .vt-erledigt-titel { color: var(--text-3); font-weight: 500; }
.vt-tafel-rahmen::before, .vt-tafel-rahmen::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 28px;
  pointer-events: none; opacity: 0; transition: opacity var(--dauer) var(--kurve); z-index: 2;
}
.vt-tafel-rahmen::before { left: 0; background: linear-gradient(to right, rgba(0,0,0,.14), rgba(0,0,0,0)); }
.vt-tafel-rahmen::after { right: 0; background: linear-gradient(to left, rgba(0,0,0,.14), rgba(0,0,0,0)); }
.vt-tafel-rahmen.geht-links-weiter::before,
.vt-tafel-rahmen.geht-rechts-weiter::after { opacity: 1; }
/* Karten passen sich der Spalte an: nichts ragt heraus. Kunde und
   Werkstoff kürzt schon die Hausregel der Karte mit „…" (`.karte-kunde`,
   `.karte-positionen`; der volle Text steht jetzt im Tooltip). Die Chips
   brechen in der Vertriebskarte um — `.karte-chips` ist sonst einzeilig
   (Auftragskarte): Kurze Chips schrumpften zu „D…", und mit Umbruch aber
   ohne Deckel ragte ein langer Chip 30 px aus der Karte (Bedienprobe
   28.09.2026). Gekürzt wird nur, was allein breiter ist als die Karte. */
.vt-karte { min-width: 0; overflow-wrap: anywhere; }
.vt-karte .karte-chips { flex-wrap: wrap; }
.vt-karte .karte-chips .chip { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vt-karte .karte-kopf { min-width: 0; flex-wrap: wrap; }
.vt-karte .vt-mail-unter { overflow-x: auto; }
.karte-aktionen {
  display: flex; flex-wrap: wrap; gap: var(--a1); align-items: flex-start;
  margin-top: var(--a2);
}
details.karte-mehr > summary { list-style: none; cursor: pointer; }
details.karte-mehr > summary::-webkit-details-marker { display: none; }
details.karte-mehr[open] {
  flex-basis: 100%; padding: var(--a2); border-radius: var(--radius);
  background: var(--flaeche-2);
}
details.karte-mehr .aktionszeile { margin-top: var(--a1); gap: var(--a1); }
/* Mitlesen (24.09.2026): Die Knöpfe sind Korrekturen — zugeklappt. */
details.vt-korrigieren > summary { list-style: none; cursor: pointer; }
details.vt-korrigieren > summary::-webkit-details-marker { display: none; }
details.vt-korrigieren[open] { flex-basis: 100%; }
details.vt-korrigieren > .aktionszeile {
  display: flex; flex-wrap: wrap; gap: var(--a1); margin-top: var(--a1);
}
.karte-ereignis { margin-top: var(--a1); }
.vt-klaerfall { padding: var(--a2) 0; border-bottom: 1px solid var(--linie); }
.vt-klaerfall .aktionszeile { display: flex; flex-wrap: wrap; gap: var(--a1); margin-top: var(--a1); }
details.vt-telefon { position: relative; }
details.vt-telefon > summary { list-style: none; }
details.vt-telefon > summary::-webkit-details-marker { display: none; }
.vt-telefon-form {
  position: absolute; right: 0; top: calc(100% + var(--a1)); z-index: 30;
  width: min(380px, 90vw); box-shadow: var(--schatten-hebt);
}
.vt-zahlen { display: flex; flex-wrap: wrap; gap: var(--a4); margin-bottom: var(--a4); }
.vt-zahl { display: flex; flex-direction: column; min-width: 7rem; }
.vt-zahl strong { font-size: var(--groesse-l); }
.vt-abschnitt { margin-bottom: var(--a5); }
/* E1 (29.09.2026): überfällige Anfrage in der Warteschlange — rote Zeile. */
#warteschlange tr.ws-ueberfaellig > td { background: var(--fehler-flaeche); }
#warteschlange tr.ws-ueberfaellig > td:first-child { box-shadow: inset 3px 0 0 var(--fehler); }
.ws-unbesetzt { font-weight: 600; white-space: nowrap; }
.vt-abschnitt.ws-ueberfaellig-block { border-left: 3px solid var(--fehler); }
.vt-zeitleiste { list-style: none; padding: 0; margin: 0; }
.vt-zeitleiste li { padding: var(--a2) 0; border-bottom: 1px solid var(--linie); }
.vt-entwurf { white-space: pre-wrap; font-family: var(--schrift); font-size: var(--groesse-s);
  background: var(--flaeche-2); padding: var(--a3); border-radius: var(--radius); }
/* ═══ V2 C1: Anfrage-Seite im Vertrieb in zwei Spalten ab 1200 px ═══
   Die Reihenfolge trägt das DOM (links zuerst), nicht `order`: Unter
   1200 px stehen Kopf, Mail und Aktionen oben, die Seitenleiste darunter. */
.vt-anfrage-raster { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--a5); align-items: start; }
@media (min-width: 1200px) {
  .vt-anfrage-raster { grid-template-columns: minmax(0, 1fr) minmax(19rem, 25rem); }
}
.vt-anfrage-rechts { margin-bottom: var(--a5); }
.vt-anfrage-rechts .panel-felder { grid-template-columns: 100px minmax(0, 1fr); }
.vt-anfrage-rechts .panel-abschnitt:first-child { border-top: none; padding-top: 0; }
.vt-kopfzeile { display: flex; flex-wrap: wrap; align-items: center; gap: var(--a2) var(--a3); }
.vt-kopfzeile h1 { margin: 0; }
.vt-kopffelder { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--a1) var(--a3);
  margin: var(--a3) 0; }
.vt-kopffelder dt { color: var(--text-2); }
.vt-kopffelder dd { margin: 0; min-width: 0; }
#anfrage-kopf #kalkulieren { margin-top: var(--a3); }
details#angebot-aussen > summary { cursor: pointer; }
details#angebot-aussen > summary h2 { display: inline; }
.vt-kalk-liste { list-style: none; padding: 0; margin: 0; }
.vt-kalk-liste li { padding: var(--a1) 0; }
.vt-kalk-zahlen { display: block; color: var(--text-2); font-variant-numeric: tabular-nums; }

/* ═══ V2 C5: die Kundenmail, vollständig lesbar ═══
   Kein Feld fester Höhe, kein inneres Scrollfeld: Die Mail wächst mit
   ihrem Text. Lesebreite begrenzt, Zeilenumbrüche wie im Original. */
.vt-mail { max-width: 52rem; line-height: 1.5; }
.vt-mailzeilen { white-space: pre-wrap; overflow-wrap: anywhere; }
.vt-mail a { overflow-wrap: anywhere; }
.vt-merkmal { font-weight: 650; }
.vt-mailtabelle { border-collapse: collapse; margin: var(--a2) 0; font-variant-numeric: tabular-nums; }
.vt-mailtabelle td { border: 1px solid var(--linie); padding: 2px var(--a2); vertical-align: top; }
.vt-mail details { margin-top: var(--a2); }
.vt-mail details > summary { cursor: pointer; color: var(--text-2); }
.vt-mail-signatur .vt-mailzeilen, .vt-mail-verlauf .vt-mailzeilen { color: var(--text-2); }
/* Der Pfeil in den Listen (V2 C5): klein, ohne Rahmen; zeigt nach unten, wenn offen. */
.vt-mail-pfeil { background: none; border: none; padding: 0 var(--a1); cursor: pointer; color: var(--text-2);
  font-size: var(--groesse-s); line-height: 1; min-height: 0; box-shadow: none; }
.vt-mail-pfeil[aria-expanded="true"] { transform: rotate(90deg); }
.vt-mail-pfeil:hover { color: var(--text); }
tr.vt-mailzeile > td { background: var(--flaeche-2); padding: var(--a3) var(--a4); }
.vt-mail-unter { background: var(--flaeche-2); padding: var(--a3); border-radius: var(--radius); margin-top: var(--a2); }
.vt-klaer-ganz > summary { cursor: pointer; color: var(--text-2); }
.vt-anhaenge { list-style: none; padding: 0; margin: var(--a2) 0 0; }
.vt-anhaenge li { padding: 2px 0; }

/* Die Aktions-Zelle der Queue-Liste liegt ÜBER dem Zeilenlink (Wächter
   test_zeilenlink, AUSGENOMMENE_ZELLEN „aktion-zelle"). */
td.aktion-zelle { position: relative; z-index: 1; }

/* ═══ VK1 (29.09.2026): Vertrieb -> „Anfragen" ═══
   KEIN neues Design: Kacheln, Board, Karte, Status-Pille, Chip, Tabelle und
   Initialen-Kreis sind die Klassen der Auftrags-Übersicht „/" und der
   Liste „/liste". Hier stehen nur die Ergänzungen im selben Stil. */
.vk-ansicht-wahl { margin: 0 0 var(--a3); }
.vk-werkzeuge .filterleiste { flex-wrap: wrap; }
.vk-excel { margin-left: auto; }
.vk-reiter { margin: 0 0 var(--a3); flex-wrap: wrap; }
.vk-chip-zahl { font-variant-numeric: tabular-nums; opacity: .8; margin-left: 2px; }
/* Kacheln: aktive Kachel sichtbar markiert, gelber Rand bei „Nachfassen". */
.kachel.kachel-aktiv { box-shadow: inset 0 0 0 2px var(--akzent); }
.kachel.kachel-gelb { border-left: 3px solid var(--warnung); }
.kachel.kachel-gelb .kachel-wert { color: var(--warnung); }
.kachel-zusatz { font-size: var(--groesse-s); font-weight: 400; }
.vk-kachel-hinweis { margin: var(--a2) 0; }
/* Karte: gelber Rand bei „Nachfassen fällig", Übernehmen-Knopf im Fuss,
   Initialen gestrichelt rot, wenn niemand zuständig ist. */
.vk-karte.vk-gelb { border-left-color: var(--warnung); }
.vk-pille { white-space: nowrap; max-width: 60%; overflow: hidden; text-overflow: ellipsis; }
.vk-pille-rot { background: var(--fehler-flaeche); color: var(--fehler); }
.vk-summe { font-variant-numeric: tabular-nums; font-size: var(--groesse-xs); margin-left: auto; margin-right: var(--a2); }
.vk-karte .avatar-leer { border: 1px dashed var(--fehler); color: var(--fehler); background: transparent; }
.vk-karte-aktion { margin-top: var(--a2); }
/* Liste: Zeilenfarbe — IMMER zusätzlich als Text (nächster Schritt, Status). */
.vk-liste td { vertical-align: top; }
.vk-liste tr.vk-rot > td { background: var(--fehler-flaeche); }
.vk-liste tr.vk-rot > td:first-child { box-shadow: inset 3px 0 0 var(--fehler); }
.vk-liste tr.vk-gelb > td { background: var(--warnung-flaeche); }
.vk-liste tr.vk-gelb > td:first-child { box-shadow: inset 3px 0 0 var(--warnung); }
.vk-liste tr.vk-grau > td { background: var(--flaeche-2); color: var(--text-3); }
.vk-liste tr.vk-markiert > td { outline: 2px solid var(--akzent); outline-offset: -2px; }
.vk-liste a.zeilenlink { font-weight: 600; color: var(--akzent); }
/* Status und Bemerkung werden bedient — die GANZE Zelle liegt über dem
   Zeilenlink (wie `td.zustaendig-zelle`). */
td.vk-status-zelle, td.vk-bemerkung-zelle { position: relative; z-index: 1; }
.vk-entwurf { font-size: var(--groesse-xs); }
.vk-marge-niedrig { color: var(--fehler); font-weight: 600; }
.vk-status-zelle { min-width: 11rem; }
.vk-status { max-width: 12rem; }
.vk-schritt { font-size: var(--groesse-xs); color: var(--text-3); margin-top: 2px; }
.vk-schritt-rot { color: var(--fehler); font-weight: 600; }
.vk-schritt-gelb { color: var(--warnung); font-weight: 600; }
.vk-quittung { font-size: var(--groesse-xs); color: var(--ok); margin-top: 2px; }
.vk-fehler { font-size: var(--groesse-xs); color: var(--fehler); margin-top: 2px; }
.vk-bemerkung-zelle { max-width: 16rem; }
.vk-bemerkung { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: text; min-height: 1.4em; }
.vk-bemerkung:hover, .vk-bemerkung:focus { outline: 1px dashed var(--linie); }
.vk-bemerkung-eingabe { width: 100%; min-width: 10rem; }
.vk-fuss td { font-weight: 600; border-top: 2px solid var(--linie); }
.vk-seiten { display: flex; gap: var(--a3); align-items: center; margin: var(--a3) 0; }
.vk-dialog { border: 1px solid var(--linie); border-radius: var(--radius); padding: var(--a4); max-width: 26rem; }
.vk-dialog::backdrop { background: rgba(0, 0, 0, .25); }
.vk-dialog .menue-aktionen { display: flex; gap: var(--a2); justify-content: flex-end; }
/* Menü: zwei Zähler am Punkt „Anfragen" — rot nicht zugewiesen, gelb Nachfassen. */
.nav-badges { display: inline-flex; gap: 3px; }
.nav-badge.nav-badge-gelb { background: var(--warnung); }
/* Anfrage-Seite: Kopf, Reiter, Brotkrumen (Kalkulation gehört zur Anfrage). */
.vk-brotkrumen { display: flex; flex-wrap: wrap; gap: var(--a1); align-items: center; font-size: var(--groesse-s); margin: 0 0 var(--a2); }
.vk-zurueck-knopf { margin-left: auto; }
.vk-anfragekopf { margin-bottom: var(--a2); }
.vk-kopf-zeile { display: flex; flex-wrap: wrap; gap: var(--a2); align-items: center; }
.vk-kopf-nummer { font-size: var(--groesse-l); }
.vk-kopf-felder { display: flex; flex-wrap: wrap; gap: var(--a2) var(--a5); margin: var(--a2) 0 0; }
.vk-kopf-felder dt { font-size: var(--groesse-xs); color: var(--text-3); }
.vk-kopf-felder dd { margin: 0; }
.vk-anfrage-reiter { margin-bottom: var(--a3); }
.vk-verlauf { list-style: none; padding: 0; margin: 0; }
.vk-verlauf li { padding: var(--a2) 0; border-bottom: 1px solid var(--linie); }
/* VK1, gemessen an den Bildschirmfotos bei 1366 px: */
.vk-kacheln { flex-wrap: nowrap; }
.vk-kacheln .kachel { flex: 1 1 0; min-width: 0; }
.vk-kacheln .kachel-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vk-kacheln .kachel-wert { white-space: nowrap; }
.vk-karte .karte-nummer { white-space: nowrap; }
.vk-karte .karte-fuss { flex-wrap: wrap; }
/* Zwei Chips passen bei 1366 px nicht nebeneinander („MARGE 19,1 %“ war
   rechts abgeschnitten, Bildschirmfoto 29.09.2026) — sie brechen um. */
.vk-karte .karte-chips { flex-wrap: wrap; }
.vk-karte .karte-chips .chip { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vk-karte .karte-fuss .karte-termin { flex: 1 1 100%; }
.vk-board > .spalte:not(.schmal) .spalte-titel { white-space: normal; overflow: visible; }
.vk-liste { font-size: var(--groesse-s); }
/* Elf Spalten bei 1366 px: 4 px je Seite statt 6 — sonst fehlen im
   Szenario der Bedienprobe 31 px (gemessen 29.09.2026). */
.vk-liste th, .vk-liste td { padding-left: 4px; padding-right: 4px; }
.vk-liste select.vk-status { font-size: var(--groesse-s); padding: 2px 34px 2px 6px; min-height: 0; height: auto; max-width: 9.5rem; width: auto; }
.vk-liste .vk-status-zelle { min-width: 9.5rem; }
.vk-kunde { max-width: 11rem; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.vk-material { max-width: 9rem; }
.vk-liste .vk-bemerkung-zelle { max-width: 9rem; }
.vk-liste .zustaendig-zelle select { max-width: 8.5rem; font-size: var(--groesse-s); }
/* Über der Kalkulation steht der Kopf der Anfrage — die Kopfleiste rückt
   dann nicht mehr an den oberen Rand (sonst läge sie über den Reitern). */
.kalk-kopfleiste.vk-mit-kopf { margin-top: 0; }
/* Die Angebotsnummer bricht nie um — bei 1366 px stand sie sonst als
   „AN-/0010-/1“ auf drei Zeilen (Bildschirmfoto 29.09.2026). */
.kalk-kopfleiste.vk-mit-kopf .kalk-titel { white-space: nowrap; flex-shrink: 0; }

/* ═══ AV1 (29.09.2026): Stammdaten -> Antwortvorlagen ═══
   Liste im Stil von /liste, Editor mit Live-Vorschau daneben (ab 1200 px),
   darunter untereinander. Unbekannte Platzhalter rot MIT Wort („unbekannter
   Platzhalter" als Tooltip, Meldung darüber) — nie nur Farbe. */
.av-reiter { margin-bottom: var(--a3); }
.av-erklaerung { margin: 0 0 var(--a3); max-width: 70rem; }
.av-filter { display: flex; flex-wrap: wrap; gap: var(--a2); align-items: center; margin: 0 0 var(--a3); }
.av-filter input[type="search"] { min-width: 14rem; }
.av-liste td { vertical-align: top; }
.av-liste .av-betreff { max-width: 14rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.av-liste .av-text { max-width: 18rem; font-size: var(--groesse-s); }
.av-stern { color: var(--warnung); font-weight: 600; white-space: nowrap; }
.av-aktionen { white-space: nowrap; }
.av-aktionen .knopf, .av-aktionen button { margin-right: 2px; }
.av-liste th, .av-liste td { padding-left: 6px; padding-right: 6px; }
.av-inline { display: inline; margin: 0; }
td.av-aktionen { position: relative; z-index: 1; }
.av-bedingungen .av-text { max-width: 13rem; }
/* N1: mit „Hinweis intern“ wird die Zahlungstabelle breiter — die fünf Knöpfe
   (↑ ↓ Bearbeiten Archivieren Löschen) brechen um statt die Seite zu verbreitern
   (gemessen 1366 px: Aktionen 351 px, Tabelle 38 px über dem Kasten). */
.av-bedingungen td.av-aktionen { white-space: normal; min-width: 11rem; }
.av-bedingung-form { display: flex; flex-wrap: wrap; gap: var(--a2); align-items: end; }
.av-bedingung-form label { display: flex; flex-direction: column; font-size: var(--groesse-s); color: var(--text-3); }
.av-bedingung-form input:not([type="checkbox"]) { min-width: 12rem; }
.av-haken { display: inline-flex; gap: var(--a1); align-items: center; }
.av-sprache-fehlt { font-size: var(--groesse-xs); }
.av-editor { display: flex; flex-direction: column; gap: var(--a4); }
.av-felder { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--a2) var(--a3); align-items: center; }
.av-platzhalter { display: flex; flex-wrap: wrap; gap: var(--a1); align-items: center; margin: var(--a3) 0 var(--a2); }
.av-platzhalter-knopf { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: var(--groesse-xs); }
.av-text-feld { width: 100%; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: var(--groesse-s); }
.av-vorschau-rahmen { border: 1px solid var(--linie); border-radius: var(--radius); padding: var(--a3) var(--a4); background: var(--flaeche); }
.av-vorschau-rahmen h3 { margin-top: 0; }
.av-vorschau-text { white-space: normal; font-family: Calibri, Arial, sans-serif; line-height: 1.45; }
mark.av-unbekannt { background: var(--fehler-flaeche); color: var(--fehler); font-weight: 600; outline: 1px solid var(--fehler); }
@media (min-width: 1200px) {
  .av-editor { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; }
  .av-vorschau-rahmen { position: sticky; top: var(--a4); max-height: calc(100vh - 2 * var(--a4)); overflow: auto; }
}
.av-signatur { display: grid; gap: var(--a4); }
.av-signatur-felder { display: flex; flex-direction: column; gap: var(--a2); max-width: 36rem; }
.av-signatur-pre { font-family: Calibri, Arial, sans-serif; white-space: pre-wrap; margin: 0; }
.av-signatur-vorschau-rahmen { border: 1px solid var(--linie); border-radius: var(--radius); padding: var(--a3) var(--a4); background: var(--flaeche); }
@media (min-width: 1200px) { .av-signatur { grid-template-columns: minmax(0, 36rem) minmax(0, 1fr); align-items: start; } }
/* Antwort an den Kunden (Kalkulation): Auswahl in einer umbrechenden Zeile. */
.kalk-antwort-wahl { flex-wrap: wrap; }
.kalk-antwort-quelle { margin: var(--a1) 0; }
.kalk-schnappschuss { display: flex; flex-wrap: wrap; gap: var(--a2); align-items: center; margin: var(--a2) 0; }
/* N1: Konditionen als eigene, umbrechende Zeile unter der Auswahl. Die
   Herkunft steht als WORT daneben („aus Frachtblock" / „nur im Angebotstext"). */
.kalk-konditionen { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: var(--a2) var(--a3); align-items: center; }
.kalk-kond-feld { display: inline-flex; gap: var(--a1); align-items: center; white-space: nowrap; }
.kalk-kond-zahl { width: 6rem; }
.kalk-kond-quelle { font-size: var(--groesse-xs); }
.av-vorgaben-form { display: grid; grid-template-columns: max-content 8rem; gap: var(--a2) var(--a3); align-items: center; max-width: 40rem; }
.av-summe-hinweis { margin: var(--a2) 0 0; }

/* ═══════════════════════════════ Kalkulationsrechner nach Zielbild (G6, 26.09.2026)
   /root/kalk-mockup.html 1:1 (Aufbau, Spalten, Farben, Abstände, Schriftgrößen),
   Vorgabe Eric. Abweichungen, die ODIN-Technik erzwingt, stehen im Bericht
   kalk-g6-gestaltung.md: Hausschrift statt system-ui, Hausrot (--akzent) statt
   #CC1118, Zellpolster 6 px statt 8 px (1366 px mit Seitenleiste), Seitenleiste
   links (die Summenleiste beginnt rechts davon).
   Alle Klassen tragen das Präfix kalk-. Die Zielbild-Farben stehen als
   --kalk-*-Token auf der Seite (Wächter test_kalkulation_gestaltung: Schriftgrößen,
   Abstände, Radien, Rot nur für Hauptaktion/aktive Zeile/Fehler, Kontrast AA). */
main.kalk-seite {
  --kalk-rot: var(--akzent); --kalk-rot-hell: var(--akzent-flaeche);
  /* G8 (27.09.2026, Vorgabe Eric — geht dem Zielbild vor): deutlich mehr Kontrast.
     Text #111827, Beschriftungen #374151, Eingabezellen immer mit Rahmen #9ca3af
     auf Weiss, berechnete Zellen #eceef1 mit #374151, Zeilentrenner #d1d5db,
     Zebra #fafafa, Kopfzeile #f3f4f6 fett, Einkauf #bfdbfe/#e0edff, Verkauf
     #bbf7d0/#e3f7e9, Marge-Chips kräftiger. Wächter: 7:1 Daten, 4,5:1 Rest. */
  --kalk-text: #111827; --kalk-grau: #374151; --kalk-grau-hell: #9ca3af; --kalk-rahmen: #9ca3af;
  --kalk-linie: #d1d5db; --kalk-flaeche: #f3f4f6; --kalk-weiss: #fff; --kalk-zebra: #fafafa;
  --kalk-ek: #e0edff; --kalk-ek-kopf: #bfdbfe; --kalk-ek-text: #1e3a5f;
  --kalk-vk: #e3f7e9; --kalk-vk-kopf: #bbf7d0; --kalk-vk-text: #14532d;
  --kalk-auto: #eceef1; --kalk-neu: #fafafa;
  --kalk-ok: #166534; --kalk-ok-bg: #bbf7d0; --kalk-warn: #92400e; --kalk-warn-bg: #fde68a;
  --kalk-warn-text: #78350f; --kalk-err: #991b1b; --kalk-err-bg: #fecaca; --kalk-man: #1d4ed8;
  --kalk-chip-bg: #e5e7eb; --kalk-punkt-warn: #d97706; --kalk-punkt-err: #dc2626;
  font-size: 14px; line-height: 1.4; color: var(--kalk-text);
  padding-bottom: 120px;
}
.kalk-seite .kalk-num { font-variant-numeric: tabular-nums; text-align: right; font-weight: 500; }
.kalk-seite .kalk-mitte { text-align: center; }
.kalk-label { font-size: 12px; color: var(--kalk-grau); text-transform: uppercase; letter-spacing: .03em; }
.kalk-seite .kalk-einheit { color: var(--kalk-grau); font-size: 12px; }
.kalk-nur-vorlesen { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.kalk-mini { font-size: 12px; vertical-align: super; margin-left: 2px; color: var(--kalk-grau); }
.kalk-rot { color: var(--kalk-err); font-weight: 600; }

/* Kopfleiste (fest oben, über die ganze Breite der Hauptspalte) */
.kalk-kopfleiste {
  position: sticky; top: 0; z-index: 5; background: var(--kalk-weiss); border-bottom: 1px solid var(--kalk-linie);
  padding: 12px 24px; display: flex; align-items: center; gap: 16px;
  margin: calc(-1 * var(--a6)) calc(-1 * clamp(var(--a4), 2.5vw, var(--a7))) 16px;
}
.kalk-titel { font-size: 20px; margin: 0; font-weight: 650; }
.kalk-chip { display: inline-block; font-size: 12px; padding: 2px 8px; border-radius: 999px; background: var(--kalk-chip-bg); color: var(--kalk-grau); }
.kalk-chip-ok { background: var(--kalk-ok-bg); color: var(--kalk-ok); }
.kalk-chip-err { background: var(--kalk-err-bg); color: var(--kalk-err); }
.kalk-kundenzeile { color: var(--kalk-grau); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kalk-kundenzeile b { color: var(--kalk-text); font-weight: 600; }
.kalk-kundenzeile a { color: var(--kalk-rot); text-decoration: none; }
.kalk-kopf-rechts { margin-left: auto; display: flex; gap: 8px; align-items: center; flex-shrink: 0; }
/* Doppelter Selektor (Wächter test_waechter_knopfstile): die rote Submit-Grundregel `button[type="submit"]`
   hat 0-1-1 und schlüge eine blosse Klasse — in den Dialogen (Zuordnen, Kopie, Storno) sind das Submit-Knöpfe. */
.kalk-btn, button[type="submit"].kalk-btn { border: 1px solid var(--kalk-linie); background: var(--kalk-weiss); color: var(--kalk-text); border-radius: 6px; padding: 8px 14px;
  font: inherit; font-size: 14px; cursor: pointer; min-height: 0; margin: 0; line-height: 1.4; text-decoration: none; display: inline-block; }
.kalk-btn:hover, button[type="submit"].kalk-btn:hover { background: var(--kalk-flaeche); }
.kalk-btn-primaer, button[type="submit"].kalk-btn-primaer { background: var(--kalk-rot); border-color: var(--kalk-rot); color: var(--kalk-weiss); font-weight: 600; }
.kalk-btn-primaer:hover, button[type="submit"].kalk-btn-primaer:hover { background: var(--akzent-hover); border-color: var(--akzent-hover); }
.kalk-btn-mehr { padding: 8px 10px; }
.kalk-btn-klein { padding: 4px 10px; font-size: 12px; }
.kalk-link, button[type="submit"].kalk-link { color: var(--kalk-rot); font-weight: 600; text-decoration: none; background: none; border: none; padding: 0; margin-left: 12px; font: inherit; font-weight: 600; cursor: pointer; }

/* Menü (⋯) — <details>, Liste als Popover */
.kalk-menue { position: relative; display: inline-block; }
.kalk-menue > summary { list-style: none; cursor: pointer; }
.kalk-menue > summary::-webkit-details-marker { display: none; }
/* Popover (oberste Ebene): eigene Lage über top/left aus dem Skript, kein Auto-Zentrieren. */
.kalk-menue-liste { position: fixed; inset: auto; margin: 0; background: var(--kalk-weiss); border: 1px solid var(--kalk-rahmen); border-radius: 8px;
  box-shadow: var(--schatten-hebt); padding: 4px; min-width: 220px; z-index: 100; display: none; flex-direction: column; color: var(--kalk-text); }
.kalk-menue-liste:popover-open, .kalk-menue-liste.kalk-menue-offen { display: flex; }
.kalk-menue-knopf { cursor: pointer; }
.kalk-menue-liste > button, .kalk-menue-liste > a, .kalk-menue-liste > form > button { display: block; width: 100%; text-align: left; padding: 6px 10px; background: none; border: none;
  border-radius: 4px; font: inherit; font-size: 14px; color: var(--kalk-text); cursor: pointer; text-decoration: none; min-height: 0; margin: 0; line-height: 1.4; }
.kalk-menue-liste > button:hover, .kalk-menue-liste > a:hover, .kalk-menue-liste > form > button:hover { background: var(--kalk-flaeche); }
.kalk-menue-liste > button:disabled { color: var(--kalk-grau); opacity: .55; cursor: default; pointer-events: none; }
.kalk-menue-liste:focus { outline: none; }
.kalk-menue-liste > button.kalk-gefahr { color: var(--kalk-err); }
.kalk-menue-liste > form { margin: 0; }
.kalk-zeilenmenue .kalk-menue-knopf { background: none; border: none; color: var(--kalk-grau); font: inherit; font-size: 16px; padding: 0; margin: 0; min-height: 0; width: 100%; height: 30px; line-height: 30px; }
.kalk-zeilenmenue .kalk-menue-knopf:hover, .kalk-zeilenmenue .kalk-menue-knopf[aria-expanded="true"] { color: var(--kalk-text); background: var(--kalk-flaeche); border-radius: 4px; }
.kalk-nur-details { background: none; border: none; color: var(--kalk-grau); cursor: pointer; padding: 0; min-height: 0; margin: 0; font: inherit; }

/* Gelbe Zeile: Kunde nicht im Stamm */
.kalk-hinweis { background: var(--kalk-warn-bg); color: var(--kalk-warn-text); border-radius: 6px; padding: 8px 12px; margin-bottom: 16px; display: flex; gap: 12px; align-items: center; font-size: 13px; }
/* V2 B3: „Als Neukunde anlegen" ist ein Submit-Knopf — ohne die Submit-Variante
   bliebe er ein roter Vollton-Balken (Wächter test_waechter_knopfstile). */
.kalk-hinweis .kalk-link, .kalk-hinweis button[type="submit"].kalk-link { color: var(--kalk-warn-text); margin-left: 0; }

/* Meldungen (Konflikt, Fehler, gespeichert, Rückgängig, Begründung) */
.kalk-meldung { border-radius: 6px; padding: 8px 12px; margin-bottom: 12px; font-size: 13px; display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.kalk-meldung-fehler { background: var(--kalk-err-bg); color: var(--kalk-err); }
.kalk-meldung-ok { background: var(--kalk-ok-bg); color: var(--kalk-ok); }
.kalk-meldung-warnung { background: var(--kalk-warn-bg); color: var(--kalk-warn-text); }
.kalk-meldung input { width: auto; min-height: 0; height: 30px; padding: 0 8px; margin: 0; font-size: 14px; border: 1px solid var(--kalk-linie); border-radius: 6px; }

/* Kopfdaten: gleichmäßiges Raster */
.kalk-karte { background: var(--kalk-weiss); border: 1px solid var(--kalk-linie); border-radius: 8px; margin-bottom: 16px; }
.kalk-kopfdaten { display: grid; grid-template-columns: repeat(6, 1fr); gap: 12px 16px; padding: 16px; }
.kalk-feld { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.kalk-feld-breit { grid-column: 1 / -1; }
.kalk-seite .kalk-wert { height: 34px; min-height: 0; border: 1px solid var(--kalk-rahmen); border-radius: 6px; padding: 0 10px; display: flex; align-items: center;
  background: var(--kalk-weiss); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 14px; margin: 0; width: 100%; color: var(--kalk-text); box-shadow: none; }
.kalk-seite input.kalk-wert:focus, .kalk-seite select.kalk-wert:focus { border-color: var(--kalk-rot); box-shadow: 0 0 0 2px var(--kalk-rot-hell); outline: none; }
.kalk-seite select.kalk-wert { appearance: none; background-image: none; padding-right: 10px; }
.kalk-wert-paar { padding: 0 4px; gap: 4px; }
.kalk-wert-paar > input, .kalk-wert-paar > select { border: none; background: transparent; background-image: none; height: 32px; min-height: 0; padding: 0 6px; margin: 0; font-size: 14px; flex: 1 1 auto; min-width: 0; width: auto; box-shadow: none; }
.kalk-wert-paar > input:focus, .kalk-wert-paar > select:focus { outline: none; background: var(--kalk-flaeche); border-radius: 4px; }
.kalk-wert-paar > select { appearance: none; background-image: none; padding-right: 6px; }
.kalk-wert-paar > select.kalk-anrede { flex: 0 0 auto; width: 4.6em; color: var(--kalk-grau); font-size: 12px; padding: 0 4px; appearance: none; background-image: none; }
.kalk-wert-paar > input.kalk-plz { flex: 0 0 5em; }
.kalk-wert-num { justify-content: flex-end; }
.kalk-wert-num > input { text-align: right; }
.kalk-wert-paar > input[type="date"] { flex: 0 0 auto; width: 8.4em; font-size: 12px; color: var(--kalk-grau); padding: 0 2px; }
.kalk-mehr > summary { border-top: 1px solid var(--kalk-linie); padding: 8px 16px; font-size: 13px; color: var(--kalk-grau); cursor: pointer; list-style: none; }
.kalk-mehr > summary::-webkit-details-marker { display: none; }
.kalk-mehr > summary .kalk-mehr-pfeil, .kalk-mehr > summary { }
.kalk-mehr-pfeil { color: var(--kalk-rot); font-weight: 600; display: inline-block; transition: transform var(--dauer) var(--kurve); }
.kalk-mehr[open] .kalk-mehr-pfeil { transform: rotate(90deg); }
.kalk-mehr > summary { font-weight: 600; color: var(--kalk-rot); }
.kalk-mehr-meta { font-weight: 400; color: var(--kalk-grau); margin-left: 8px; }
.kalk-mehr[open] .kalk-mehr-meta { display: none; }
.kalk-kopfdaten-mehr { border-top: 1px solid var(--kalk-linie); }
.kalk-haken { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; color: var(--kalk-grau); }
.kalk-haken input { width: auto; min-height: 0; }

/* Positionstabelle: feste Spalten, Gruppenkopf, Zellen erst bei Maus/Fokus ein Feld */
.kalk-tabelle-umschlag { overflow: hidden; margin-bottom: 16px; }
.kalk-tabelle { width: 100%; border-collapse: separate; border-spacing: 0; table-layout: fixed; }
/* Spaltenbreiten des Zielbilds als Anteile (Zielbild in px: Nr 36, Werkstoff 104, Dichte 66, Form 80, Abmessung 96,
   Länge 78, Menge 64, Einh. 52, Gewicht 90, EK 80, je 60, Aufschlag 84, VK 80, je 60, Positionswert 104, Marge 90, ⋯ 32;
   ODIN: Abmessung/je/Positionswert etwas breiter, Werkstoff/Dichte/Länge/Marge schmaler — bei 1366 px mit Seitenleiste
   sonst nicht lesbar). Prozent statt Pixel: feste Pixel skalieren bei table-layout: fixed nicht herunter (gemessen 199 px Überlauf). */
.kalk-c-nr { width: 2.083%; } .kalk-c-werkstoff { width: 6.818%; } .kalk-c-dichte { width: 4.356%; } .kalk-c-form { width: 6.25%; } .kalk-c-abm { width: 9.754%; } .kalk-c-laenge { width: 4.545%; } .kalk-c-menge { width: 4.356%; } .kalk-c-einh { width: 3.598%; } .kalk-c-gewicht { width: 5.303%; } .kalk-c-ek { width: 5.114%; } .kalk-c-je { width: 4.356%; } .kalk-c-fracht { width: 4.356%; } .kalk-c-ekinkl { width: 7.197%; } .kalk-c-aufschlag { width: 6.439%; } .kalk-c-vk { width: 5.303%; } .kalk-c-pw { width: 8.239%; } .kalk-c-marge { width: 5.682%; } .kalk-c-aktion { width: 1.894%; }
/* V2 (Paket F, 28.09.2026): 19 Spalten — „Fracht" und „EK inkl. Kosten" in der Einkauf-Gruppe. GEMESSEN im Browser bei
   1366 px (Tabelle 1.056 px): Kopfbreiten (Text + Polster) Werkstoff 65, Aufschlag 67, Positionswert 87, „EK inkl. Kosten"
   96 — zusammen mit den Feldern (Form 66 für „Rohr rd", Aufschlag 68) passt das nur mit 2 px Zellpolster und Köpfen, die
   in zwei Zeilen umbrechen dürfen (38 px Zeile trägt zwei 14-px-Zeilen). Breiten in px (Felder nach N4 gemessen: Länge
   „3000" 32, Abmessung „100×200×300" 88 Text + Polster): Nr 22, Werkstoff 72 (B4, vorher 65), Dichte 46, Form 66,
   Abmessung 103, Länge 48, Menge 46, Einh. 38, Gewicht 56, EK 54, je 46, Fracht 46, EK inkl. 76, Aufschlag 68, VK 56,
   je 46, Positionswert 87, Marge 60, ⋯ 20 = 1.056. */
.kalk-tabelle th, .kalk-tabelle td { height: 38px; padding: 0 2px; border-bottom: 1px solid var(--kalk-linie); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: middle; font-size: 14px; }
.kalk-tabelle thead tr.kalk-gruppe th { height: 26px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--kalk-grau); text-align: left; border-bottom: none; background: var(--kalk-flaeche); }
.kalk-tabelle thead tr.kalk-spalten th { font-size: 12px; font-weight: 700; color: var(--kalk-text); text-align: left; background: var(--kalk-flaeche);
  white-space: normal; line-height: 14px; overflow-wrap: normal; }
.kalk-tabelle thead th.kalk-num { text-align: right; }
.kalk-tabelle thead th.kalk-mitte { text-align: center; }
.kalk-tabelle .kalk-g-ek { background: var(--kalk-ek-kopf); color: var(--kalk-ek-text); }
.kalk-tabelle .kalk-g-vk { background: var(--kalk-vk-kopf); color: var(--kalk-vk-text); }
.kalk-tabelle td.kalk-ek { background: var(--kalk-ek); }
.kalk-tabelle td.kalk-vk { background: var(--kalk-vk); }
.kalk-tabelle td.kalk-auto { background: var(--kalk-auto); color: var(--kalk-grau); }
.kalk-tabelle tbody tr.kalk-zeile:nth-of-type(even) td { background-color: var(--kalk-zebra); }
/* KEIN filter am Hover: ein Filter macht jedes `position: fixed`-Kind zum Kind der Zelle
   (Menü abgeschnitten, gemessen 27.09.2026). Hover nur über die Feldrahmen. */
.kalk-tabelle tbody tr.kalk-aktiv td:first-child { box-shadow: inset 3px 0 0 var(--kalk-rot); }
.kalk-tabelle td.kalk-aktion { overflow: visible; text-align: center; padding: 0; }
.kalk-alternativ td { color: var(--kalk-grau); }
.kalk-uhr { background: none; border: none; color: var(--kalk-grau); font: inherit; font-size: 11px; cursor: pointer; padding: 0; margin: 0 0 0 2px; min-height: 0; line-height: 1; vertical-align: middle; }
.kalk-uhr:hover { color: var(--kalk-text); }
.kalk-tabelle td.kalk-nr { text-align: left; padding-left: 6px; overflow: visible; text-overflow: clip; }
.kalk-seite .kalk-zelle { display: block; width: 100%; height: 30px; min-height: 0; line-height: 28px; border: 1px solid var(--kalk-rahmen); border-radius: 4px; padding: 0 4px; margin: 0;
  background: var(--kalk-weiss); font-size: 14px; color: var(--kalk-text); box-shadow: none; box-sizing: border-box; }
.kalk-seite .kalk-zelle:hover { border-color: var(--kalk-grau); }
.kalk-seite .kalk-zelle:focus { border-color: var(--kalk-rot); box-shadow: 0 0 0 1px var(--kalk-rot); outline: none; }
.kalk-seite .kalk-zelle:disabled { background: var(--kalk-auto); color: var(--kalk-grau); border-color: transparent; }
.kalk-seite .kalk-auto .kalk-zelle { background: var(--kalk-auto); border-color: transparent; color: var(--kalk-grau); }
.kalk-seite .kalk-auto .kalk-zelle:hover { background: var(--kalk-weiss); border-color: var(--kalk-grau); }
.kalk-seite .kalk-auto .kalk-zelle:focus { background: var(--kalk-weiss); border-color: var(--kalk-rot); }
.kalk-seite .kalk-zelle[readonly] { color: var(--kalk-grau); }
.kalk-seite select.kalk-zelle { appearance: none; background-image: none; padding-right: 6px; cursor: pointer; }
.kalk-seite select.kalk-form { font-size: 13px; }
.kalk-seite .kalk-zelle.kalk-einheit { color: var(--kalk-grau); font-size: 12px; font-weight: 500; }
.kalk-num .kalk-zelle, .kalk-seite input.kalk-zahl { text-align: right; font-variant-numeric: tabular-nums; }
.kalk-seite .kalk-feld-fehlt { border-color: #fca5a5; background: var(--kalk-err-bg); }
.kalk-seite .kalk-feld-warnung { border-color: var(--kalk-punkt-warn); background: var(--kalk-warn-bg); }
.kalk-seite .kalk-feld-hinweis { border-style: dashed; border-color: var(--kalk-linie); }
.kalk-seite .kalk-dichte-fehlt { border-color: #fca5a5; background: var(--kalk-err-bg); }
.kalk-seite .kalk-dichte-gruppe { color: var(--kalk-warn); }
.kalk-seite .kalk-dichte-manuell { color: var(--kalk-man); }
.kalk-seite input.kalk-werkstoff::-webkit-calendar-picker-indicator, .kalk-seite input[list]::-webkit-calendar-picker-indicator { display: none; opacity: 0; width: 0; height: 0; }
.kalk-werkstoff-halter, .kalk-mitpunkt { position: relative; display: block; }
.kalk-kurzname { position: absolute; right: 4px; top: 0; line-height: 30px; font-size: 12px; color: var(--kalk-grau); pointer-events: none; max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kalk-werkstoff-halter:focus-within .kalk-kurzname, .kalk-werkstoff-halter:hover .kalk-kurzname { display: none; }
/* Unter 1800 px ist die Werkstoffspalte zu schmal für Nummer UND Kurzname (gemessen 1366: 73 px, 1920: 100 px) — der Kurzname bleibt im Tooltip. */
@media (max-width: 1799px) { .kalk-kurzname { display: none; } }
.kalk-punkt { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-left: 4px; vertical-align: middle; }
.kalk-p-warn { background: var(--kalk-punkt-warn); } .kalk-p-err { background: var(--kalk-punkt-err); } .kalk-p-man { background: var(--kalk-man); } .kalk-p-fest { background: var(--kalk-grau); }
.kalk-mitpunkt > .kalk-punkt { position: absolute; right: 2px; top: 50%; transform: translateY(-50%); margin: 0; pointer-events: none; }
.kalk-mitpunkt > .kalk-zelle:has(+ .kalk-punkt) { padding-right: 12px; }
.kalk-suffix { position: absolute; right: 4px; top: 0; line-height: 30px; font-size: 12px; color: var(--kalk-grau); pointer-events: none; }
.kalk-mitpunkt > .kalk-zelle:has(~ .kalk-suffix) { padding-right: 14px; }
.kalk-mitpunkt > .kalk-zelle:has(+ .kalk-punkt ~ .kalk-suffix), .kalk-mitpunkt > .kalk-zelle:has(+ .kalk-punkt + .kalk-suffix) { padding-right: 24px; }
.kalk-mitpunkt > .kalk-punkt:has(+ .kalk-suffix) { right: 14px; }
.kalk-positionswert { font-weight: 700; }
.kalk-margechip { display: inline-flex; align-items: center; justify-content: center; min-width: 54px; border-radius: 999px; padding: 2px 8px; font-size: 12px; font-weight: 700; gap: 2px; vertical-align: middle; }
.kalk-m-ok { background: var(--kalk-ok-bg); color: var(--kalk-ok); } .kalk-m-warn { background: var(--kalk-warn-bg); color: var(--kalk-warn); } .kalk-m-err { background: var(--kalk-err-bg); color: var(--kalk-err); }
.kalk-seite .kalk-margechip input { width: 3.2em; min-height: 0; height: auto; border: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; text-align: right; box-shadow: none; }
.kalk-seite .kalk-margechip input:focus { outline: none; background: var(--kalk-weiss); border-radius: 4px; }
.kalk-seite .kalk-margechip input.kalk-marge-leer { display: none; }
.kalk-margechip.kalk-m-err .kalk-marge-text + input + .kalk-marge-prozent { display: none; }
.kalk-marge-zelle { text-align: center; }
.kalk-tabelle tr.kalk-neu-zeile td { color: var(--kalk-grau); font-style: italic; background: var(--kalk-neu); }
.kalk-seite textarea.kalk-schnell-feld { color: var(--kalk-text); }
.kalk-neu-plus button { background: none; border: none; color: var(--kalk-grau); font: inherit; font-size: 16px; cursor: pointer; padding: 0; margin: 0; min-height: 0; width: 100%; text-align: right; }
.kalk-neu-plus button:hover { color: var(--kalk-text); }
.kalk-neu-feld { overflow: visible; }
.kalk-schnell-halter { position: relative; display: block; }
.kalk-seite textarea.kalk-schnell-feld { border: 1px dashed var(--kalk-rahmen); resize: none; overflow: hidden; font-style: italic; font-family: inherit; line-height: 28px; }
.kalk-seite textarea.kalk-schnell-feld:focus { font-style: normal; border-style: solid; }
.kalk-schnell-vorschau { position: absolute; left: 0; right: 0; top: 34px; z-index: 20; background: var(--kalk-weiss); border: 1px solid var(--kalk-linie); border-radius: 8px;
  box-shadow: var(--schatten-hebt); padding: 8px 12px; font-size: 13px; font-style: normal; color: var(--kalk-text); white-space: normal; }
.kalk-schnell-vorschau:not(:has(.kalk-schnell-zeile)) { display: none; }
.kalk-schnell-zeile { margin-top: 4px; }
.kalk-tabelle tr.kalk-fracht td { font-size: 13px; color: var(--kalk-grau); background: var(--kalk-neu); overflow: visible; }
.kalk-fracht-titel { font-weight: 600; }
.kalk-fracht-zeile { display: inline-flex; align-items: center; gap: 4px; margin-left: 12px; }
.kalk-seite .kalk-fracht-zeile .kalk-zelle { display: inline-block; width: auto; height: 26px; line-height: 24px; border-color: var(--kalk-linie); background: var(--kalk-weiss); }
.kalk-seite .kalk-fracht-zeile input.kalk-fracht-betrag { width: 6em; }
.kalk-fracht-weg { background: none; border: none; color: var(--kalk-grau); cursor: pointer; padding: 0 4px; margin: 0; min-height: 0; font: inherit; font-size: 14px; }
.kalk-fracht-weg:hover { color: var(--kalk-err); }
.kalk-fracht-summe { margin-left: 12px; }
/* T2: Tarif an der Frachtzeile — Frachtführer, PLZ/Land (eingehend), Grund, manuell */
.kalk-tarif { display: inline-flex; align-items: center; gap: 4px; margin-left: 8px; }
.kalk-seite .kalk-tarif .kalk-zelle { display: inline-block; width: auto; height: 26px; line-height: 24px; border-color: var(--kalk-linie); background: var(--kalk-weiss); }
.kalk-seite .kalk-tarif input.kalk-fracht-plz { width: 5em; }
.kalk-seite .kalk-tarif input.kalk-land { width: 3em; }
.kalk-seite input.kalk-land { text-transform: uppercase; }
.kalk-tarif-hinweis { font-size: 12px; color: var(--kalk-grau); white-space: nowrap; }
.kalk-tarif-kein { color: var(--kalk-err); font-weight: 600; }
.kalk-tarif-manuell { color: var(--kalk-man); font-weight: 600; }
.kalk-tarif .kalk-link { margin-left: 4px; font-size: 12px; }
/* T2: Seite Frachttarife */
#tarif-versionen tr.tarif-gezeigt td { font-weight: 600; }
.tarif-tabelle td { font-variant-numeric: tabular-nums; white-space: nowrap; }
.tarif-tabelle td.tarif-leer { color: var(--text-3); }
.tarif-tabelle td.tarif-null { color: var(--fehler); }
.tarif-aendern input { width: 6em; }

/* Details einer Zeile */
.kalk-details td { background: var(--kalk-flaeche); padding: 12px 16px; height: auto; white-space: normal; overflow: visible; }
.kalk-details-raster { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 1100px) { .kalk-details-raster { grid-template-columns: 1fr; } }
.kalk-details h4 { margin: 8px 0 4px; font-size: 12px; color: var(--kalk-grau); text-transform: uppercase; letter-spacing: .03em; }
.kalk-details input, .kalk-details select { min-height: 0; height: 30px; padding: 0 6px; font-size: 14px; margin: 0; width: auto; border: 1px solid var(--kalk-linie); border-radius: 4px; appearance: none; background-image: none; }
.kalk-kostenzeile { margin-bottom: 4px; }
.kalk-rechenweg { width: 100%; font-size: 12px; }
.kalk-rechenweg td, .kalk-rechenweg th { padding: 2px 4px; height: auto; }
.kalk-positionstext { width: 100%; font-family: inherit; font-size: 14px; }

/* Summenleiste fest am unteren Rand (rechts der Seitenleiste) */
.kalk-summen { position: fixed; left: 240px; right: 0; bottom: 0; z-index: 40; background: var(--kalk-weiss); border-top: 1px solid var(--kalk-linie);
  box-shadow: 0 -4px 12px rgba(0,0,0,.04); padding: 10px 24px; display: flex; gap: 24px; align-items: center; justify-content: flex-end; }
.kalk-summe .kalk-label { white-space: nowrap; }
body.leiste-zu .kalk-summen { left: 64px; }
.kalk-summen .chip { margin-right: auto; }
.kalk-summe { display: flex; flex-direction: column; align-items: flex-end; }
.kalk-summe b { font-size: 16px; font-variant-numeric: tabular-nums; }
.kalk-summe-gross b { font-size: 22px; }
body:has(.loki-knopf) .kalk-summen { padding-right: 96px; }

/* ═══ N6 (Vorgabe Eric, 29.09.2026): Kundenmail neben der Arbeit ═══
   Ersetzt die V2-C5-Leiste (Lasche am rechten Rand, Breite gezogen):
   ausgeliefert OFFEN, eingeklappt nur über den Knopf (Keks `odin_kalk_mail`).
   Unter 1600 px ein Block ÜBER der Tabelle, höchstens 260 px hoch mit
   eigenem Scrollbalken — die Tabelle behält die volle Breite. Ab 1600 px
   eine rechte Spalte (30 %, 360–560 px), die unter der Kopfleiste klebt und
   bis über die Summenleiste reicht; sie scrollt in sich. Die Summenleiste
   selbst ist fest positioniert und bleibt über die ganze Breite. */
.kalk-mit-mail { display: flex; flex-direction: column; }
.kalk-mit-mail-haupt { min-width: 0; }
.kalk-mailpanel { order: -1; margin-bottom: 12px; border: 1px solid var(--kalk-linie); border-radius: 8px; background: var(--kalk-weiss); }
.kalk-mailpanel-leiste { display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 6px 12px; background: var(--kalk-flaeche); border-radius: 8px; }
.kalk-mailpanel.ist-offen .kalk-mailpanel-leiste { border-radius: 8px 8px 0 0; border-bottom: 1px solid var(--kalk-linie); }
.kalk-mailpanel-inhalt { padding: 12px 16px; max-height: 260px; overflow: auto; overscroll-behavior: contain; }
.kalk-mailpanel-felder { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 2px 12px; margin: 0 0 8px; font-size: 12px; }
.kalk-mailpanel-felder dt { color: var(--kalk-grau); }
.kalk-mailpanel-felder dd { margin: 0; overflow-wrap: anywhere; }
.kalk-mailpanel-meta { color: var(--kalk-grau); font-size: 12px; margin: 0 0 8px; }
.kalk-mailpanel-notiz { white-space: pre-wrap; overflow-wrap: anywhere; margin: 0; font-size: 13px; }
.kalk-mailpanel-titel { margin: 12px 0 4px; font-size: 12px; color: var(--kalk-grau); text-transform: uppercase; letter-spacing: .03em; }
.kalk-mailpanel .vt-mail { max-width: none; font-size: 13px; }
@media (min-width: 1600px) {
  .kalk-mit-mail:has(> .kalk-mailpanel.ist-offen) { display: grid; grid-template-columns: minmax(0, 1fr) clamp(360px, 30%, 560px);
    gap: 16px; align-items: start; }
  .kalk-mit-mail > .kalk-mailpanel.ist-offen { order: 0; margin: 0; position: sticky; top: 76px;
    max-height: calc(100vh - 76px - 96px); display: flex; flex-direction: column; }
  .kalk-mailpanel.ist-offen .kalk-mailpanel-inhalt { max-height: none; flex: 1 1 auto; min-height: 0; }
}
/* Die Regel „unter 1800 px kein Kurzname in der Werkstoffzelle" misst das
   FENSTER. Mit offener Mail-Spalte ist die TABELLE bei 1920 px so schmal wie
   sonst bei 1366 — der Kurzname lag über der Nummer (Bildschirmfoto N6,
   29.09.2026). Breit genug wird sie erst ab 2400 px Fenster (Spalte 560 px). */
@media (min-width: 1600px) and (max-width: 2399px) {
  .kalk-mit-mail:has(> .kalk-mailpanel.ist-offen) .kalk-kurzname { display: none; }
}

/* ═══ K2 (28.09.2026): unlesbare Eingabe — das Feld behält den getippten Text,
   wird rot, der Hinweis steht direkt darunter (über der nächsten Zeile, damit die
   Tabelle nicht springt). Nichts verschwindet. */
.kalk-seite input[aria-invalid="true"], .kalk-seite input.kalk-zelle[aria-invalid="true"] {
  border-color: var(--kalk-err); background: var(--kalk-err-bg); color: var(--kalk-err); }
.kalk-seite td:has(> .kalk-feldfehler), .kalk-seite td:has(.kalk-mitpunkt > .kalk-feldfehler),
.kalk-seite .kalk-feld:has(.kalk-feldfehler), .kalk-seite .kalk-wert-paar:has(.kalk-feldfehler) { position: relative; }
/* ⚠ Die Tabellenzellen schneiden ab (`overflow: hidden` für die Auslassungspunkte) —
   der Hinweis stand im DOM und war auf dem Bildschirm UNSICHTBAR (gemessen am
   Screenshot der Menschen-Probe, 28.09.2026). Eine Zelle mit Hinweis lässt ihn
   überstehen; er legt sich über die Zeile darunter (die „Neue Position"-Zeile
   folgt immer, der Umschlag schneidet ihn also nicht). */
.kalk-tabelle td:has(.kalk-feldfehler) { overflow: visible; }
.kalk-feldfehler { position: absolute; left: 0; top: 100%; z-index: 6; margin-top: 2px; white-space: nowrap;
  font-size: 12px; line-height: 14px; padding: 2px 5px; border-radius: 4px; font-weight: 500;
  background: var(--kalk-err-bg); color: var(--kalk-err); border: 1px solid var(--kalk-err); pointer-events: none; }
#kalk-eingabefehler .kalk-link { margin-left: 6px; }

/* Seitenleiste „Früher angeboten" (F2), Dialoge */
.kalk-leiste { position: fixed; right: 0; top: 0; bottom: 0; width: 28rem; max-width: 100vw; background: var(--kalk-weiss); border-left: 1px solid var(--kalk-linie);
  box-shadow: var(--schatten-hebt); z-index: 50; padding: 16px 24px; overflow: auto; }
.kalk-leiste-kopf { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; }
.kalk-frueher-inhalt h3 { display: none; }
.kalk-frueher-inhalt h4 { margin: 12px 0 4px; font-size: 12px; color: var(--kalk-grau); text-transform: uppercase; letter-spacing: .03em; }
.kalk-frueher-suche input, .kalk-frueher-suche select { width: auto; min-height: 0; height: 30px; padding: 0 6px; font-size: 14px; margin: 0; appearance: none; background-image: none; }
.kalk-frueher-tabelle { font-size: 12px; }
.kalk-frueher-tabelle td, .kalk-frueher-tabelle th { padding: 2px 4px; height: auto; white-space: nowrap; }
.kalk-uebernehmen button { padding: 0 4px; min-height: 24px; }
.kalk-fremdkunde { color: var(--kalk-grau); }
.kalk-dialog { border: 1px solid var(--kalk-linie); border-radius: 8px; padding: 24px; max-width: 36rem; width: calc(100% - 32px); box-shadow: var(--schatten-hebt); color: var(--kalk-text); font-size: 14px; }
.kalk-dialog::backdrop { background: rgba(0,0,0,.35); }
.kalk-dialog h3 { margin: 0 0 8px; font-size: 16px; }
.kalk-dialog-breit { max-width: 60rem; }
.kalk-dialog-aktionen { display: flex; gap: 8px; margin: 16px 0 0; }
.kalk-dialog-form .kalk-kunde { display: block; }
.kalk-meta-zeile { font-size: 13px; color: var(--kalk-grau); margin: 0 0 8px; }
.kalk-vorschlaege-start { list-style: none; padding: 0; margin: 8px 0 0; }
.kalk-vorschlag-knopf, button[type="submit"].kalk-vorschlag-knopf { display: block; width: 100%; text-align: left; padding: 6px 10px; background: var(--kalk-weiss); border: 1px solid var(--kalk-linie); border-radius: 6px; margin-bottom: 4px; font: inherit; font-size: 14px; cursor: pointer; min-height: 0; color: var(--kalk-text); }
.kalk-vorschlag-knopf:hover, button[type="submit"].kalk-vorschlag-knopf:hover { background: var(--kalk-flaeche); }
.kalk-vorschlag-knopf .meta { display: block; font-size: 12px; color: var(--kalk-grau); }
.kalk-hilfe-tabelle td, .kalk-hilfe-tabelle th { height: auto; padding: 2px 8px; }
.kalk-verlauf { list-style: none; padding: 0; margin: 0; }
.kalk-verlauf li { padding: 2px 0; border-bottom: 1px solid var(--kalk-linie); }
.kalk-inline-form { display: inline-flex; gap: 4px; align-items: center; margin: 0; }
.kalk-antwort { padding: 16px; margin-bottom: 12px; }
.kalk-antwort-text { width: 100%; font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: 13px; }
.kalk-antwort-betreff { flex: 1; }
.kalk-antwort-bereich { margin-bottom: 12px; }

/* Andere Seiten des Rechners (Liste, Anlegen, Vorlagen) — unverändert */
.kalk-filter-zusatz input { width: auto; }
.kalk-neu-form label { display: block; margin-top: var(--a3); }
.kalk-vorlage-form label { display: block; margin-top: var(--a2); }
.kalk-vorlage-form textarea { width: 100%; font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: var(--groesse-xs); }
.kalk-seitenkopf .dazu { display: flex; flex-wrap: wrap; gap: var(--a2); align-items: center; }

/* Kundenfeld des Rechners (G3): Trefferliste breit genug für Name · Nr. · Ort. */
.kalk-kunde { display: inline-block; }
.kalk-neu-form .kalk-kunde { display: block; }
.kalk-kunde .vorschlaege { min-width: 340px; right: auto; max-height: min(50vh, 420px); overflow-y: auto; }
.kalk-treffer { list-style: none; margin: var(--a2) 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--a2); }

/* ══ V2 Paket F (28.09.2026): Block „Fracht und Zusatzkosten" unter der Positionstabelle ══ */
.kalk-zusatz { padding: 12px 16px; margin-bottom: 16px; }
.kalk-zusatz-kopf { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; margin-bottom: 8px; }
.kalk-zusatz-titel { margin: 0; font-size: 16px; font-weight: 700; color: var(--kalk-text); }
.kalk-zusatz-ort { display: inline-flex; align-items: center; gap: 4px; }
.kalk-seite .kalk-zusatz .kalk-zelle { display: inline-block; width: auto; height: 28px; line-height: 26px; }
.kalk-seite .kalk-zusatz input.kalk-plz { width: 5.5em; }
.kalk-seite .kalk-zusatz input.kalk-ort { width: 10em; }
.kalk-seite .kalk-zusatz input.kalk-land { width: 3.2em; }
.kalk-zusatz-abholung { font-size: 13px; font-weight: 600; color: var(--kalk-man); }
/* Passt ohne waagrechten Überlauf in 1.043 px (1366 mit Seitenleiste): Wahlschalter
   untereinander, Quelle darf umbrechen. Gemessen 28.09.2026: in einer Zeile ragte die
   Quelle 300 px über den Rand — ein Tab dorthin schob die Seite waagrecht, und der
   nächste Mausklick oben traf danach ein anderes Element (Abschluss ging ins Leere). */
.kalk-zusatz-tabelle { width: 100%; border-collapse: collapse; font-size: 13px; table-layout: auto; }
.kalk-zusatz-tabelle th { text-align: left; font-size: 12px; font-weight: 700; color: var(--kalk-grau); padding: 4px 6px; border-bottom: 1px solid var(--kalk-linie); white-space: nowrap; }
.kalk-zusatz-tabelle th.kalk-num { text-align: right; }
.kalk-zusatz-tabelle td { padding: 4px 6px; border-bottom: 1px solid var(--kalk-linie); vertical-align: middle; }
.kalk-zusatz-art { font-weight: 600; color: var(--kalk-text); white-space: nowrap; width: 6em; }
.kalk-seite .kalk-zusatz input.kalk-zusatz-bezeichnung { width: 100%; min-width: 8em; }
.kalk-seite .kalk-zusatz input.kalk-fracht-betrag, .kalk-seite .kalk-zusatz input.kalk-zusatz-preis { width: 6em; }
.kalk-zusatz-quelle { white-space: normal; }
.kalk-zusatz-quelle .kalk-tarif { display: flex; flex-wrap: wrap; margin-left: 0; gap: 2px 6px; }
.kalk-seite .kalk-zusatz-quelle select.kalk-frachtfuehrer { max-width: 11em; }
.kalk-zusatz-quelle .kalk-tarif-hinweis { white-space: normal; }
.kalk-zusatz-wie { white-space: nowrap; }
.kalk-wahl { display: flex; align-items: center; gap: 4px; margin: 0; font-size: 13px; color: var(--kalk-text); cursor: pointer; line-height: 20px; }
.kalk-wahl input { width: auto; min-height: 0; margin: 0; }
.kalk-verteilung { display: block; margin-left: 24px; font-size: 12px; }
.kalk-verteilung > summary { cursor: pointer; color: var(--kalk-grau); list-style: none; display: inline; }
.kalk-verteilung > summary::-webkit-details-marker { display: none; }
.kalk-verteilung[open] > summary { margin-right: 4px; }
.kalk-zusatz-zeile[data-wie="eigene"] td { background: var(--kalk-vk); }
.kalk-zusatz-entfaellt td { color: var(--kalk-grau); text-decoration: line-through; }
.kalk-zusatz-entfaellt td .kalk-zusatz-hinweis { text-decoration: none; display: inline-block; margin-left: 6px; }
.kalk-zusatz-fuss { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 10px; }
.kalk-chips { display: inline-flex; flex-wrap: wrap; gap: 4px; margin-left: 4px; }
.kalk-chip { border: 1px solid var(--kalk-linie); background: var(--kalk-weiss); color: var(--kalk-text); border-radius: 999px; padding: 2px 10px; font: inherit; font-size: 12px; min-height: 0; cursor: pointer; }
.kalk-chip:hover { border-color: var(--kalk-grau); }
.kalk-zusatz-summe { margin-left: auto; }
/* Einkauf-Gruppe: Frachtanteil und EK inkl. Kosten je Position */
.kalk-tabelle td.kalk-fracht-anteil, .kalk-tabelle td.kalk-ek-inkl { font-variant-numeric: tabular-nums; text-align: right; }
.kalk-ek-inkl-knopf { background: none; border: none; padding: 0; margin: 0; min-height: 0; font: inherit; color: var(--kalk-text); font-weight: 600; cursor: pointer; font-variant-numeric: tabular-nums; }
.kalk-ek-inkl-knopf:hover { text-decoration: underline dotted; }
.kalk-ek-inkl-knopf .kalk-einheit { font-weight: 400; font-size: 11px; color: var(--kalk-grau); }
/* B4: negative Werte immer rot, nie grün */
.kalk-seite input.kalk-negativ { color: var(--kalk-err); font-weight: 700; }
.kalk-tabelle tr.kalk-kostenwarnung td { height: auto; padding: 4px 8px; background: var(--kalk-warn-bg); white-space: normal; }
.kalk-als-eigene { margin-left: 8px; }

/* V2 B2: Schalter „Alternative" in der Nr-Zelle; eine Alternativzeile ist deutlich markiert */
.kalk-nr-stapel { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 2px; line-height: 14px; }
.kalk-alt-schalter { border: 1px solid var(--kalk-linie); background: var(--kalk-weiss); color: var(--kalk-grau); border-radius: 4px;
  font: inherit; font-size: 11px; font-weight: 700; line-height: 12px; padding: 0 4px; margin: 0; min-height: 0; cursor: pointer; }
.kalk-alt-schalter[aria-pressed="true"] { background: var(--kalk-warn-bg); border-color: var(--kalk-punkt-warn); color: var(--kalk-warn); }
.kalk-tabelle tr.kalk-alternativ td { font-style: italic; }
.kalk-tabelle tr.kalk-alternativ td:first-child { box-shadow: inset 3px 0 0 var(--kalk-punkt-warn); }

/* ═══ W1 (30.09.2026): Hinweis zur Kundenmail unter „Zuständig" ═══
   Grau = Schalter aus, Mail liegt woanders; gelb = Weiterleitung fehlgeschlagen
   (mit Knopf). Das Wort trägt die Aussage, nicht die Farbe. */
.mail-hinweis { display: flex; flex-wrap: wrap; gap: var(--a2); align-items: center; margin-top: var(--a2);
  font-size: var(--groesse-s); }
.mail-hinweis-grau, .mail-hinweis-info { color: var(--text-3); }
.mail-hinweis-form { margin: 0; }
